diff --git a/webrtc/common_video/i420_video_frame_unittest.cc b/webrtc/common_video/i420_video_frame_unittest.cc index 2b000a709c..62d14b9f4a 100644 --- a/webrtc/common_video/i420_video_frame_unittest.cc +++ b/webrtc/common_video/i420_video_frame_unittest.cc @@ -151,16 +151,12 @@ TEST(TestVideoFrame, ShallowCopy) { memset(buffer_y, 16, kSizeY); memset(buffer_u, 8, kSizeU); memset(buffer_v, 4, kSizeV); - // TODO(nisse): This new + Copy looks quite awkward. Consider adding - // an alternative I420Buffer::Create method. + VideoFrame frame1( - I420Buffer::Copy(*rtc::scoped_refptr( - new rtc::RefCountedObject( - width, height, - buffer_y, stride_y, - buffer_u, stride_u, - buffer_v, stride_v, - rtc::Callback0([](){})))), + I420Buffer::Copy(width, height, + buffer_y, stride_y, + buffer_u, stride_u, + buffer_v, stride_v), kRotation, 0); frame1.set_timestamp(timestamp); frame1.set_ntp_time_ms(ntp_time_ms); diff --git a/webrtc/common_video/include/video_frame_buffer.h b/webrtc/common_video/include/video_frame_buffer.h index 287624e59e..2d5949fbc4 100644 --- a/webrtc/common_video/include/video_frame_buffer.h +++ b/webrtc/common_video/include/video_frame_buffer.h @@ -58,9 +58,6 @@ class VideoFrameBuffer : public rtc::RefCountInterface { // Plain I420 buffer in standard memory. class I420Buffer : public VideoFrameBuffer { public: - I420Buffer(int width, int height); - I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v); - static rtc::scoped_refptr Create(int width, int height); static rtc::scoped_refptr Create(int width, int height, @@ -68,6 +65,24 @@ class I420Buffer : public VideoFrameBuffer { int stride_u, int stride_v); + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr Copy(const VideoFrameBuffer& buffer); + + static rtc::scoped_refptr Copy( + int width, int height, + const uint8_t* data_y, int stride_y, + const uint8_t* data_u, int stride_u, + const uint8_t* data_v, int stride_v); + + // Returns a rotated versions of |src|. Native buffers are not + // supported. The reason this function doesn't return an I420Buffer, + // is that it returns |src| unchanged in case |rotation| is zero. + // TODO(nisse): Consider dropping the special handling of zero + // rotation, and leave any optimizing that case to the caller. + static rtc::scoped_refptr Rotate( + rtc::scoped_refptr src, + VideoRotation rotation); + // Sets all three planes to all zeros. Used to work around for // quirks in memory checkers // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and @@ -95,9 +110,6 @@ class I420Buffer : public VideoFrameBuffer { void* native_handle() const override; rtc::scoped_refptr NativeToI420Buffer() override; - // Create a new buffer and copy the pixel data. - static rtc::scoped_refptr Copy(const VideoFrameBuffer& buffer); - // Scale the cropped area of |src| to the size of |this| buffer, and // write the result into |this|. void CropAndScaleFrom(const VideoFrameBuffer& src, @@ -133,14 +145,10 @@ class I420Buffer : public VideoFrameBuffer { ScaleFrom(*src); } - // Returns a rotated versions of |src|. Native buffers are not - // supported. The reason this function doesn't return an I420Buffer, - // is that it returns |src| unchanged in case |rotation| is zero. - static rtc::scoped_refptr Rotate( - rtc::scoped_refptr src, - VideoRotation rotation); - protected: + I420Buffer(int width, int height); + I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + ~I420Buffer() override; private: diff --git a/webrtc/common_video/video_frame_buffer.cc b/webrtc/common_video/video_frame_buffer.cc index 1ee97531b0..d23b4c5d45 100644 --- a/webrtc/common_video/video_frame_buffer.cc +++ b/webrtc/common_video/video_frame_buffer.cc @@ -61,10 +61,12 @@ I420Buffer::I420Buffer(int width, I420Buffer::~I420Buffer() { } +// static rtc::scoped_refptr I420Buffer::Create(int width, int height) { return new rtc::RefCountedObject(width, height); } +// static rtc::scoped_refptr I420Buffer::Create(int width, int height, int stride_y, @@ -74,6 +76,67 @@ rtc::scoped_refptr I420Buffer::Create(int width, width, height, stride_y, stride_u, stride_v); } +// static +rtc::scoped_refptr I420Buffer::Copy( + const VideoFrameBuffer& source) { + return Copy(source.width(), source.height(), + source.DataY(), source.StrideY(), + source.DataU(), source.StrideU(), + source.DataV(), source.StrideV()); +} + +// static +rtc::scoped_refptr I420Buffer::Copy( + int width, int height, + const uint8_t* data_y, int stride_y, + const uint8_t* data_u, int stride_u, + const uint8_t* data_v, int stride_v) { + // Note: May use different strides than the input data. + rtc::scoped_refptr buffer = Create(width, height); + RTC_CHECK_EQ(0, libyuv::I420Copy(data_y, stride_y, + data_u, stride_u, + data_v, stride_v, + buffer->MutableDataY(), buffer->StrideY(), + buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), + width, height)); + return buffer; +} + +// static +rtc::scoped_refptr I420Buffer::Rotate( + rtc::scoped_refptr src, + VideoRotation rotation) { + RTC_CHECK(src->DataY()); + RTC_CHECK(src->DataU()); + RTC_CHECK(src->DataV()); + + if (rotation == webrtc::kVideoRotation_0) { + return src; + } + + int rotated_width = src->width(); + int rotated_height = src->height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr buffer = + I420Buffer::Create(rotated_width, rotated_height); + + RTC_CHECK_EQ(0, libyuv::I420Rotate( + src->DataY(), src->StrideY(), + src->DataU(), src->StrideU(), + src->DataV(), src->StrideV(), + buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(), + src->width(), src->height(), + static_cast(rotation))); + + return buffer; +} + void I420Buffer::InitializeData() { memset(data_.get(), 0, I420DataSize(height_, stride_y_, stride_u_, stride_v_)); @@ -126,23 +189,6 @@ rtc::scoped_refptr I420Buffer::NativeToI420Buffer() { return nullptr; } -// static -rtc::scoped_refptr I420Buffer::Copy( - const VideoFrameBuffer& source) { - int width = source.width(); - int height = source.height(); - rtc::scoped_refptr target = I420Buffer::Create(width, height); - RTC_CHECK(libyuv::I420Copy(source.DataY(), source.StrideY(), - source.DataU(), source.StrideU(), - source.DataV(), source.StrideV(), - target->MutableDataY(), target->StrideY(), - target->MutableDataU(), target->StrideU(), - target->MutableDataV(), target->StrideV(), - width, height) == 0); - - return target; -} - void I420Buffer::SetToBlack() { RTC_CHECK(libyuv::I420Rect(MutableDataY(), StrideY(), MutableDataU(), StrideU(), @@ -205,41 +251,6 @@ void I420Buffer::ScaleFrom(const VideoFrameBuffer& src) { CropAndScaleFrom(src, 0, 0, src.width(), src.height()); } -// static -rtc::scoped_refptr I420Buffer::Rotate( - rtc::scoped_refptr src, - VideoRotation rotation) { - RTC_DCHECK(src->DataY()); - RTC_DCHECK(src->DataU()); - RTC_DCHECK(src->DataV()); - - if (rotation == webrtc::kVideoRotation_0) { - return src; - } - - int rotated_width = src->width(); - int rotated_height = src->height(); - if (rotation == webrtc::kVideoRotation_90 || - rotation == webrtc::kVideoRotation_270) { - std::swap(rotated_width, rotated_height); - } - - rtc::scoped_refptr buffer = - I420Buffer::Create(rotated_width, rotated_height); - - int res = libyuv::I420Rotate( - src->DataY(), src->StrideY(), - src->DataU(), src->StrideU(), - src->DataV(), src->StrideV(), - buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(), - buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(), - src->width(), src->height(), - static_cast(rotation)); - RTC_DCHECK_EQ(res, 0); - - return buffer; -} - NativeHandleBuffer::NativeHandleBuffer(void* native_handle, int width, int height)