blob: 67db8eb247961652ea190b6aa6e54388099684b8 [file] [log] [blame]
Henrik Boströmbd9e4a92021-03-22 11:24:301/*
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 12:43:0848 VideoFrame frame =
49 VideoFrame::Builder()
50 .set_video_frame_buffer(rtc::make_ref_counted<MappableNativeBuffer>(
51 mappable_type, width, height))
Per K0fa90882024-03-13 08:52:4152 .set_rtp_timestamp(99)
Tommi87f70902021-04-27 12:43:0853 .set_timestamp_ms(99)
54 .set_rotation(kVideoRotation_0)
55 .build();
Henrik Boströmbd9e4a92021-03-22 11:24:3056 frame.set_ntp_time_ms(ntp_time_ms);
57 return frame;
58}
59
60rtc::scoped_refptr<MappableNativeBuffer> GetMappableNativeBufferFromVideoFrame(
61 const VideoFrame& frame) {
Niels Möller93b20892022-01-13 12:50:2062 return rtc::scoped_refptr<MappableNativeBuffer>(
63 static_cast<MappableNativeBuffer*>(frame.video_frame_buffer().get()));
Henrik Boströmbd9e4a92021-03-22 11:24:3064}
65
66MappableNativeBuffer::ScaledBuffer::ScaledBuffer(
67 rtc::scoped_refptr<MappableNativeBuffer> parent,
68 int width,
69 int height)
70 : parent_(std::move(parent)), width_(width), height_(height) {}
71
72MappableNativeBuffer::ScaledBuffer::~ScaledBuffer() {}
73
74rtc::scoped_refptr<VideoFrameBuffer>
75MappableNativeBuffer::ScaledBuffer::CropAndScale(int offset_x,
76 int offset_y,
77 int crop_width,
78 int crop_height,
79 int scaled_width,
80 int scaled_height) {
Tommi87f70902021-04-27 12:43:0881 return rtc::make_ref_counted<ScaledBuffer>(parent_, scaled_width,
82 scaled_height);
Henrik Boströmbd9e4a92021-03-22 11:24:3083}
84
85rtc::scoped_refptr<I420BufferInterface>
86MappableNativeBuffer::ScaledBuffer::ToI420() {
87 return parent_->GetOrCreateMappedBuffer(width_, height_)->ToI420();
88}
89
90rtc::scoped_refptr<VideoFrameBuffer>
91MappableNativeBuffer::ScaledBuffer::GetMappedFrameBuffer(
92 rtc::ArrayView<VideoFrameBuffer::Type> types) {
93 if (absl::c_find(types, parent_->mappable_type_) == types.end())
94 return nullptr;
95 return parent_->GetOrCreateMappedBuffer(width_, height_);
96}
97
98MappableNativeBuffer::MappableNativeBuffer(VideoFrameBuffer::Type mappable_type,
99 int width,
100 int height)
101 : mappable_type_(mappable_type), width_(width), height_(height) {
102 RTC_DCHECK(mappable_type_ == VideoFrameBuffer::Type::kI420 ||
103 mappable_type_ == VideoFrameBuffer::Type::kNV12);
104}
105
106MappableNativeBuffer::~MappableNativeBuffer() {}
107
108rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::CropAndScale(
109 int offset_x,
110 int offset_y,
111 int crop_width,
112 int crop_height,
113 int scaled_width,
114 int scaled_height) {
115 return FullSizeBuffer()->CropAndScale(
116 offset_x, offset_y, crop_width, crop_height, scaled_width, scaled_height);
117}
118
119rtc::scoped_refptr<I420BufferInterface> MappableNativeBuffer::ToI420() {
120 return FullSizeBuffer()->ToI420();
121}
122
123rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::GetMappedFrameBuffer(
124 rtc::ArrayView<VideoFrameBuffer::Type> types) {
125 return FullSizeBuffer()->GetMappedFrameBuffer(types);
126}
127
128std::vector<rtc::scoped_refptr<VideoFrameBuffer>>
129MappableNativeBuffer::GetMappedFramedBuffers() const {
130 MutexLock lock(&lock_);
131 return mapped_buffers_;
132}
133
134bool MappableNativeBuffer::DidConvertToI420() const {
135 if (mappable_type_ != VideoFrameBuffer::Type::kNV12)
136 return false;
137 MutexLock lock(&lock_);
138 for (auto& mapped_buffer : mapped_buffers_) {
139 if (static_cast<NV12BufferWithDidConvertToI420*>(mapped_buffer.get())
140 ->did_convert_to_i420()) {
141 return true;
142 }
143 }
144 return false;
145}
146
147rtc::scoped_refptr<MappableNativeBuffer::ScaledBuffer>
148MappableNativeBuffer::FullSizeBuffer() {
Niels Möller93b20892022-01-13 12:50:20149 return rtc::make_ref_counted<ScaledBuffer>(
150 rtc::scoped_refptr<MappableNativeBuffer>(this), width_, height_);
Henrik Boströmbd9e4a92021-03-22 11:24:30151}
152
153rtc::scoped_refptr<VideoFrameBuffer>
154MappableNativeBuffer::GetOrCreateMappedBuffer(int width, int height) {
155 MutexLock lock(&lock_);
156 for (auto& mapped_buffer : mapped_buffers_) {
157 if (mapped_buffer->width() == width && mapped_buffer->height() == height) {
158 return mapped_buffer;
159 }
160 }
161 rtc::scoped_refptr<VideoFrameBuffer> mapped_buffer;
162 switch (mappable_type_) {
163 case VideoFrameBuffer::Type::kI420: {
164 rtc::scoped_refptr<I420Buffer> i420_buffer =
165 I420Buffer::Create(width, height);
Niels Möller3c4f9c12022-04-22 09:14:34166 I420Buffer::SetBlack(i420_buffer.get());
Henrik Boströmbd9e4a92021-03-22 11:24:30167 mapped_buffer = i420_buffer;
168 break;
169 }
170 case VideoFrameBuffer::Type::kNV12: {
Tommi87f70902021-04-27 12:43:08171 auto nv12_buffer =
172 rtc::make_ref_counted<NV12BufferWithDidConvertToI420>(width, height);
Henrik Boströmbd9e4a92021-03-22 11:24:30173 nv12_buffer->InitializeData();
Tommi87f70902021-04-27 12:43:08174 mapped_buffer = std::move(nv12_buffer);
Henrik Boströmbd9e4a92021-03-22 11:24:30175 break;
176 }
177 default:
Artem Titovd3251962021-11-15 15:57:07178 RTC_DCHECK_NOTREACHED();
Henrik Boströmbd9e4a92021-03-22 11:24:30179 }
180 mapped_buffers_.push_back(mapped_buffer);
181 return mapped_buffer;
182}
183
184} // namespace test
185} // namespace webrtc