blob: bd0b30454590df23c43641f702f168a4c3612a7e [file] [log] [blame]
Henrik Boströmbd9e4a92021-03-22 12:24:30 +01001/*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "test/mappable_native_buffer.h"
12
13#include "absl/algorithm/container.h"
14#include "api/video/i420_buffer.h"
15#include "api/video/nv12_buffer.h"
16#include "api/video/video_frame.h"
17#include "api/video/video_rotation.h"
18#include "common_video/include/video_frame_buffer.h"
19#include "rtc_base/checks.h"
20
21namespace webrtc {
22namespace test {
23
24namespace {
25
26class NV12BufferWithDidConvertToI420 : public NV12Buffer {
27 public:
28 NV12BufferWithDidConvertToI420(int width, int height)
29 : NV12Buffer(width, height), did_convert_to_i420_(false) {}
30
31 bool did_convert_to_i420() const { return did_convert_to_i420_; }
32
33 rtc::scoped_refptr<I420BufferInterface> ToI420() override {
34 did_convert_to_i420_ = true;
35 return NV12Buffer::ToI420();
36 }
37
38 private:
39 bool did_convert_to_i420_;
40};
41
42} // namespace
43
44VideoFrame CreateMappableNativeFrame(int64_t ntp_time_ms,
45 VideoFrameBuffer::Type mappable_type,
46 int width,
47 int height) {
Tommi87f70902021-04-27 14:43:08 +020048 VideoFrame frame =
49 VideoFrame::Builder()
50 .set_video_frame_buffer(rtc::make_ref_counted<MappableNativeBuffer>(
51 mappable_type, width, height))
52 .set_timestamp_rtp(99)
53 .set_timestamp_ms(99)
54 .set_rotation(kVideoRotation_0)
55 .build();
Henrik Boströmbd9e4a92021-03-22 12:24:30 +010056 frame.set_ntp_time_ms(ntp_time_ms);
57 return frame;
58}
59
60rtc::scoped_refptr<MappableNativeBuffer> GetMappableNativeBufferFromVideoFrame(
61 const VideoFrame& frame) {
62 return static_cast<MappableNativeBuffer*>(frame.video_frame_buffer().get());
63}
64
65MappableNativeBuffer::ScaledBuffer::ScaledBuffer(
66 rtc::scoped_refptr<MappableNativeBuffer> parent,
67 int width,
68 int height)
69 : parent_(std::move(parent)), width_(width), height_(height) {}
70
71MappableNativeBuffer::ScaledBuffer::~ScaledBuffer() {}
72
73rtc::scoped_refptr<VideoFrameBuffer>
74MappableNativeBuffer::ScaledBuffer::CropAndScale(int offset_x,
75 int offset_y,
76 int crop_width,
77 int crop_height,
78 int scaled_width,
79 int scaled_height) {
Tommi87f70902021-04-27 14:43:08 +020080 return rtc::make_ref_counted<ScaledBuffer>(parent_, scaled_width,
81 scaled_height);
Henrik Boströmbd9e4a92021-03-22 12:24:30 +010082}
83
84rtc::scoped_refptr<I420BufferInterface>
85MappableNativeBuffer::ScaledBuffer::ToI420() {
86 return parent_->GetOrCreateMappedBuffer(width_, height_)->ToI420();
87}
88
89rtc::scoped_refptr<VideoFrameBuffer>
90MappableNativeBuffer::ScaledBuffer::GetMappedFrameBuffer(
91 rtc::ArrayView<VideoFrameBuffer::Type> types) {
92 if (absl::c_find(types, parent_->mappable_type_) == types.end())
93 return nullptr;
94 return parent_->GetOrCreateMappedBuffer(width_, height_);
95}
96
97MappableNativeBuffer::MappableNativeBuffer(VideoFrameBuffer::Type mappable_type,
98 int width,
99 int height)
100 : mappable_type_(mappable_type), width_(width), height_(height) {
101 RTC_DCHECK(mappable_type_ == VideoFrameBuffer::Type::kI420 ||
102 mappable_type_ == VideoFrameBuffer::Type::kNV12);
103}
104
105MappableNativeBuffer::~MappableNativeBuffer() {}
106
107rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::CropAndScale(
108 int offset_x,
109 int offset_y,
110 int crop_width,
111 int crop_height,
112 int scaled_width,
113 int scaled_height) {
114 return FullSizeBuffer()->CropAndScale(
115 offset_x, offset_y, crop_width, crop_height, scaled_width, scaled_height);
116}
117
118rtc::scoped_refptr<I420BufferInterface> MappableNativeBuffer::ToI420() {
119 return FullSizeBuffer()->ToI420();
120}
121
122rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::GetMappedFrameBuffer(
123 rtc::ArrayView<VideoFrameBuffer::Type> types) {
124 return FullSizeBuffer()->GetMappedFrameBuffer(types);
125}
126
127std::vector<rtc::scoped_refptr<VideoFrameBuffer>>
128MappableNativeBuffer::GetMappedFramedBuffers() const {
129 MutexLock lock(&lock_);
130 return mapped_buffers_;
131}
132
133bool MappableNativeBuffer::DidConvertToI420() const {
134 if (mappable_type_ != VideoFrameBuffer::Type::kNV12)
135 return false;
136 MutexLock lock(&lock_);
137 for (auto& mapped_buffer : mapped_buffers_) {
138 if (static_cast<NV12BufferWithDidConvertToI420*>(mapped_buffer.get())
139 ->did_convert_to_i420()) {
140 return true;
141 }
142 }
143 return false;
144}
145
146rtc::scoped_refptr<MappableNativeBuffer::ScaledBuffer>
147MappableNativeBuffer::FullSizeBuffer() {
Tommi87f70902021-04-27 14:43:08 +0200148 return rtc::make_ref_counted<ScaledBuffer>(this, width_, height_);
Henrik Boströmbd9e4a92021-03-22 12:24:30 +0100149}
150
151rtc::scoped_refptr<VideoFrameBuffer>
152MappableNativeBuffer::GetOrCreateMappedBuffer(int width, int height) {
153 MutexLock lock(&lock_);
154 for (auto& mapped_buffer : mapped_buffers_) {
155 if (mapped_buffer->width() == width && mapped_buffer->height() == height) {
156 return mapped_buffer;
157 }
158 }
159 rtc::scoped_refptr<VideoFrameBuffer> mapped_buffer;
160 switch (mappable_type_) {
161 case VideoFrameBuffer::Type::kI420: {
162 rtc::scoped_refptr<I420Buffer> i420_buffer =
163 I420Buffer::Create(width, height);
164 I420Buffer::SetBlack(i420_buffer);
165 mapped_buffer = i420_buffer;
166 break;
167 }
168 case VideoFrameBuffer::Type::kNV12: {
Tommi87f70902021-04-27 14:43:08 +0200169 auto nv12_buffer =
170 rtc::make_ref_counted<NV12BufferWithDidConvertToI420>(width, height);
Henrik Boströmbd9e4a92021-03-22 12:24:30 +0100171 nv12_buffer->InitializeData();
Tommi87f70902021-04-27 14:43:08 +0200172 mapped_buffer = std::move(nv12_buffer);
Henrik Boströmbd9e4a92021-03-22 12:24:30 +0100173 break;
174 }
175 default:
176 RTC_NOTREACHED();
177 }
178 mapped_buffers_.push_back(mapped_buffer);
179 return mapped_buffer;
180}
181
182} // namespace test
183} // namespace webrtc