• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
21 namespace webrtc {
22 namespace test {
23 
24 namespace {
25 
26 class NV12BufferWithDidConvertToI420 : public NV12Buffer {
27  public:
NV12BufferWithDidConvertToI420(int width,int height)28   NV12BufferWithDidConvertToI420(int width, int height)
29       : NV12Buffer(width, height), did_convert_to_i420_(false) {}
30 
did_convert_to_i420() const31   bool did_convert_to_i420() const { return did_convert_to_i420_; }
32 
ToI420()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 
CreateMappableNativeFrame(int64_t ntp_time_ms,VideoFrameBuffer::Type mappable_type,int width,int height)44 VideoFrame CreateMappableNativeFrame(int64_t ntp_time_ms,
45                                      VideoFrameBuffer::Type mappable_type,
46                                      int width,
47                                      int height) {
48   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();
56   frame.set_ntp_time_ms(ntp_time_ms);
57   return frame;
58 }
59 
GetMappableNativeBufferFromVideoFrame(const VideoFrame & frame)60 rtc::scoped_refptr<MappableNativeBuffer> GetMappableNativeBufferFromVideoFrame(
61     const VideoFrame& frame) {
62   return rtc::scoped_refptr<MappableNativeBuffer>(
63       static_cast<MappableNativeBuffer*>(frame.video_frame_buffer().get()));
64 }
65 
ScaledBuffer(rtc::scoped_refptr<MappableNativeBuffer> parent,int width,int height)66 MappableNativeBuffer::ScaledBuffer::ScaledBuffer(
67     rtc::scoped_refptr<MappableNativeBuffer> parent,
68     int width,
69     int height)
70     : parent_(std::move(parent)), width_(width), height_(height) {}
71 
~ScaledBuffer()72 MappableNativeBuffer::ScaledBuffer::~ScaledBuffer() {}
73 
74 rtc::scoped_refptr<VideoFrameBuffer>
CropAndScale(int offset_x,int offset_y,int crop_width,int crop_height,int scaled_width,int scaled_height)75 MappableNativeBuffer::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) {
81   return rtc::make_ref_counted<ScaledBuffer>(parent_, scaled_width,
82                                              scaled_height);
83 }
84 
85 rtc::scoped_refptr<I420BufferInterface>
ToI420()86 MappableNativeBuffer::ScaledBuffer::ToI420() {
87   return parent_->GetOrCreateMappedBuffer(width_, height_)->ToI420();
88 }
89 
90 rtc::scoped_refptr<VideoFrameBuffer>
GetMappedFrameBuffer(rtc::ArrayView<VideoFrameBuffer::Type> types)91 MappableNativeBuffer::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 
MappableNativeBuffer(VideoFrameBuffer::Type mappable_type,int width,int height)98 MappableNativeBuffer::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 
~MappableNativeBuffer()106 MappableNativeBuffer::~MappableNativeBuffer() {}
107 
CropAndScale(int offset_x,int offset_y,int crop_width,int crop_height,int scaled_width,int scaled_height)108 rtc::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 
ToI420()119 rtc::scoped_refptr<I420BufferInterface> MappableNativeBuffer::ToI420() {
120   return FullSizeBuffer()->ToI420();
121 }
122 
GetMappedFrameBuffer(rtc::ArrayView<VideoFrameBuffer::Type> types)123 rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::GetMappedFrameBuffer(
124     rtc::ArrayView<VideoFrameBuffer::Type> types) {
125   return FullSizeBuffer()->GetMappedFrameBuffer(types);
126 }
127 
128 std::vector<rtc::scoped_refptr<VideoFrameBuffer>>
GetMappedFramedBuffers() const129 MappableNativeBuffer::GetMappedFramedBuffers() const {
130   MutexLock lock(&lock_);
131   return mapped_buffers_;
132 }
133 
DidConvertToI420() const134 bool 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 
147 rtc::scoped_refptr<MappableNativeBuffer::ScaledBuffer>
FullSizeBuffer()148 MappableNativeBuffer::FullSizeBuffer() {
149   return rtc::make_ref_counted<ScaledBuffer>(
150       rtc::scoped_refptr<MappableNativeBuffer>(this), width_, height_);
151 }
152 
153 rtc::scoped_refptr<VideoFrameBuffer>
GetOrCreateMappedBuffer(int width,int height)154 MappableNativeBuffer::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);
166       I420Buffer::SetBlack(i420_buffer.get());
167       mapped_buffer = i420_buffer;
168       break;
169     }
170     case VideoFrameBuffer::Type::kNV12: {
171       auto nv12_buffer =
172           rtc::make_ref_counted<NV12BufferWithDidConvertToI420>(width, height);
173       nv12_buffer->InitializeData();
174       mapped_buffer = std::move(nv12_buffer);
175       break;
176     }
177     default:
178       RTC_DCHECK_NOTREACHED();
179   }
180   mapped_buffers_.push_back(mapped_buffer);
181   return mapped_buffer;
182 }
183 
184 }  // namespace test
185 }  // namespace webrtc
186