diff options
author | wjia@chromium.org <wjia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-28 22:01:04 +0000 |
---|---|---|
committer | wjia@chromium.org <wjia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-28 22:01:04 +0000 |
commit | 1fa37522cade3c1bbd5a523f4aafc884348f8262 (patch) | |
tree | dbb65668ba5d228c41fa5d17a887e8d323ba972e /content/browser/renderer_host/media/video_capture_controller.cc | |
parent | 2226daac070dd08be5f6c60cf464dba7fa4bd94c (diff) | |
download | chromium_src-1fa37522cade3c1bbd5a523f4aafc884348f8262.zip chromium_src-1fa37522cade3c1bbd5a523f4aafc884348f8262.tar.gz chromium_src-1fa37522cade3c1bbd5a523f4aafc884348f8262.tar.bz2 |
Remove one video frame copying in video capture.
On Android, the captured frame might need to be rotated. By moving the rotation code into VideoCaptureController, one video frame copying is reduced.
On Nexus 4, the frame copying from intermedia buffer to shared memory takes about 0.1 ms per frame for VGA YV12.
Review URL: https://codereview.chromium.org/12378007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185339 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/renderer_host/media/video_capture_controller.cc')
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller.cc | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index b503293..fc18af4 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc @@ -20,6 +20,39 @@ #include "third_party/libyuv/include/libyuv.h" #endif +namespace { + +void ResetBufferYV12(uint8* buffer, int width, int height) { + int y_size = width * height; + memset(buffer, 0, y_size); + buffer += y_size; + memset(buffer, 128, y_size / 2); +} + +// TODO(wjia): Support stride. +void RotatePackedYV12Frame( + const uint8* src, + uint8* dest_yplane, + uint8* dest_uplane, + uint8* dest_vplane, + int width, + int height, + int rotation, + bool flip_vert, + bool flip_horiz) { + media::RotatePlaneByPixels( + src, dest_yplane, width, height, rotation, flip_vert, flip_horiz); + int y_size = width * height; + src += y_size; + media::RotatePlaneByPixels( + src, dest_uplane, width/2, height/2, rotation, flip_vert, flip_horiz); + src += y_size/4; + media::RotatePlaneByPixels( + src, dest_vplane, width/2, height/2, rotation, flip_vert, flip_horiz); +} + +} // namespace + namespace content { // The number of DIBs VideoCaptureController allocate. @@ -58,6 +91,7 @@ struct VideoCaptureController::ControllerClient { struct VideoCaptureController::SharedDIB { SharedDIB(base::SharedMemory* ptr) : shared_memory(ptr), + rotation(0), references(0) { } @@ -66,6 +100,8 @@ struct VideoCaptureController::SharedDIB { // The memory created to be shared with renderer processes. scoped_ptr<base::SharedMemory> shared_memory; + int rotation; + // Number of renderer processes which hold this shared memory. // renderer process is represented by VidoeCaptureHost. int references; @@ -250,7 +286,8 @@ void VideoCaptureController::ReturnBuffer( bool VideoCaptureController::ReserveSharedMemory(int* buffer_id_out, uint8** yplane, uint8** uplane, - uint8** vplane) { + uint8** vplane, + int rotation) { int buffer_id = 0; base::SharedMemory* dib = NULL; { @@ -263,6 +300,11 @@ bool VideoCaptureController::ReserveSharedMemory(int* buffer_id_out, // renderer side. dib_it->second->references = -1; dib = dib_it->second->shared_memory.get(); + if (rotation != dib_it->second->rotation) { + ResetBufferYV12(static_cast<uint8*>(dib->memory()), + frame_info_.width, frame_info_.height); + dib_it->second->rotation = rotation; + } break; } } @@ -284,42 +326,46 @@ bool VideoCaptureController::ReserveSharedMemory(int* buffer_id_out, // Implements VideoCaptureDevice::EventHandler. // OnIncomingCapturedFrame is called the thread running the capture device. // I.e.- DirectShow thread on windows and v4l2_thread on Linux. -void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, - int length, - base::Time timestamp) { +void VideoCaptureController::OnIncomingCapturedFrame( + const uint8* data, + int length, + base::Time timestamp, + int rotation, + bool flip_vert, + bool flip_horiz) { + DCHECK (frame_info_.color == media::VideoCaptureCapability::kI420 || + frame_info_.color == media::VideoCaptureCapability::kYV12 || + (rotation == 0 && !flip_vert && !flip_horiz)); + int buffer_id = 0; uint8* yplane = NULL; uint8* uplane = NULL; uint8* vplane = NULL; - if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane)) + if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane, rotation)) return; // Do color conversion from the camera format to I420. switch (frame_info_.color) { case media::VideoCaptureCapability::kColorUnknown: // Color format not set. break; - case media::VideoCaptureCapability::kI420: { + case media::VideoCaptureCapability::kI420: DCHECK(!chopped_width_ && !chopped_height_); - memcpy(yplane, data, (frame_info_.width * frame_info_.height * 3) / 2); + RotatePackedYV12Frame( + data, yplane, uplane, vplane, frame_info_.width, frame_info_.height, + rotation, flip_vert, flip_horiz); break; - } - case media::VideoCaptureCapability::kYV12: { + case media::VideoCaptureCapability::kYV12: DCHECK(!chopped_width_ && !chopped_height_); - const uint8* ptr = data; - memcpy(yplane, ptr, (frame_info_.width * frame_info_.height)); - ptr += frame_info_.width * frame_info_.height; - memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2); - ptr += (frame_info_.width * frame_info_.height) >> 2; - memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2); + RotatePackedYV12Frame( + data, yplane, vplane, uplane, frame_info_.width, frame_info_.height, + rotation, flip_vert, flip_horiz); break; - } - case media::VideoCaptureCapability::kNV21: { + case media::VideoCaptureCapability::kNV21: DCHECK(!chopped_width_ && !chopped_height_); media::ConvertNV21ToYUV(data, yplane, uplane, vplane, frame_info_.width, frame_info_.height); break; - } - case media::VideoCaptureCapability::kYUY2: { + case media::VideoCaptureCapability::kYUY2: DCHECK(!chopped_width_ && !chopped_height_); if (frame_info_.width * frame_info_.height * 2 != length) { // If |length| of |data| does not match the expected width and height @@ -330,7 +376,6 @@ void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, 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; @@ -347,13 +392,12 @@ void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, rgb_stride, ystride, uvstride); break; } - case media::VideoCaptureCapability::kARGB: { + case media::VideoCaptureCapability::kARGB: media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width, frame_info_.height, (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; @@ -398,7 +442,7 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame( uint8* yplane = NULL; uint8* uplane = NULL; uint8* vplane = NULL; - if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane)) + if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane, 0)) return; scoped_refptr<media::VideoFrame> target_as_frame( @@ -553,6 +597,8 @@ void VideoCaptureController::DoFrameInfoOnIOThread() { frames_created = false; break; } + ResetBufferYV12(static_cast<uint8*>(shared_memory->memory()), + frame_info_.width, frame_info_.height); SharedDIB* dib = new SharedDIB(shared_memory.release()); owned_dibs_.insert(std::make_pair(i, dib)); } |