video_frame_buffer.cc (12825B)
1 /* 2 * Copyright (c) 2015 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 #include "common_video/include/video_frame_buffer.h" 11 12 #include <cstdint> 13 #include <functional> 14 15 #include "api/make_ref_counted.h" 16 #include "api/scoped_refptr.h" 17 #include "api/video/i420_buffer.h" 18 #include "api/video/video_frame_buffer.h" 19 #include "rtc_base/checks.h" 20 #include "rtc_base/ref_counted_object.h" 21 #include "third_party/libyuv/include/libyuv/convert.h" 22 23 namespace webrtc { 24 25 namespace { 26 27 // Template to implement a wrapped buffer for a I4??BufferInterface. 28 template <typename Base> 29 class WrappedYuvBuffer : public Base { 30 public: 31 WrappedYuvBuffer(int width, 32 int height, 33 const uint8_t* y_plane, 34 int y_stride, 35 const uint8_t* u_plane, 36 int u_stride, 37 const uint8_t* v_plane, 38 int v_stride, 39 std::function<void()> no_longer_used) 40 : width_(width), 41 height_(height), 42 y_plane_(y_plane), 43 u_plane_(u_plane), 44 v_plane_(v_plane), 45 y_stride_(y_stride), 46 u_stride_(u_stride), 47 v_stride_(v_stride), 48 no_longer_used_cb_(no_longer_used) {} 49 50 ~WrappedYuvBuffer() override { no_longer_used_cb_(); } 51 52 int width() const override { return width_; } 53 54 int height() const override { return height_; } 55 56 const uint8_t* DataY() const override { return y_plane_; } 57 58 const uint8_t* DataU() const override { return u_plane_; } 59 60 const uint8_t* DataV() const override { return v_plane_; } 61 62 int StrideY() const override { return y_stride_; } 63 64 int StrideU() const override { return u_stride_; } 65 66 int StrideV() const override { return v_stride_; } 67 68 private: 69 friend class RefCountedObject<WrappedYuvBuffer>; 70 71 const int width_; 72 const int height_; 73 const uint8_t* const y_plane_; 74 const uint8_t* const u_plane_; 75 const uint8_t* const v_plane_; 76 const int y_stride_; 77 const int u_stride_; 78 const int v_stride_; 79 std::function<void()> no_longer_used_cb_; 80 }; 81 82 // Template to implement a wrapped buffer for a I4??BufferInterface. 83 template <typename BaseWithA> 84 class WrappedYuvaBuffer : public WrappedYuvBuffer<BaseWithA> { 85 public: 86 WrappedYuvaBuffer(int width, 87 int height, 88 const uint8_t* y_plane, 89 int y_stride, 90 const uint8_t* u_plane, 91 int u_stride, 92 const uint8_t* v_plane, 93 int v_stride, 94 const uint8_t* a_plane, 95 int a_stride, 96 std::function<void()> no_longer_used) 97 : WrappedYuvBuffer<BaseWithA>(width, 98 height, 99 y_plane, 100 y_stride, 101 u_plane, 102 u_stride, 103 v_plane, 104 v_stride, 105 no_longer_used), 106 a_plane_(a_plane), 107 a_stride_(a_stride) {} 108 109 const uint8_t* DataA() const override { return a_plane_; } 110 int StrideA() const override { return a_stride_; } 111 112 private: 113 const uint8_t* const a_plane_; 114 const int a_stride_; 115 }; 116 117 class I444BufferBase : public I444BufferInterface { 118 public: 119 scoped_refptr<I420BufferInterface> ToI420() final; 120 }; 121 122 scoped_refptr<I420BufferInterface> I444BufferBase::ToI420() { 123 scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(width(), height()); 124 libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), 125 i420_buffer->MutableDataY(), i420_buffer->StrideY(), 126 i420_buffer->MutableDataU(), i420_buffer->StrideU(), 127 i420_buffer->MutableDataV(), i420_buffer->StrideV(), 128 width(), height()); 129 return i420_buffer; 130 } 131 132 class I422BufferBase : public I422BufferInterface { 133 public: 134 scoped_refptr<I420BufferInterface> ToI420() final; 135 }; 136 137 scoped_refptr<I420BufferInterface> I422BufferBase::ToI420() { 138 scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(width(), height()); 139 libyuv::I422ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), 140 i420_buffer->MutableDataY(), i420_buffer->StrideY(), 141 i420_buffer->MutableDataU(), i420_buffer->StrideU(), 142 i420_buffer->MutableDataV(), i420_buffer->StrideV(), 143 width(), height()); 144 return i420_buffer; 145 } 146 147 // Template to implement a wrapped buffer for a PlanarYuv16BBuffer. 148 template <typename Base> 149 class WrappedYuv16BBuffer : public Base { 150 public: 151 WrappedYuv16BBuffer(int width, 152 int height, 153 const uint16_t* y_plane, 154 int y_stride, 155 const uint16_t* u_plane, 156 int u_stride, 157 const uint16_t* v_plane, 158 int v_stride, 159 std::function<void()> no_longer_used) 160 : width_(width), 161 height_(height), 162 y_plane_(y_plane), 163 u_plane_(u_plane), 164 v_plane_(v_plane), 165 y_stride_(y_stride), 166 u_stride_(u_stride), 167 v_stride_(v_stride), 168 no_longer_used_cb_(no_longer_used) {} 169 170 ~WrappedYuv16BBuffer() override { no_longer_used_cb_(); } 171 172 int width() const override { return width_; } 173 174 int height() const override { return height_; } 175 176 const uint16_t* DataY() const override { return y_plane_; } 177 178 const uint16_t* DataU() const override { return u_plane_; } 179 180 const uint16_t* DataV() const override { return v_plane_; } 181 182 int StrideY() const override { return y_stride_; } 183 184 int StrideU() const override { return u_stride_; } 185 186 int StrideV() const override { return v_stride_; } 187 188 private: 189 friend class RefCountedObject<WrappedYuv16BBuffer>; 190 191 const int width_; 192 const int height_; 193 const uint16_t* const y_plane_; 194 const uint16_t* const u_plane_; 195 const uint16_t* const v_plane_; 196 const int y_stride_; 197 const int u_stride_; 198 const int v_stride_; 199 std::function<void()> no_longer_used_cb_; 200 }; 201 202 class I010BufferBase : public I010BufferInterface { 203 public: 204 scoped_refptr<I420BufferInterface> ToI420() final; 205 }; 206 207 scoped_refptr<I420BufferInterface> I010BufferBase::ToI420() { 208 scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(width(), height()); 209 libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), 210 i420_buffer->MutableDataY(), i420_buffer->StrideY(), 211 i420_buffer->MutableDataU(), i420_buffer->StrideU(), 212 i420_buffer->MutableDataV(), i420_buffer->StrideV(), 213 width(), height()); 214 return i420_buffer; 215 } 216 217 class I210BufferBase : public I210BufferInterface { 218 public: 219 scoped_refptr<I420BufferInterface> ToI420() final; 220 }; 221 222 scoped_refptr<I420BufferInterface> I210BufferBase::ToI420() { 223 scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(width(), height()); 224 libyuv::I210ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), 225 i420_buffer->MutableDataY(), i420_buffer->StrideY(), 226 i420_buffer->MutableDataU(), i420_buffer->StrideU(), 227 i420_buffer->MutableDataV(), i420_buffer->StrideV(), 228 width(), height()); 229 return i420_buffer; 230 } 231 232 class I410BufferBase : public I410BufferInterface { 233 public: 234 scoped_refptr<I420BufferInterface> ToI420() final; 235 }; 236 237 scoped_refptr<I420BufferInterface> I410BufferBase::ToI420() { 238 scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(width(), height()); 239 libyuv::I410ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), 240 i420_buffer->MutableDataY(), i420_buffer->StrideY(), 241 i420_buffer->MutableDataU(), i420_buffer->StrideU(), 242 i420_buffer->MutableDataV(), i420_buffer->StrideV(), 243 width(), height()); 244 return i420_buffer; 245 } 246 247 } // namespace 248 249 scoped_refptr<I420BufferInterface> WrapI420Buffer( 250 int width, 251 int height, 252 const uint8_t* y_plane, 253 int y_stride, 254 const uint8_t* u_plane, 255 int u_stride, 256 const uint8_t* v_plane, 257 int v_stride, 258 std::function<void()> no_longer_used) { 259 return scoped_refptr<I420BufferInterface>( 260 make_ref_counted<WrappedYuvBuffer<I420BufferInterface>>( 261 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 262 v_stride, no_longer_used)); 263 } 264 265 scoped_refptr<I420ABufferInterface> WrapI420ABuffer( 266 int width, 267 int height, 268 const uint8_t* y_plane, 269 int y_stride, 270 const uint8_t* u_plane, 271 int u_stride, 272 const uint8_t* v_plane, 273 int v_stride, 274 const uint8_t* a_plane, 275 int a_stride, 276 std::function<void()> no_longer_used) { 277 return scoped_refptr<I420ABufferInterface>( 278 make_ref_counted<WrappedYuvaBuffer<I420ABufferInterface>>( 279 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 280 v_stride, a_plane, a_stride, no_longer_used)); 281 } 282 283 scoped_refptr<I422BufferInterface> WrapI422Buffer( 284 int width, 285 int height, 286 const uint8_t* y_plane, 287 int y_stride, 288 const uint8_t* u_plane, 289 int u_stride, 290 const uint8_t* v_plane, 291 int v_stride, 292 std::function<void()> no_longer_used) { 293 return scoped_refptr<I422BufferBase>( 294 make_ref_counted<WrappedYuvBuffer<I422BufferBase>>( 295 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 296 v_stride, no_longer_used)); 297 } 298 299 scoped_refptr<I444BufferInterface> WrapI444Buffer( 300 int width, 301 int height, 302 const uint8_t* y_plane, 303 int y_stride, 304 const uint8_t* u_plane, 305 int u_stride, 306 const uint8_t* v_plane, 307 int v_stride, 308 std::function<void()> no_longer_used) { 309 return scoped_refptr<I444BufferInterface>( 310 make_ref_counted<WrappedYuvBuffer<I444BufferBase>>( 311 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 312 v_stride, no_longer_used)); 313 } 314 315 scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer( 316 VideoFrameBuffer::Type type, 317 int width, 318 int height, 319 const uint8_t* y_plane, 320 int y_stride, 321 const uint8_t* u_plane, 322 int u_stride, 323 const uint8_t* v_plane, 324 int v_stride, 325 std::function<void()> no_longer_used) { 326 switch (type) { 327 case VideoFrameBuffer::Type::kI420: 328 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride, 329 v_plane, v_stride, no_longer_used); 330 case VideoFrameBuffer::Type::kI422: 331 return WrapI422Buffer(width, height, y_plane, y_stride, u_plane, u_stride, 332 v_plane, v_stride, no_longer_used); 333 case VideoFrameBuffer::Type::kI444: 334 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride, 335 v_plane, v_stride, no_longer_used); 336 default: 337 RTC_CHECK_NOTREACHED(); 338 } 339 } 340 341 scoped_refptr<I010BufferInterface> WrapI010Buffer( 342 int width, 343 int height, 344 const uint16_t* y_plane, 345 int y_stride, 346 const uint16_t* u_plane, 347 int u_stride, 348 const uint16_t* v_plane, 349 int v_stride, 350 std::function<void()> no_longer_used) { 351 return scoped_refptr<I010BufferInterface>( 352 make_ref_counted<WrappedYuv16BBuffer<I010BufferBase>>( 353 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 354 v_stride, no_longer_used)); 355 } 356 357 scoped_refptr<I210BufferInterface> WrapI210Buffer( 358 int width, 359 int height, 360 const uint16_t* y_plane, 361 int y_stride, 362 const uint16_t* u_plane, 363 int u_stride, 364 const uint16_t* v_plane, 365 int v_stride, 366 std::function<void()> no_longer_used) { 367 return scoped_refptr<I210BufferInterface>( 368 make_ref_counted<WrappedYuv16BBuffer<I210BufferBase>>( 369 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 370 v_stride, no_longer_used)); 371 } 372 373 scoped_refptr<I410BufferInterface> WrapI410Buffer( 374 int width, 375 int height, 376 const uint16_t* y_plane, 377 int y_stride, 378 const uint16_t* u_plane, 379 int u_stride, 380 const uint16_t* v_plane, 381 int v_stride, 382 std::function<void()> no_longer_used) { 383 return scoped_refptr<I410BufferInterface>( 384 make_ref_counted<WrappedYuv16BBuffer<I410BufferBase>>( 385 width, height, y_plane, y_stride, u_plane, u_stride, v_plane, 386 v_stride, no_longer_used)); 387 } 388 389 } // namespace webrtc