diff --git a/webrtc/common_video/libyuv/include/webrtc_libyuv.h b/webrtc/common_video/libyuv/include/webrtc_libyuv.h index 4b1b2a58f..c6a0046ac 100644 --- a/webrtc/common_video/libyuv/include/webrtc_libyuv.h +++ b/webrtc/common_video/libyuv/include/webrtc_libyuv.h @@ -63,6 +63,15 @@ enum VideoRotationMode { // Return value: An aligned form of the input value. int AlignInt(int value, int alignment); +// Align stride values for I420 Video frames. +// Input: +// - width : Image width. +// - stride_y : Pointer to the stride of the y plane. +// - stride_uv: Pointer to the stride of the u and v planes (setting identical +// values for both). +// Setting 16 byte alignment. +void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv); + // Calculate the required buffer size. // Input: // - type :The type of the designated video frame. diff --git a/webrtc/common_video/libyuv/libyuv_unittest.cc b/webrtc/common_video/libyuv/libyuv_unittest.cc index 6f7606552..6ab8c2336 100644 --- a/webrtc/common_video/libyuv/libyuv_unittest.cc +++ b/webrtc/common_video/libyuv/libyuv_unittest.cc @@ -138,8 +138,12 @@ TEST_F(TestLibYuv, ConvertTest) { printf("\nConvert #%d I420 <-> RGB24\n", j); scoped_array res_rgb_buffer2(new uint8_t[width_ * height_ * 3]); I420VideoFrame res_i420_frame; - res_i420_frame.CreateEmptyFrame(width_, height_, width_, - (width_ + 1) / 2, (width_ + 1) / 2); + // Align the stride values for the output frame. + int stride_y = 0; + int stride_uv = 0; + Calc16ByteAlignedStride(width_, &stride_y, &stride_uv); + res_i420_frame.CreateEmptyFrame(width_, height_, stride_y, + stride_uv, stride_uv); EXPECT_EQ(0, ConvertFromI420(orig_frame, kRGB24, 0, res_rgb_buffer2.get())); EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2.get(), 0, 0, width_, @@ -320,4 +324,21 @@ TEST_F(TestLibYuv, alignment) { EXPECT_EQ(0x400, AlignInt(value, 32)); // Low 5 bits are zero. } +TEST_F(TestLibYuv, StrideAlignment) { + int stride_y = 0; + int stride_uv = 0; + int width = 52; + Calc16ByteAlignedStride(width, &stride_y, &stride_uv); + EXPECT_EQ(64, stride_y); + EXPECT_EQ(32, stride_uv); + width = 128; + Calc16ByteAlignedStride(width, &stride_y, &stride_uv); + EXPECT_EQ(128, stride_y); + EXPECT_EQ(64, stride_uv); + width = 127; + Calc16ByteAlignedStride(width, &stride_y, &stride_uv); + EXPECT_EQ(128, stride_y); + EXPECT_EQ(64, stride_uv); +} + } // namespace diff --git a/webrtc/common_video/libyuv/webrtc_libyuv.cc b/webrtc/common_video/libyuv/webrtc_libyuv.cc index 816fa8f6a..ba5c6fad2 100644 --- a/webrtc/common_video/libyuv/webrtc_libyuv.cc +++ b/webrtc/common_video/libyuv/webrtc_libyuv.cc @@ -17,6 +17,8 @@ namespace webrtc { +const int k16ByteAlignment = 16; + VideoType RawVideoTypeToCommonVideoVideoType(RawVideoType type) { switch (type) { case kVideoI420: @@ -58,6 +60,11 @@ int AlignInt(int value, int alignment) { return ((value + alignment - 1) & ~ (alignment - 1)); } +void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) { + *stride_y = AlignInt(width, k16ByteAlignment); + *stride_uv = AlignInt((width + 1) / 2, k16ByteAlignment); +} + int CalcBufferSize(VideoType type, int width, int height) { int buffer_size = 0; switch (type) { diff --git a/webrtc/modules/video_capture/main/source/video_capture_impl.cc b/webrtc/modules/video_capture/main/source/video_capture_impl.cc index e2e120956..794156fea 100644 --- a/webrtc/modules/video_capture/main/source/video_capture_impl.cc +++ b/webrtc/modules/video_capture/main/source/video_capture_impl.cc @@ -284,9 +284,12 @@ WebRtc_Word32 VideoCaptureImpl::IncomingFrame( // Setting absolute height (in case it was negative). // In Windows, the image starts bottom left, instead of top left. // Setting a negative source height, inverts the image (within LibYuv). + int stride_y = 0; + int stride_uv = 0; + Calc16ByteAlignedStride(width, &stride_y, &stride_uv); int ret = _captureFrame.CreateEmptyFrame(width, abs(height), - width, (width + 1) / 2, - (width + 1) / 2); + stride_y, + stride_uv, stride_uv); if (ret < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, @@ -336,7 +339,6 @@ WebRtc_Word32 VideoCaptureImpl::IncomingFrameI420( const VideoFrameI420& video_frame, WebRtc_Word64 captureTime) { CriticalSectionScoped cs(&_callBackCs); - // TODO(mikhal): Do we take the stride as is, or do we align it? int size_y = video_frame.height * video_frame.y_pitch; int size_u = video_frame.u_pitch * (video_frame.height + 1) / 2; int size_v = video_frame.v_pitch * (video_frame.height + 1) / 2; diff --git a/webrtc/modules/video_capture/main/source/video_capture_impl.h b/webrtc/modules/video_capture/main/source/video_capture_impl.h index 7d62de385..38f62bf19 100644 --- a/webrtc/modules/video_capture/main/source/video_capture_impl.h +++ b/webrtc/modules/video_capture/main/source/video_capture_impl.h @@ -98,7 +98,6 @@ public: protected: VideoCaptureImpl(const WebRtc_Word32 id); virtual ~VideoCaptureImpl(); - // TODO(mikhal): Remove codec_type. WebRtc_Word32 DeliverCapturedFrame(I420VideoFrame& captureFrame, WebRtc_Word64 capture_time); WebRtc_Word32 DeliverEncodedCapturedFrame(