summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-30 22:03:02 +0000
committerjiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-30 22:03:02 +0000
commit74e69b1b9c1e1a3c129bd955fb6601a4b517539b (patch)
treeb657cb23e181f810a50d1f7b8e58daf4222a80b7 /content
parent7499f22fea8d42ac115055053f1e20a5cdb67044 (diff)
downloadchromium_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.cc39
-rw-r--r--content/browser/renderer_host/media/video_capture_controller_unittest.cc28
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