diff options
author | jiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 22:03:02 +0000 |
---|---|---|
committer | jiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 22:03:02 +0000 |
commit | 74e69b1b9c1e1a3c129bd955fb6601a4b517539b (patch) | |
tree | b657cb23e181f810a50d1f7b8e58daf4222a80b7 /content | |
parent | 7499f22fea8d42ac115055053f1e20a5cdb67044 (diff) | |
download | chromium_src-74e69b1b9c1e1a3c129bd955fb6601a4b517539b.zip chromium_src-74e69b1b9c1e1a3c129bd955fb6601a4b517539b.tar.gz chromium_src-74e69b1b9c1e1a3c129bd955fb6601a4b517539b.tar.bz2 |
Round up the destination buffer instead of chopping 1 pixel when the frame has odd width/height.
Libyuv can handle odd width/height if the output buffer size is rounded up.
This will solve the frame dropped problem when the input is a 1x1 frame.
TESTED=Minimized the shared window during window sharing to produce a 1x1 black frame and verified the frame is rendered fine.
BUG=360655
Review URL: https://codereview.chromium.org/253813007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267352 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller.cc | 39 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller_unittest.cc | 28 |
2 files changed, 50 insertions, 17 deletions
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index 9c70806..d208281 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc @@ -299,20 +299,25 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData( if (!frame_format.IsValid()) return; - // Chopped pixels in width/height in case video capture device has odd - // numbers for width/height. - int chopped_width = 0; - int chopped_height = 0; + // Padded pixels in width/height in case video capture device has odd + // numbers for width/height. When the width/height is odd, the last pixel of + // each row will have a Y/U/V sample. It's still considered odd width/height, + // not duplicated. Converting back to ARGB it will still be odd width/height. + // The destination buffer should be rounded up. Pass in a stride that reflects + // the byte per line with rounding to libyuv::ConvertToI420, but pass in the + // original width/height. + int padded_width = 0; + int padded_height = 0; int new_unrotated_width = frame_format.frame_size.width(); int new_unrotated_height = frame_format.frame_size.height(); if (new_unrotated_width & 1) { - --new_unrotated_width; - chopped_width = 1; + ++new_unrotated_width; + padded_width = 1; } if (new_unrotated_height & 1) { - --new_unrotated_height; - chopped_height = 1; + ++new_unrotated_height; + padded_height = 1; } int destination_width = new_unrotated_width; @@ -364,23 +369,23 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData( case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. break; case media::PIXEL_FORMAT_I420: - DCHECK(!chopped_width && !chopped_height); + DCHECK(!padded_width && !padded_height); origin_colorspace = libyuv::FOURCC_I420; break; case media::PIXEL_FORMAT_YV12: - DCHECK(!chopped_width && !chopped_height); + DCHECK(!padded_width && !padded_height); origin_colorspace = libyuv::FOURCC_YV12; break; case media::PIXEL_FORMAT_NV21: - DCHECK(!chopped_width && !chopped_height); + DCHECK(!padded_width && !padded_height); origin_colorspace = libyuv::FOURCC_NV21; break; case media::PIXEL_FORMAT_YUY2: - DCHECK(!chopped_width && !chopped_height); + DCHECK(!padded_width && !padded_height); origin_colorspace = libyuv::FOURCC_YUY2; break; case media::PIXEL_FORMAT_UYVY: - DCHECK(!chopped_width && !chopped_height); + DCHECK(!padded_width && !padded_height); origin_colorspace = libyuv::FOURCC_UYVY; break; case media::PIXEL_FORMAT_RGB24: @@ -414,10 +419,10 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData( crop_x, crop_y, frame_format.frame_size.width(), - (flip ? -frame_format.frame_size.height() : - frame_format.frame_size.height()), - new_unrotated_width, - new_unrotated_height, + (flip ? -frame_format.frame_size.height() + : frame_format.frame_size.height()), + frame_format.frame_size.width(), + frame_format.frame_size.height(), rotation_mode, origin_colorspace); #else diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index f650397..2387b15 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc @@ -615,4 +615,32 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) { Mock::VerifyAndClearExpectations(client_b_.get()); } +// This test verifies that a 1x1 frame is passed down to the client. +TEST_F(VideoCaptureControllerTest, CaptureOddWidthHeightFrames) { + media::VideoCaptureParams session_100; + session_100.requested_format = media::VideoCaptureFormat( + gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); + const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1); + controller_->AddClient(client_a_route_1, + client_a_.get(), + base::kNullProcessHandle, + 100, + session_100); + { + InSequence s; + EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1); + EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1); + } + + media::VideoCaptureFormat frame_format( + gfx::Size(1, 1), 30, media::PIXEL_FORMAT_ARGB); + size_t length = + frame_format.frame_size.width() * frame_format.frame_size.height() * 4; + scoped_ptr<uint8[]> buffer(new uint8[length]); + + device_->OnIncomingCapturedData( + buffer.get(), length, frame_format, 0, base::TimeTicks()); + base::RunLoop().RunUntilIdle(); +} + } // namespace content |