| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/media/video_capture_controller.h" | 5 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 6 | 6 |
| 7 #include <map> |
| 7 #include <set> | 8 #include <set> |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 12 #include "content/browser/renderer_host/media/media_stream_manager.h" | 13 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 13 #include "content/browser/renderer_host/media/video_capture_manager.h" | 14 #include "content/browser/renderer_host/media/video_capture_manager.h" |
| 14 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 16 #include "gpu/command_buffer/common/mailbox_holder.h" |
| 15 #include "media/base/video_frame.h" | 17 #include "media/base/video_frame.h" |
| 16 #include "media/base/video_util.h" | 18 #include "media/base/video_util.h" |
| 17 #include "media/base/yuv_convert.h" | 19 #include "media/base/yuv_convert.h" |
| 18 | 20 |
| 19 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) | 21 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) |
| 20 #include "third_party/libyuv/include/libyuv.h" | 22 #include "third_party/libyuv/include/libyuv.h" |
| 21 #endif | 23 #endif |
| 22 | 24 |
| 23 using media::VideoCaptureFormat; | 25 using media::VideoCaptureFormat; |
| 24 | 26 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 VideoCaptureControllerEventHandler* const event_handler; | 69 VideoCaptureControllerEventHandler* const event_handler; |
| 68 | 70 |
| 69 // Handle to the render process that will receive the capture buffers. | 71 // Handle to the render process that will receive the capture buffers. |
| 70 const base::ProcessHandle render_process_handle; | 72 const base::ProcessHandle render_process_handle; |
| 71 const media::VideoCaptureSessionId session_id; | 73 const media::VideoCaptureSessionId session_id; |
| 72 const media::VideoCaptureParams parameters; | 74 const media::VideoCaptureParams parameters; |
| 73 | 75 |
| 74 // Buffers that are currently known to this client. | 76 // Buffers that are currently known to this client. |
| 75 std::set<int> known_buffers; | 77 std::set<int> known_buffers; |
| 76 | 78 |
| 77 // Buffers currently held by this client. | 79 // Buffers currently held by this client, and syncpoint callback to call when |
| 78 std::set<int> active_buffers; | 80 // they are returned from the client. |
| 81 typedef std::map<int, scoped_refptr<media::VideoFrame> > ActiveBufferMap; |
| 82 ActiveBufferMap active_buffers; |
| 79 | 83 |
| 80 // State of capture session, controlled by VideoCaptureManager directly. This | 84 // State of capture session, controlled by VideoCaptureManager directly. This |
| 81 // transitions to true as soon as StopSession() occurs, at which point the | 85 // transitions to true as soon as StopSession() occurs, at which point the |
| 82 // client is sent an OnEnded() event. However, because the client retains a | 86 // client is sent an OnEnded() event. However, because the client retains a |
| 83 // VideoCaptureController* pointer, its ControllerClient entry lives on until | 87 // VideoCaptureController* pointer, its ControllerClient entry lives on until |
| 84 // it unregisters itself via RemoveClient(), which may happen asynchronously. | 88 // it unregisters itself via RemoveClient(), which may happen asynchronously. |
| 85 // | 89 // |
| 86 // TODO(nick): If we changed the semantics of VideoCaptureHost so that | 90 // TODO(nick): If we changed the semantics of VideoCaptureHost so that |
| 87 // OnEnded() events were processed synchronously (with the RemoveClient() done | 91 // OnEnded() events were processed synchronously (with the RemoveClient() done |
| 88 // implicitly), we could avoid tracking this state here in the Controller, and | 92 // implicitly), we could avoid tracking this state here in the Controller, and |
| (...skipping 14 matching lines...) Expand all Loading... |
| 103 public: | 107 public: |
| 104 explicit VideoCaptureDeviceClient( | 108 explicit VideoCaptureDeviceClient( |
| 105 const base::WeakPtr<VideoCaptureController>& controller, | 109 const base::WeakPtr<VideoCaptureController>& controller, |
| 106 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool); | 110 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool); |
| 107 virtual ~VideoCaptureDeviceClient(); | 111 virtual ~VideoCaptureDeviceClient(); |
| 108 | 112 |
| 109 // VideoCaptureDevice::Client implementation. | 113 // VideoCaptureDevice::Client implementation. |
| 110 virtual scoped_refptr<Buffer> ReserveOutputBuffer( | 114 virtual scoped_refptr<Buffer> ReserveOutputBuffer( |
| 111 media::VideoFrame::Format format, | 115 media::VideoFrame::Format format, |
| 112 const gfx::Size& size) OVERRIDE; | 116 const gfx::Size& size) OVERRIDE; |
| 113 virtual void OnIncomingCapturedFrame(const uint8* data, | 117 virtual void OnIncomingCapturedData(const uint8* data, |
| 114 int length, | 118 int length, |
| 115 base::TimeTicks timestamp, | 119 const VideoCaptureFormat& frame_format, |
| 116 int rotation, | 120 int rotation, |
| 117 const VideoCaptureFormat& frame_format) | 121 base::TimeTicks timestamp) OVERRIDE; |
| 118 OVERRIDE; | 122 virtual void OnIncomingCapturedVideoFrame( |
| 119 virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer, | 123 const scoped_refptr<Buffer>& buffer, |
| 120 media::VideoFrame::Format format, | 124 const VideoCaptureFormat& buffer_format, |
| 121 const gfx::Size& dimensions, | 125 const scoped_refptr<media::VideoFrame>& frame, |
| 122 base::TimeTicks timestamp, | 126 base::TimeTicks timestamp) OVERRIDE; |
| 123 int frame_rate) OVERRIDE; | |
| 124 virtual void OnError(const std::string& reason) OVERRIDE; | 127 virtual void OnError(const std::string& reason) OVERRIDE; |
| 125 | 128 |
| 126 private: | 129 private: |
| 127 scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format, | 130 scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format, |
| 128 const gfx::Size& dimensions); | 131 const gfx::Size& dimensions); |
| 129 | 132 |
| 130 // The controller to which we post events. | 133 // The controller to which we post events. |
| 131 const base::WeakPtr<VideoCaptureController> controller_; | 134 const base::WeakPtr<VideoCaptureController> controller_; |
| 132 | 135 |
| 133 // The pool of shared-memory buffers used for capturing. | 136 // The pool of shared-memory buffers used for capturing. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 const VideoCaptureControllerID& id, | 202 const VideoCaptureControllerID& id, |
| 200 VideoCaptureControllerEventHandler* event_handler) { | 203 VideoCaptureControllerEventHandler* event_handler) { |
| 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 202 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id; | 205 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id; |
| 203 | 206 |
| 204 ControllerClient* client = FindClient(id, event_handler, controller_clients_); | 207 ControllerClient* client = FindClient(id, event_handler, controller_clients_); |
| 205 if (!client) | 208 if (!client) |
| 206 return kInvalidMediaCaptureSessionId; | 209 return kInvalidMediaCaptureSessionId; |
| 207 | 210 |
| 208 // Take back all buffers held by the |client|. | 211 // Take back all buffers held by the |client|. |
| 209 for (std::set<int>::iterator buffer_it = client->active_buffers.begin(); | 212 for (ControllerClient::ActiveBufferMap::iterator buffer_it = |
| 213 client->active_buffers.begin(); |
| 210 buffer_it != client->active_buffers.end(); | 214 buffer_it != client->active_buffers.end(); |
| 211 ++buffer_it) { | 215 ++buffer_it) { |
| 212 int buffer_id = *buffer_it; | 216 buffer_pool_->RelinquishConsumerHold(buffer_it->first, 1); |
| 213 buffer_pool_->RelinquishConsumerHold(buffer_id, 1); | |
| 214 } | 217 } |
| 215 client->active_buffers.clear(); | 218 client->active_buffers.clear(); |
| 216 | 219 |
| 217 int session_id = client->session_id; | 220 int session_id = client->session_id; |
| 218 controller_clients_.remove(client); | 221 controller_clients_.remove(client); |
| 219 delete client; | 222 delete client; |
| 220 | 223 |
| 221 return session_id; | 224 return session_id; |
| 222 } | 225 } |
| 223 | 226 |
| 224 void VideoCaptureController::StopSession(int session_id) { | 227 void VideoCaptureController::StopSession(int session_id) { |
| 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 226 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; | 229 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; |
| 227 | 230 |
| 228 ControllerClient* client = FindClient(session_id, controller_clients_); | 231 ControllerClient* client = FindClient(session_id, controller_clients_); |
| 229 | 232 |
| 230 if (client) { | 233 if (client) { |
| 231 client->session_closed = true; | 234 client->session_closed = true; |
| 232 client->event_handler->OnEnded(client->controller_id); | 235 client->event_handler->OnEnded(client->controller_id); |
| 233 } | 236 } |
| 234 } | 237 } |
| 235 | 238 |
| 236 void VideoCaptureController::ReturnBuffer( | 239 void VideoCaptureController::ReturnBuffer( |
| 237 const VideoCaptureControllerID& id, | 240 const VideoCaptureControllerID& id, |
| 238 VideoCaptureControllerEventHandler* event_handler, | 241 VideoCaptureControllerEventHandler* event_handler, |
| 239 int buffer_id) { | 242 int buffer_id, |
| 243 uint32 sync_point) { |
| 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 241 | 245 |
| 242 ControllerClient* client = FindClient(id, event_handler, controller_clients_); | 246 ControllerClient* client = FindClient(id, event_handler, controller_clients_); |
| 243 | 247 |
| 244 // If this buffer is not held by this client, or this client doesn't exist | 248 // If this buffer is not held by this client, or this client doesn't exist |
| 245 // in controller, do nothing. | 249 // in controller, do nothing. |
| 246 if (!client || !client->active_buffers.erase(buffer_id)) { | 250 ControllerClient::ActiveBufferMap::iterator iter; |
| 251 if (!client || (iter = client->active_buffers.find(buffer_id)) == |
| 252 client->active_buffers.end()) { |
| 247 NOTREACHED(); | 253 NOTREACHED(); |
| 248 return; | 254 return; |
| 249 } | 255 } |
| 256 scoped_refptr<media::VideoFrame> frame = iter->second; |
| 257 client->active_buffers.erase(iter); |
| 258 |
| 259 if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) |
| 260 frame->mailbox_holder()->sync_point = sync_point; |
| 250 | 261 |
| 251 buffer_pool_->RelinquishConsumerHold(buffer_id, 1); | 262 buffer_pool_->RelinquishConsumerHold(buffer_id, 1); |
| 252 } | 263 } |
| 253 | 264 |
| 254 const media::VideoCaptureFormat& | 265 const media::VideoCaptureFormat& |
| 255 VideoCaptureController::GetVideoCaptureFormat() const { | 266 VideoCaptureController::GetVideoCaptureFormat() const { |
| 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 257 return video_capture_format_; | 268 return video_capture_format_; |
| 258 } | 269 } |
| 259 | 270 |
| 260 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> | 271 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> |
| 261 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer( | 272 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 262 media::VideoFrame::Format format, | 273 media::VideoFrame::Format format, |
| 263 const gfx::Size& size) { | 274 const gfx::Size& size) { |
| 264 return DoReserveOutputBuffer(format, size); | 275 return DoReserveOutputBuffer(format, size); |
| 265 } | 276 } |
| 266 | 277 |
| 267 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( | 278 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData( |
| 268 const uint8* data, | 279 const uint8* data, |
| 269 int length, | 280 int length, |
| 270 base::TimeTicks timestamp, | 281 const VideoCaptureFormat& frame_format, |
| 271 int rotation, | 282 int rotation, |
| 272 const VideoCaptureFormat& frame_format) { | 283 base::TimeTicks timestamp) { |
| 273 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); | 284 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedData"); |
| 274 | 285 |
| 275 if (!frame_format.IsValid()) | 286 if (!frame_format.IsValid()) |
| 276 return; | 287 return; |
| 277 | 288 |
| 278 // Chopped pixels in width/height in case video capture device has odd | 289 // Chopped pixels in width/height in case video capture device has odd |
| 279 // numbers for width/height. | 290 // numbers for width/height. |
| 280 int chopped_width = 0; | 291 int chopped_width = 0; |
| 281 int chopped_height = 0; | 292 int chopped_height = 0; |
| 282 int new_unrotated_width = frame_format.frame_size.width(); | 293 int new_unrotated_width = frame_format.frame_size.width(); |
| 283 int new_unrotated_height = frame_format.frame_size.height(); | 294 int new_unrotated_height = frame_format.frame_size.height(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 296 if (rotation == 90 || rotation == 270) { | 307 if (rotation == 90 || rotation == 270) { |
| 297 destination_width = new_unrotated_height; | 308 destination_width = new_unrotated_height; |
| 298 destination_height = new_unrotated_width; | 309 destination_height = new_unrotated_width; |
| 299 } | 310 } |
| 300 const gfx::Size dimensions(destination_width, destination_height); | 311 const gfx::Size dimensions(destination_width, destination_height); |
| 301 scoped_refptr<Buffer> buffer = | 312 scoped_refptr<Buffer> buffer = |
| 302 DoReserveOutputBuffer(media::VideoFrame::I420, dimensions); | 313 DoReserveOutputBuffer(media::VideoFrame::I420, dimensions); |
| 303 | 314 |
| 304 if (!buffer) | 315 if (!buffer) |
| 305 return; | 316 return; |
| 317 uint8* yplane = NULL; |
| 306 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) | 318 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) |
| 307 bool flip = false; | 319 bool flip = false; |
| 308 uint8* yplane = reinterpret_cast<uint8*>(buffer->data()); | 320 yplane = reinterpret_cast<uint8*>(buffer->data()); |
| 309 uint8* uplane = | 321 uint8* uplane = |
| 310 yplane + | 322 yplane + |
| 311 media::VideoFrame::PlaneAllocationSize( | 323 media::VideoFrame::PlaneAllocationSize( |
| 312 media::VideoFrame::I420, media::VideoFrame::kYPlane, dimensions); | 324 media::VideoFrame::I420, media::VideoFrame::kYPlane, dimensions); |
| 313 uint8* vplane = | 325 uint8* vplane = |
| 314 uplane + | 326 uplane + |
| 315 media::VideoFrame::PlaneAllocationSize( | 327 media::VideoFrame::PlaneAllocationSize( |
| 316 media::VideoFrame::I420, media::VideoFrame::kUPlane, dimensions); | 328 media::VideoFrame::I420, media::VideoFrame::kUPlane, dimensions); |
| 317 int yplane_stride = dimensions.width(); | 329 int yplane_stride = dimensions.width(); |
| 318 int uv_plane_stride = yplane_stride / 2; | 330 int uv_plane_stride = yplane_stride / 2; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 new_unrotated_width, | 399 new_unrotated_width, |
| 388 new_unrotated_height, | 400 new_unrotated_height, |
| 389 rotation_mode, | 401 rotation_mode, |
| 390 origin_colorspace); | 402 origin_colorspace); |
| 391 #else | 403 #else |
| 392 // Libyuv is not linked in for Android WebView builds, but video capture is | 404 // Libyuv is not linked in for Android WebView builds, but video capture is |
| 393 // not used in those builds either. Whenever libyuv is added in that build, | 405 // not used in those builds either. Whenever libyuv is added in that build, |
| 394 // address all these #ifdef parts, see http://crbug.com/299611 . | 406 // address all these #ifdef parts, see http://crbug.com/299611 . |
| 395 NOTREACHED(); | 407 NOTREACHED(); |
| 396 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) | 408 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) |
| 409 VideoCaptureFormat format( |
| 410 dimensions, frame_format.frame_rate, media::PIXEL_FORMAT_I420); |
| 411 scoped_refptr<media::VideoFrame> frame = |
| 412 media::VideoFrame::WrapExternalPackedMemory( |
| 413 media::VideoFrame::I420, |
| 414 dimensions, |
| 415 gfx::Rect(dimensions), |
| 416 dimensions, |
| 417 yplane, |
| 418 media::VideoFrame::AllocationSize(media::VideoFrame::I420, |
| 419 dimensions), |
| 420 base::SharedMemory::NULLHandle(), |
| 421 base::TimeDelta(), |
| 422 base::Closure()); |
| 423 DCHECK(frame); |
| 397 BrowserThread::PostTask( | 424 BrowserThread::PostTask( |
| 398 BrowserThread::IO, | 425 BrowserThread::IO, |
| 399 FROM_HERE, | 426 FROM_HERE, |
| 400 base::Bind( | 427 base::Bind( |
| 401 &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread, | 428 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
| 402 controller_, | 429 controller_, |
| 403 buffer, | 430 buffer, |
| 404 dimensions, | 431 format, |
| 405 frame_format.frame_rate, | 432 frame, |
| 406 timestamp)); | 433 timestamp)); |
| 407 } | 434 } |
| 408 | 435 |
| 409 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 436 void |
| 437 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
| 410 const scoped_refptr<Buffer>& buffer, | 438 const scoped_refptr<Buffer>& buffer, |
| 411 media::VideoFrame::Format format, | 439 const VideoCaptureFormat& buffer_format, |
| 412 const gfx::Size& dimensions, | 440 const scoped_refptr<media::VideoFrame>& frame, |
| 413 base::TimeTicks timestamp, | 441 base::TimeTicks timestamp) { |
| 414 int frame_rate) { | |
| 415 // The capture pipeline expects I420 for now. | |
| 416 DCHECK_EQ(format, media::VideoFrame::I420) | |
| 417 << "Non-I420 output buffer returned"; | |
| 418 | |
| 419 BrowserThread::PostTask( | 442 BrowserThread::PostTask( |
| 420 BrowserThread::IO, | 443 BrowserThread::IO, |
| 421 FROM_HERE, | 444 FROM_HERE, |
| 422 base::Bind( | 445 base::Bind( |
| 423 &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread, | 446 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
| 424 controller_, | 447 controller_, |
| 425 buffer, | 448 buffer, |
| 426 dimensions, | 449 buffer_format, |
| 427 frame_rate, | 450 frame, |
| 428 timestamp)); | 451 timestamp)); |
| 429 } | 452 } |
| 430 | 453 |
| 431 void VideoCaptureController::VideoCaptureDeviceClient::OnError( | 454 void VideoCaptureController::VideoCaptureDeviceClient::OnError( |
| 432 const std::string& reason) { | 455 const std::string& reason) { |
| 433 MediaStreamManager::SendMessageToNativeLog( | 456 MediaStreamManager::SendMessageToNativeLog( |
| 434 "Error on video capture: " + reason); | 457 "Error on video capture: " + reason); |
| 435 BrowserThread::PostTask(BrowserThread::IO, | 458 BrowserThread::PostTask(BrowserThread::IO, |
| 436 FROM_HERE, | 459 FROM_HERE, |
| 437 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); | 460 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); |
| 438 } | 461 } |
| 439 | 462 |
| 440 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> | 463 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> |
| 441 VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer( | 464 VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer( |
| 442 media::VideoFrame::Format format, | 465 media::VideoFrame::Format format, |
| 443 const gfx::Size& dimensions) { | 466 const gfx::Size& dimensions) { |
| 444 // The capture pipeline expects I420 for now. | 467 size_t frame_bytes = 0; |
| 445 DCHECK_EQ(format, media::VideoFrame::I420) | 468 if (format == media::VideoFrame::NATIVE_TEXTURE) { |
| 446 << "Non-I420 output buffer requested"; | 469 DCHECK_EQ(dimensions.width(), 0); |
| 470 DCHECK_EQ(dimensions.height(), 0); |
| 471 } else { |
| 472 // The capture pipeline expects I420 for now. |
| 473 DCHECK_EQ(format, media::VideoFrame::I420) |
| 474 << "Non-I420 output buffer format " << format << " requested"; |
| 475 frame_bytes = media::VideoFrame::AllocationSize(format, dimensions); |
| 476 } |
| 447 | 477 |
| 448 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 478 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
| 449 const size_t frame_bytes = | |
| 450 media::VideoFrame::AllocationSize(format, dimensions); | |
| 451 | |
| 452 int buffer_id = | 479 int buffer_id = |
| 453 buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); | 480 buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); |
| 454 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 481 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 455 return NULL; | 482 return NULL; |
| 456 void* data; | 483 void* data; |
| 457 size_t size; | 484 size_t size; |
| 458 buffer_pool_->GetBufferInfo(buffer_id, &data, &size); | 485 buffer_pool_->GetBufferInfo(buffer_id, &data, &size); |
| 459 | 486 |
| 460 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( | 487 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( |
| 461 new PoolBuffer(buffer_pool_, buffer_id, data, size)); | 488 new PoolBuffer(buffer_pool_, buffer_id, data, size)); |
| 462 | 489 |
| 463 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { | 490 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
| 464 BrowserThread::PostTask(BrowserThread::IO, | 491 BrowserThread::PostTask(BrowserThread::IO, |
| 465 FROM_HERE, | 492 FROM_HERE, |
| 466 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, | 493 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, |
| 467 controller_, buffer_id_to_drop)); | 494 controller_, buffer_id_to_drop)); |
| 468 } | 495 } |
| 469 | 496 |
| 470 return output_buffer; | 497 return output_buffer; |
| 471 } | 498 } |
| 472 | 499 |
| 473 VideoCaptureController::~VideoCaptureController() { | 500 VideoCaptureController::~VideoCaptureController() { |
| 474 STLDeleteContainerPointers(controller_clients_.begin(), | 501 STLDeleteContainerPointers(controller_clients_.begin(), |
| 475 controller_clients_.end()); | 502 controller_clients_.end()); |
| 476 } | 503 } |
| 477 | 504 |
| 478 void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread( | 505 void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( |
| 479 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer, | 506 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, |
| 480 const gfx::Size& dimensions, | 507 const media::VideoCaptureFormat& buffer_format, |
| 481 int frame_rate, | 508 const scoped_refptr<media::VideoFrame>& frame, |
| 482 base::TimeTicks timestamp) { | 509 base::TimeTicks timestamp) { |
| 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 484 DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); | 511 DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); |
| 485 | 512 |
| 486 VideoCaptureFormat frame_format( | |
| 487 dimensions, frame_rate, media::PIXEL_FORMAT_I420); | |
| 488 | |
| 489 int count = 0; | 513 int count = 0; |
| 490 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 514 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 491 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 515 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 492 client_it != controller_clients_.end(); ++client_it) { | 516 client_it != controller_clients_.end(); ++client_it) { |
| 493 ControllerClient* client = *client_it; | 517 ControllerClient* client = *client_it; |
| 494 if (client->session_closed) | 518 if (client->session_closed) |
| 495 continue; | 519 continue; |
| 496 | 520 |
| 497 bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; | 521 if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { |
| 498 if (is_new_buffer) { | 522 client->event_handler->OnMailboxBufferReady(client->controller_id, |
| 499 // On the first use of a buffer on a client, share the memory handle. | 523 buffer->id(), |
| 500 size_t memory_size = 0; | 524 *frame->mailbox_holder(), |
| 501 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( | 525 buffer_format, |
| 502 buffer->id(), client->render_process_handle, &memory_size); | 526 timestamp); |
| 503 client->event_handler->OnBufferCreated( | 527 } else { |
| 504 client->controller_id, remote_handle, memory_size, buffer->id()); | 528 bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; |
| 529 if (is_new_buffer) { |
| 530 // On the first use of a buffer on a client, share the memory handle. |
| 531 size_t memory_size = 0; |
| 532 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( |
| 533 buffer->id(), client->render_process_handle, &memory_size); |
| 534 client->event_handler->OnBufferCreated( |
| 535 client->controller_id, remote_handle, memory_size, buffer->id()); |
| 536 } |
| 537 |
| 538 client->event_handler->OnBufferReady( |
| 539 client->controller_id, buffer->id(), buffer_format, timestamp); |
| 505 } | 540 } |
| 506 | 541 |
| 507 client->event_handler->OnBufferReady( | 542 bool inserted = |
| 508 client->controller_id, buffer->id(), timestamp, frame_format); | 543 client->active_buffers.insert(std::make_pair(buffer->id(), frame)) |
| 509 bool inserted = client->active_buffers.insert(buffer->id()).second; | 544 .second; |
| 510 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id(); | 545 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id(); |
| 511 count++; | 546 count++; |
| 512 } | 547 } |
| 513 } | 548 } |
| 514 | 549 |
| 515 buffer_pool_->HoldForConsumers(buffer->id(), count); | 550 buffer_pool_->HoldForConsumers(buffer->id(), count); |
| 516 } | 551 } |
| 517 | 552 |
| 518 void VideoCaptureController::DoErrorOnIOThread() { | 553 void VideoCaptureController::DoErrorOnIOThread() { |
| 519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 } | 608 } |
| 574 return NULL; | 609 return NULL; |
| 575 } | 610 } |
| 576 | 611 |
| 577 int VideoCaptureController::GetClientCount() { | 612 int VideoCaptureController::GetClientCount() { |
| 578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 613 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 579 return controller_clients_.size(); | 614 return controller_clients_.size(); |
| 580 } | 615 } |
| 581 | 616 |
| 582 } // namespace content | 617 } // namespace content |
| OLD | NEW |