Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Unified Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 23870002: Video Capture: Use libyuv for color conversion in VideoCaptureController. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: DCHECK for no rotation no flips in kRGB24+OS_WIN Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/renderer_host/media/video_capture_controller.cc
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index a9c11a6291c9c3bf17a5aa3162627746b3eb4c6f..7f847bbe7df661765b35cd2d8dafc530f6d820e0 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -23,6 +23,7 @@
namespace {
+#if defined(OS_IOS) || defined(OS_ANDROID)
// TODO(wjia): Support stride.
void RotatePackedYV12Frame(
const uint8* src,
@@ -44,6 +45,7 @@ void RotatePackedYV12Frame(
media::RotatePlaneByPixels(
src, dest_vplane, width/2, height/2, rotation, flip_vert, flip_horiz);
}
+#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
} // namespace
@@ -258,6 +260,133 @@ scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveOutputBuffer() {
// Implements VideoCaptureDevice::EventHandler.
// OnIncomingCapturedFrame is called the thread running the capture device.
// I.e.- DirectShow thread on windows and v4l2_thread on Linux.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+void VideoCaptureController::OnIncomingCapturedFrame(
+ const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ bool flip_vert,
+ bool flip_horiz) {
+ TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
+
+ scoped_refptr<media::VideoFrame> dst;
+ {
+ base::AutoLock lock(buffer_pool_lock_);
+ if (!buffer_pool_.get())
+ return;
+ dst = buffer_pool_->ReserveI420VideoFrame(
+ gfx::Size(frame_info_.width, frame_info_.height), rotation);
+ }
+
+ if (!dst.get())
+ return;
+
+ uint8* yplane = dst->data(media::VideoFrame::kYPlane);
+ uint8* uplane = dst->data(media::VideoFrame::kUPlane);
+ uint8* vplane = dst->data(media::VideoFrame::kVPlane);
+ int yplane_stride = frame_info_.width;
+ int uv_plane_stride = (frame_info_.width + 1) / 2;
+ int crop_x = 0;
+ int crop_y = 0;
+ libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY;
+ // Assuming rotation happens first and flips next, we can consolidate both
+ // vertical and horizontal flips together with rotation into two variables:
+ // new_rotation = (rotation + 180 * vertical_flip) modulo 360
+ // new_vertical_flip = horizontal_flip XOR vertical_flip
+ int new_rotation_angle = (rotation + 180 * flip_vert) % 360;
+ libyuv::RotationMode rotation_mode = libyuv::kRotate0;
+ if (new_rotation_angle == 90)
+ rotation_mode = libyuv::kRotate90;
+ else if (new_rotation_angle == 180)
+ rotation_mode = libyuv::kRotate180;
+ else if (new_rotation_angle == 270)
+ rotation_mode = libyuv::kRotate270;
+
+ switch (frame_info_.color) {
+ case media::VideoCaptureCapability::kColorUnknown: // Color format not set.
+ break;
+ case media::VideoCaptureCapability::kI420:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_I420;
+ break;
+ case media::VideoCaptureCapability::kYV12:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_YV12;
+ break;
+ case media::VideoCaptureCapability::kNV21:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_NV12;
+ break;
+ case media::VideoCaptureCapability::kYUY2:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_YUY2;
+ break;
+ case media::VideoCaptureCapability::kRGB24:
+ origin_colorspace = libyuv::FOURCC_RAW;
+ break;
+ case media::VideoCaptureCapability::kARGB:
+ origin_colorspace = libyuv::FOURCC_ARGB;
+ break;
+ case media::VideoCaptureCapability::kMJPEG:
+ origin_colorspace = libyuv::FOURCC_MJPG;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ int need_convert_rgb24_on_win = false;
+#if defined(OS_WIN)
+ // kRGB24 on Windows start at the bottom line and has a negative stride. This
+ // is not supported by libyuv, so the media API is used instead.
+ if (frame_info_.color == media::VideoCaptureCapability::kRGB24) {
+ // Rotation and flipping is not supported in kRGB24 and OS_WIN case.
+ DCHECK(!rotation && !flip_vert && !flip_horiz);
+ need_convert_rgb24_on_win = true;
+ }
+#endif
+ if (need_convert_rgb24_on_win) {
+ int rgb_stride = -3 * (frame_info_.width + chopped_width_);
+ const uint8* rgb_src =
+ data + 3 * (frame_info_.width + chopped_width_) *
+ (frame_info_.height - 1 + chopped_height_);
+ media::ConvertRGB24ToYUV(rgb_src,
+ yplane,
+ uplane,
+ vplane,
+ frame_info_.width,
+ frame_info_.height,
+ rgb_stride,
+ yplane_stride,
+ uv_plane_stride);
+ } else {
+ libyuv::ConvertToI420(
+ data,
+ length,
+ yplane,
+ yplane_stride,
+ uplane,
+ uv_plane_stride,
+ vplane,
+ uv_plane_stride,
+ crop_x,
+ crop_y,
+ frame_info_.width,
+ frame_info_.height * (flip_vert ^ flip_horiz ? -1 : 1),
+ frame_info_.width,
+ frame_info_.height,
+ rotation_mode,
+ origin_colorspace);
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
+ this,
+ dst,
+ timestamp));
+}
+#else
void VideoCaptureController::OnIncomingCapturedFrame(
const uint8* data,
int length,
@@ -316,21 +445,14 @@ void VideoCaptureController::OnIncomingCapturedFrame(
// we can't convert the frame to I420. YUY2 is 2 bytes per pixel.
break;
}
-
media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
frame_info_.height);
break;
case media::VideoCaptureCapability::kRGB24: {
int ystride = frame_info_.width;
int uvstride = frame_info_.width / 2;
-#if defined(OS_WIN) // RGB on Windows start at the bottom line.
- int rgb_stride = -3 * (frame_info_.width + chopped_width_);
- const uint8* rgb_src = data + 3 * (frame_info_.width + chopped_width_) *
- (frame_info_.height -1 + chopped_height_);
-#else
int rgb_stride = 3 * (frame_info_.width + chopped_width_);
const uint8* rgb_src = data;
-#endif
media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane,
frame_info_.width, frame_info_.height,
rgb_stride, ystride, uvstride);
@@ -342,20 +464,6 @@ void VideoCaptureController::OnIncomingCapturedFrame(
(frame_info_.width + chopped_width_) * 4,
frame_info_.width, frame_info_.width / 2);
break;
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
- case media::VideoCaptureCapability::kMJPEG: {
- int yplane_stride = frame_info_.width;
- int uv_plane_stride = (frame_info_.width + 1) / 2;
- int crop_x = 0;
- int crop_y = 0;
- libyuv::ConvertToI420(data, length, yplane, yplane_stride, uplane,
- uv_plane_stride, vplane, uv_plane_stride, crop_x,
- crop_y, frame_info_.width, frame_info_.height,
- frame_info_.width, frame_info_.height,
- libyuv::kRotate0, libyuv::FOURCC_MJPG);
- break;
- }
-#endif
default:
NOTREACHED();
}
@@ -365,6 +473,7 @@ void VideoCaptureController::OnIncomingCapturedFrame(
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
this, dst, timestamp));
}
+#endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
// OnIncomingCapturedVideoFrame is called the thread running the capture device.
void VideoCaptureController::OnIncomingCapturedVideoFrame(
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698