diff --git a/src/common_video/libyuv/include/webrtc_libyuv.h b/src/common_video/libyuv/include/webrtc_libyuv.h index 68c3aa5ab..c09da043c 100644 --- a/src/common_video/libyuv/include/webrtc_libyuv.h +++ b/src/common_video/libyuv/include/webrtc_libyuv.h @@ -16,6 +16,7 @@ #define WEBRTC_COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_ #include "common_types.h" // RawVideoTypes. +#include "modules/interface/module_common_types.h" // VideoFrame #include "typedefs.h" namespace webrtc { @@ -76,13 +77,12 @@ int CalcBufferSize(VideoType type, int width, int height); // - src_video_type : Type of input video. // - src_frame : Pointer to a source frame. // - crop_x/crop_y : Starting positions for cropping (0 for no crop). -// - src/dst_width : src/dst width in pixels. -// - src/dst_height : src/dst height in pixels. +// - src_width : src width in pixels. +// - src_height : src height in pixels. // - sample_size : Required only for the parsing of MJPG (set to 0 else). -// - dst_stride : Number of bytes in a row of the dst Y plane. // - rotate : Rotation mode of output image. // Output: -// - dst_frame : Pointer to a destination frame. +// - dst_frame : Reference to a destination frame. // Return value: 0 if OK, < 0 otherwise. int ConvertToI420(VideoType src_video_type, @@ -90,9 +90,8 @@ int ConvertToI420(VideoType src_video_type, int crop_x, int crop_y, int src_width, int src_height, int sample_size, - int dst_width, int dst_height, int dst_stride, VideoRotationMode rotation, - uint8_t* dst_frame); + VideoFrame* dst_frame); // Convert From I420 // Input: diff --git a/src/common_video/libyuv/libyuv_unittest.cc b/src/common_video/libyuv/libyuv_unittest.cc index 343d49439..2fb8fd244 100644 --- a/src/common_video/libyuv/libyuv_unittest.cc +++ b/src/common_video/libyuv/libyuv_unittest.cc @@ -13,6 +13,7 @@ #include "common_video/libyuv/include/webrtc_libyuv.h" #include "gtest/gtest.h" +#include "modules/interface/module_common_types.h" // VideoFrame #include "system_wrappers/interface/tick_util.h" #include "testsupport/fileutils.h" @@ -118,20 +119,21 @@ TEST_F(TestLibYuv, ConvertTest) { // printf("\nConvert #%d I420 <-> RGB24\n", j); uint8_t* res_rgb_buffer2 = new uint8_t[width_ * height_ * 3]; - uint8_t* res_i420_buffer = new uint8_t[frame_length_]; - + VideoFrame res_i420_frame; + res_i420_frame.VerifyAndAllocate(frame_length_); + res_i420_frame.SetHeight(height_); + res_i420_frame.SetWidth(width_); EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_, kRGB24, 0, width_, height_, res_rgb_buffer2)); EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2, 0, 0, width_, height_, - 0, width_, height_, width_, kRotateNone, - res_i420_buffer)); + 0, kRotateNone, &res_i420_frame)); - if (fwrite(res_i420_buffer, 1, frame_length_, + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + psnr = I420PSNR(orig_buffer, res_i420_frame.Buffer(), width_, height_); // Optimization Speed- quality trade-off => 45 dB only (platform dependant). EXPECT_GT(ceil(psnr), 44); j++; @@ -142,10 +144,10 @@ TEST_F(TestLibYuv, ConvertTest) { EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_, kUYVY, 0, width_, height_, out_uyvy_buffer)); EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer, 0, 0, width_, height_, - 0, width_, height_, width_,kRotateNone, res_i420_buffer)); - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + 0, kRotateNone, &res_i420_frame)); + psnr = I420PSNR(orig_buffer, res_i420_frame.Buffer(), width_, height_); EXPECT_EQ(48.0, psnr); - if (fwrite(res_i420_buffer, 1, frame_length_, + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } @@ -154,17 +156,16 @@ TEST_F(TestLibYuv, ConvertTest) { delete [] out_uyvy_buffer; // printf("\nConvert #%d I420 <-> I420 \n", j); - uint8_t* out_i420_buffer = new uint8_t[width_ * height_ * 3 / 2 ]; + uint8_t* out_i420_buffer = new uint8_t[width_ * height_ * 3 / 2 ]; EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, - 0, width_, height_, width_, - kRotateNone, out_i420_buffer)); - EXPECT_EQ(0, ConvertFromI420(out_i420_buffer, width_, kI420, 0, - width_, height_, res_i420_buffer)); - if (fwrite(res_i420_buffer, 1, frame_length_, + 0, kRotateNone, &res_i420_frame)); + EXPECT_EQ(0, ConvertFromI420(res_i420_frame.Buffer(), width_, kI420, 0, + width_, height_, out_i420_buffer)); + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + psnr = I420PSNR(orig_buffer, out_i420_buffer, width_, height_); EXPECT_EQ(48.0, psnr); j++; delete [] out_i420_buffer; @@ -177,13 +178,13 @@ TEST_F(TestLibYuv, ConvertTest) { EXPECT_EQ(0, ConvertFromYV12(outYV120Buffer, width_, kI420, 0, width_, height_, - res_i420_buffer)); - if (fwrite(res_i420_buffer, 1, frame_length_, + res_i420_frame.Buffer())); + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + psnr = I420PSNR(orig_buffer, res_i420_frame.Buffer(), width_, height_); EXPECT_EQ(48.0, psnr); j++; delete [] outYV120Buffer; @@ -194,14 +195,13 @@ TEST_F(TestLibYuv, ConvertTest) { kYUY2, 0, width_, height_, out_yuy2_buffer)); EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer, 0, 0, width_, height_, - 0, width_, height_, width_, - kRotateNone, res_i420_buffer)); + 0, kRotateNone, &res_i420_frame)); - if (fwrite(res_i420_buffer, 1, frame_length_, + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + psnr = I420PSNR(orig_buffer, res_i420_frame.Buffer(), width_, height_); EXPECT_EQ(48.0, psnr); // printf("\nConvert #%d I420 <-> RGB565\n", j); @@ -210,14 +210,13 @@ TEST_F(TestLibYuv, ConvertTest) { kRGB565, 0, width_, height_, out_rgb565_buffer)); EXPECT_EQ(0, ConvertToI420(kRGB565, out_rgb565_buffer, 0, 0, width_, height_, - 0, width_, height_, width_, - kRotateNone, res_i420_buffer)); + 0, kRotateNone, &res_i420_frame)); - if (fwrite(res_i420_buffer, 1, frame_length_, + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + psnr = I420PSNR(orig_buffer, res_i420_frame.Buffer(), width_, height_); // TODO(leozwang) Investigate the right psnr should be set for I420ToRGB565, // Another example is I420ToRGB24, the psnr is 44 EXPECT_GT(ceil(psnr), 40); @@ -228,23 +227,22 @@ TEST_F(TestLibYuv, ConvertTest) { kARGB, 0, width_, height_, out_argb8888_buffer)); EXPECT_EQ(0, ConvertToI420(kARGB, out_argb8888_buffer, 0, 0, width_, height_, - 0, width_, height_, width_, - kRotateNone, res_i420_buffer)); + 0, kRotateNone, &res_i420_frame)); - if (fwrite(res_i420_buffer, 1, frame_length_, + if (fwrite(res_i420_frame.Buffer(), 1, frame_length_, output_file) != static_cast(frame_length_)) { return; } - psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_); + psnr = I420PSNR(orig_buffer, res_i420_frame.Buffer(), width_, height_); // TODO(leozwang) Investigate the right psnr should be set for I420ToARGB8888, EXPECT_GT(ceil(psnr), 42); ASSERT_EQ(0, fclose(output_file)); + res_i420_frame.Free(); delete [] out_argb8888_buffer; delete [] out_rgb565_buffer; delete [] out_yuy2_buffer; - delete [] res_i420_buffer; delete [] orig_buffer; } diff --git a/src/common_video/libyuv/webrtc_libyuv.cc b/src/common_video/libyuv/webrtc_libyuv.cc index eed647637..f7226f2ad 100644 --- a/src/common_video/libyuv/webrtc_libyuv.cc +++ b/src/common_video/libyuv/webrtc_libyuv.cc @@ -170,15 +170,17 @@ int ConvertToI420(VideoType src_video_type, int crop_x, int crop_y, int src_width, int src_height, int sample_size, - int dst_width, int dst_height, int dst_stride, VideoRotationMode rotation, - uint8_t* dst_frame) { + VideoFrame* dst_frame) { // All sanity tests are conducted within LibYuv. - int abs_dst_height = (dst_height < 0) ? -dst_height : dst_height; + int dst_height = dst_frame->Height(); + int dst_width = dst_frame->Width(); + // TODO(mikhal): When available, use actual stride value. + int dst_stride = dst_frame->Width(); int half_dst_width = (dst_width + 1) >> 1; - int half_dst_height = (abs_dst_height + 1) >> 1; - uint8_t* dst_yplane = dst_frame; - uint8_t* dst_uplane = dst_yplane + dst_width * abs_dst_height; + int half_dst_height = (dst_height + 1) >> 1; + uint8_t* dst_yplane = dst_frame->Buffer(); + uint8_t* dst_uplane = dst_yplane + dst_width * dst_height; uint8_t* dst_vplane = dst_uplane + half_dst_width * half_dst_height; return libyuv::ConvertToI420(src_frame, sample_size, dst_yplane, dst_stride, diff --git a/src/modules/video_capture/main/source/video_capture_impl.cc b/src/modules/video_capture/main/source/video_capture_impl.cc index a0f9638c2..6c3312861 100644 --- a/src/modules/video_capture/main/source/video_capture_impl.cc +++ b/src/modules/video_capture/main/source/video_capture_impl.cc @@ -208,8 +208,7 @@ WebRtc_Word32 VideoCaptureImpl::CaptureDelay() } WebRtc_Word32 VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame, - WebRtc_Word32 width, WebRtc_Word32 height, WebRtc_Word64 capture_time, - VideoCodecType codec_type) { + WebRtc_Word64 capture_time, VideoCodecType codec_type) { UpdateFrameCount();// frame count used for local frame rate callback. _startImageFrameIntervall = 0; // prevent the start image to be displayed. @@ -233,9 +232,6 @@ WebRtc_Word32 VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame, } last_capture_time_ = captureFrame.RenderTimeMs(); - captureFrame.SetHeight(height); - captureFrame.SetWidth(width); - if (_dataCallBack) { if (callOnCaptureDelayChanged) { _dataCallBack->OnCaptureDelayChanged(_id, _captureDelay); @@ -289,16 +285,19 @@ WebRtc_Word32 VideoCaptureImpl::IncomingFrame( } memset(_captureFrame.Buffer(), 0, _captureFrame.Size()); - // Keeping stride = width for I420 destination. - int dstStride = width; + _captureFrame.SetWidth(width); + // 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). + _captureFrame.SetHeight(abs(height)); + // TODO(mikhal) : Set stride when available. const int conversionResult = ConvertToI420(commonVideoType, videoFrame, 0, 0, // No cropping width, height, videoFrameLength, - width, height, dstStride, _rotateFrame, - _captureFrame.Buffer()); + &_captureFrame); if (conversionResult < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, @@ -317,8 +316,7 @@ WebRtc_Word32 VideoCaptureImpl::IncomingFrame( } } - DeliverCapturedFrame(_captureFrame, width, abs(height), captureTime, - frameInfo.codecType); + DeliverCapturedFrame(_captureFrame, captureTime, frameInfo.codecType); const WebRtc_UWord32 processTime = @@ -380,12 +378,10 @@ WebRtc_Word32 VideoCaptureImpl::IncomingFrameI420( v_plane += video_frame.v_pitch; } _captureFrame.SetLength(frame_size); + _captureFrame.SetWidth(video_frame.width); + _captureFrame.SetHeight(video_frame.height); - DeliverCapturedFrame(_captureFrame, - video_frame.width, - video_frame.height, - captureTime, - kVideoCodecUnknown); + DeliverCapturedFrame(_captureFrame, captureTime, kVideoCodecUnknown); return 0; } diff --git a/src/modules/video_capture/main/source/video_capture_impl.h b/src/modules/video_capture/main/source/video_capture_impl.h index 6d2c02371..df5d981d9 100644 --- a/src/modules/video_capture/main/source/video_capture_impl.h +++ b/src/modules/video_capture/main/source/video_capture_impl.h @@ -102,7 +102,7 @@ protected: VideoCaptureImpl(const WebRtc_Word32 id); virtual ~VideoCaptureImpl(); WebRtc_Word32 DeliverCapturedFrame( - VideoFrame& captureFrame, WebRtc_Word32 width, WebRtc_Word32 height, + VideoFrame& captureFrame, WebRtc_Word64 capture_time, VideoCodecType codec_type); WebRtc_Word32 _id; // Module ID