| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // found in the LICENSE file. | 2 // found in the LICENSE file. |
| 3 | 3 |
| 4 #include "content/browser/renderer_host/media/video_capture_controller.h" | 4 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 5 | 5 |
| 6 #include <set> | 6 #include <set> |
| 7 | 7 |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "content/browser/renderer_host/media/media_stream_manager.h" | 11 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 12 #include "content/browser/renderer_host/media/video_capture_manager.h" | 12 #include "content/browser/renderer_host/media/video_capture_manager.h" |
| 13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 14 #include "media/base/video_frame.h" | 14 #include "media/base/video_frame.h" |
| 15 #include "media/base/video_util.h" | 15 #include "media/base/video_util.h" |
| 16 #include "media/base/yuv_convert.h" | 16 #include "media/base/yuv_convert.h" |
| 17 | 17 |
| 18 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) | 18 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) |
| 19 #include "third_party/libyuv/include/libyuv.h" | 19 #include "third_party/libyuv/include/libyuv.h" |
| 20 #endif | 20 #endif |
| 21 | 21 |
| 22 using media::VideoCaptureCapability; | 22 using media::VideoCaptureFormat; |
| 23 | 23 |
| 24 namespace content { | 24 namespace content { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // The number of buffers that VideoCaptureBufferPool should allocate. | 28 // The number of buffers that VideoCaptureBufferPool should allocate. |
| 29 const int kNoOfBuffers = 3; | 29 const int kNoOfBuffers = 3; |
| 30 | 30 |
| 31 class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer { | 31 class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer { |
| 32 public: | 32 public: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 // VideoCaptureDevice::Client implementation. | 105 // VideoCaptureDevice::Client implementation. |
| 106 virtual scoped_refptr<Buffer> ReserveOutputBuffer( | 106 virtual scoped_refptr<Buffer> ReserveOutputBuffer( |
| 107 media::VideoFrame::Format format, | 107 media::VideoFrame::Format format, |
| 108 const gfx::Size& size) OVERRIDE; | 108 const gfx::Size& size) OVERRIDE; |
| 109 virtual void OnIncomingCapturedFrame(const uint8* data, | 109 virtual void OnIncomingCapturedFrame(const uint8* data, |
| 110 int length, | 110 int length, |
| 111 base::Time timestamp, | 111 base::Time timestamp, |
| 112 int rotation, | 112 int rotation, |
| 113 bool flip_vert, | 113 bool flip_vert, |
| 114 bool flip_horiz, | 114 bool flip_horiz, |
| 115 const VideoCaptureCapability& frame_info) | 115 const VideoCaptureFormat& frame_format) |
| 116 OVERRIDE; | 116 OVERRIDE; |
| 117 virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer, | 117 virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer, |
| 118 media::VideoFrame::Format format, | 118 media::VideoFrame::Format format, |
| 119 const gfx::Size& dimensions, | 119 const gfx::Size& dimensions, |
| 120 base::Time timestamp, | 120 base::Time timestamp, |
| 121 int frame_rate) OVERRIDE; | 121 int frame_rate) OVERRIDE; |
| 122 virtual void OnError() OVERRIDE; | 122 virtual void OnError() OVERRIDE; |
| 123 | 123 |
| 124 private: | 124 private: |
| 125 scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format, | 125 scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 return result.Pass(); | 160 return result.Pass(); |
| 161 } | 161 } |
| 162 | 162 |
| 163 void VideoCaptureController::AddClient( | 163 void VideoCaptureController::AddClient( |
| 164 const VideoCaptureControllerID& id, | 164 const VideoCaptureControllerID& id, |
| 165 VideoCaptureControllerEventHandler* event_handler, | 165 VideoCaptureControllerEventHandler* event_handler, |
| 166 base::ProcessHandle render_process, | 166 base::ProcessHandle render_process, |
| 167 const media::VideoCaptureParams& params) { | 167 const media::VideoCaptureParams& params) { |
| 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 169 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id | 169 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id |
| 170 << ", (" << params.requested_format.width | 170 << ", " << params.requested_format.frame_size.ToString() |
| 171 << ", " << params.requested_format.height | |
| 172 << ", " << params.requested_format.frame_rate | 171 << ", " << params.requested_format.frame_rate |
| 173 << ", " << params.session_id | 172 << ", " << params.session_id |
| 174 << ")"; | 173 << ")"; |
| 175 | 174 |
| 176 // Signal error in case device is already in error state. | 175 // Signal error in case device is already in error state. |
| 177 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { | 176 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
| 178 event_handler->OnError(id); | 177 event_handler->OnError(id); |
| 179 return; | 178 return; |
| 180 } | 179 } |
| 181 | 180 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 return DoReserveOutputBuffer(format, size, 0); | 255 return DoReserveOutputBuffer(format, size, 0); |
| 257 } | 256 } |
| 258 | 257 |
| 259 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( | 258 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( |
| 260 const uint8* data, | 259 const uint8* data, |
| 261 int length, | 260 int length, |
| 262 base::Time timestamp, | 261 base::Time timestamp, |
| 263 int rotation, | 262 int rotation, |
| 264 bool flip_vert, | 263 bool flip_vert, |
| 265 bool flip_horiz, | 264 bool flip_horiz, |
| 266 const VideoCaptureCapability& frame_info) { | 265 const VideoCaptureFormat& frame_format) { |
| 267 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); | 266 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); |
| 268 | 267 |
| 269 if (!frame_info.IsValid()) | 268 if (!frame_format.IsValid()) |
| 270 return; | 269 return; |
| 271 | 270 |
| 272 // Chopped pixels in width/height in case video capture device has odd | 271 // Chopped pixels in width/height in case video capture device has odd |
| 273 // numbers for width/height. | 272 // numbers for width/height. |
| 274 int chopped_width = 0; | 273 int chopped_width = 0; |
| 275 int chopped_height = 0; | 274 int chopped_height = 0; |
| 276 int new_width = frame_info.width; | 275 int new_width = frame_format.frame_size.width(); |
| 277 int new_height = frame_info.height; | 276 int new_height = frame_format.frame_size.height(); |
| 278 | 277 |
| 279 if (frame_info.width & 1) { | 278 if (new_width & 1) { |
| 280 --new_width; | 279 --new_width; |
| 281 chopped_width = 1; | 280 chopped_width = 1; |
| 282 } | 281 } |
| 283 if (frame_info.height & 1) { | 282 if (new_height & 1) { |
| 284 --new_height; | 283 --new_height; |
| 285 chopped_height = 1; | 284 chopped_height = 1; |
| 286 } | 285 } |
| 287 | 286 |
| 288 const gfx::Size dimensions(new_width, new_height); | 287 const gfx::Size dimensions(new_width, new_height); |
| 289 scoped_refptr<Buffer> buffer = | 288 scoped_refptr<Buffer> buffer = |
| 290 DoReserveOutputBuffer(media::VideoFrame::I420, dimensions, rotation); | 289 DoReserveOutputBuffer(media::VideoFrame::I420, dimensions, rotation); |
| 291 | 290 |
| 292 if (!buffer) | 291 if (!buffer) |
| 293 return; | 292 return; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 314 // new_vertical_flip = horizontal_flip XOR vertical_flip | 313 // new_vertical_flip = horizontal_flip XOR vertical_flip |
| 315 int new_rotation_angle = (rotation + 180 * flip_vert) % 360; | 314 int new_rotation_angle = (rotation + 180 * flip_vert) % 360; |
| 316 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | 315 libyuv::RotationMode rotation_mode = libyuv::kRotate0; |
| 317 if (new_rotation_angle == 90) | 316 if (new_rotation_angle == 90) |
| 318 rotation_mode = libyuv::kRotate90; | 317 rotation_mode = libyuv::kRotate90; |
| 319 else if (new_rotation_angle == 180) | 318 else if (new_rotation_angle == 180) |
| 320 rotation_mode = libyuv::kRotate180; | 319 rotation_mode = libyuv::kRotate180; |
| 321 else if (new_rotation_angle == 270) | 320 else if (new_rotation_angle == 270) |
| 322 rotation_mode = libyuv::kRotate270; | 321 rotation_mode = libyuv::kRotate270; |
| 323 | 322 |
| 324 switch (frame_info.color) { | 323 switch (frame_format.pixel_format) { |
| 325 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. | 324 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. |
| 326 break; | 325 break; |
| 327 case media::PIXEL_FORMAT_I420: | 326 case media::PIXEL_FORMAT_I420: |
| 328 DCHECK(!chopped_width && !chopped_height); | 327 DCHECK(!chopped_width && !chopped_height); |
| 329 origin_colorspace = libyuv::FOURCC_I420; | 328 origin_colorspace = libyuv::FOURCC_I420; |
| 330 break; | 329 break; |
| 331 case media::PIXEL_FORMAT_YV12: | 330 case media::PIXEL_FORMAT_YV12: |
| 332 DCHECK(!chopped_width && !chopped_height); | 331 DCHECK(!chopped_width && !chopped_height); |
| 333 origin_colorspace = libyuv::FOURCC_YV12; | 332 origin_colorspace = libyuv::FOURCC_YV12; |
| 334 break; | 333 break; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 354 origin_colorspace = libyuv::FOURCC_MJPG; | 353 origin_colorspace = libyuv::FOURCC_MJPG; |
| 355 break; | 354 break; |
| 356 default: | 355 default: |
| 357 NOTREACHED(); | 356 NOTREACHED(); |
| 358 } | 357 } |
| 359 | 358 |
| 360 int need_convert_rgb24_on_win = false; | 359 int need_convert_rgb24_on_win = false; |
| 361 #if defined(OS_WIN) | 360 #if defined(OS_WIN) |
| 362 // kRGB24 on Windows start at the bottom line and has a negative stride. This | 361 // kRGB24 on Windows start at the bottom line and has a negative stride. This |
| 363 // is not supported by libyuv, so the media API is used instead. | 362 // is not supported by libyuv, so the media API is used instead. |
| 364 if (frame_info.color == media::PIXEL_FORMAT_RGB24) { | 363 if (frame_format.pixel_format == media::PIXEL_FORMAT_RGB24) { |
| 365 // Rotation and flipping is not supported in kRGB24 and OS_WIN case. | 364 // Rotation and flipping is not supported in kRGB24 and OS_WIN case. |
| 366 DCHECK(!rotation && !flip_vert && !flip_horiz); | 365 DCHECK(!rotation && !flip_vert && !flip_horiz); |
| 367 need_convert_rgb24_on_win = true; | 366 need_convert_rgb24_on_win = true; |
| 368 } | 367 } |
| 369 #endif | 368 #endif |
| 370 if (need_convert_rgb24_on_win) { | 369 if (need_convert_rgb24_on_win) { |
| 371 int rgb_stride = -3 * (new_width + chopped_width); | 370 int rgb_stride = -3 * (new_width + chopped_width); |
| 372 const uint8* rgb_src = data + 3 * (new_width + chopped_width) * | 371 const uint8* rgb_src = data + 3 * (new_width + chopped_width) * |
| 373 (new_height - 1 + chopped_height); | 372 (new_height - 1 + chopped_height); |
| 374 media::ConvertRGB24ToYUV(rgb_src, | 373 media::ConvertRGB24ToYUV(rgb_src, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 NOTREACHED(); | 423 NOTREACHED(); |
| 425 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) | 424 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) |
| 426 BrowserThread::PostTask( | 425 BrowserThread::PostTask( |
| 427 BrowserThread::IO, | 426 BrowserThread::IO, |
| 428 FROM_HERE, | 427 FROM_HERE, |
| 429 base::Bind( | 428 base::Bind( |
| 430 &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread, | 429 &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread, |
| 431 controller_, | 430 controller_, |
| 432 buffer, | 431 buffer, |
| 433 dimensions, | 432 dimensions, |
| 434 frame_info.frame_rate, | 433 frame_format.frame_rate, |
| 435 timestamp)); | 434 timestamp)); |
| 436 } | 435 } |
| 437 | 436 |
| 438 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 437 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 439 const scoped_refptr<Buffer>& buffer, | 438 const scoped_refptr<Buffer>& buffer, |
| 440 media::VideoFrame::Format format, | 439 media::VideoFrame::Format format, |
| 441 const gfx::Size& dimensions, | 440 const gfx::Size& dimensions, |
| 442 base::Time timestamp, | 441 base::Time timestamp, |
| 443 int frame_rate) { | 442 int frame_rate) { |
| 444 // The capture pipeline expects I420 for now. | 443 // The capture pipeline expects I420 for now. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 } | 515 } |
| 517 | 516 |
| 518 void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread( | 517 void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread( |
| 519 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer, | 518 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
| 520 const gfx::Size& dimensions, | 519 const gfx::Size& dimensions, |
| 521 int frame_rate, | 520 int frame_rate, |
| 522 base::Time timestamp) { | 521 base::Time timestamp) { |
| 523 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 522 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 524 DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); | 523 DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); |
| 525 | 524 |
| 526 media::VideoCaptureFormat frame_format( | 525 VideoCaptureFormat frame_format( |
| 527 dimensions.width(), | 526 dimensions, frame_rate, media::PIXEL_FORMAT_I420); |
| 528 dimensions.height(), | |
| 529 frame_rate, | |
| 530 media::VariableResolutionVideoCaptureDevice); | |
| 531 | 527 |
| 532 int count = 0; | 528 int count = 0; |
| 533 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 529 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 534 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 530 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 535 client_it != controller_clients_.end(); ++client_it) { | 531 client_it != controller_clients_.end(); ++client_it) { |
| 536 ControllerClient* client = *client_it; | 532 ControllerClient* client = *client_it; |
| 537 if (client->session_closed) | 533 if (client->session_closed) |
| 538 continue; | 534 continue; |
| 539 | 535 |
| 540 bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; | 536 bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 } | 612 } |
| 617 return NULL; | 613 return NULL; |
| 618 } | 614 } |
| 619 | 615 |
| 620 int VideoCaptureController::GetClientCount() { | 616 int VideoCaptureController::GetClientCount() { |
| 621 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 617 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 622 return controller_clients_.size(); | 618 return controller_clients_.size(); |
| 623 } | 619 } |
| 624 | 620 |
| 625 } // namespace content | 621 } // namespace content |
| OLD | NEW |