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 <set> | 7 #include <set> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "content/browser/renderer_host/media/media_stream_manager.h" | 12 #include "content/browser/renderer_host/media/media_stream_manager.h" |
13 #include "content/browser/renderer_host/media/video_capture_manager.h" | 13 #include "content/browser/renderer_host/media/video_capture_manager.h" |
14 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
15 #include "media/base/encoded_bitstream_buffer.h" | |
15 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
16 #include "media/base/video_util.h" | 17 #include "media/base/video_util.h" |
17 #include "media/base/yuv_convert.h" | 18 #include "media/base/yuv_convert.h" |
18 | 19 |
19 #if !defined(OS_IOS) && !defined(OS_ANDROID) | 20 #if !defined(OS_IOS) && !defined(OS_ANDROID) |
20 #include "third_party/libyuv/include/libyuv.h" | 21 #include "third_party/libyuv/include/libyuv.h" |
21 #endif | 22 #endif |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 | 80 |
80 // State of capture session, controlled by VideoCaptureManager directly. | 81 // State of capture session, controlled by VideoCaptureManager directly. |
81 bool session_closed; | 82 bool session_closed; |
82 }; | 83 }; |
83 | 84 |
84 VideoCaptureController::VideoCaptureController( | 85 VideoCaptureController::VideoCaptureController( |
85 VideoCaptureManager* video_capture_manager) | 86 VideoCaptureManager* video_capture_manager) |
86 : chopped_width_(0), | 87 : chopped_width_(0), |
87 chopped_height_(0), | 88 chopped_height_(0), |
88 frame_info_available_(false), | 89 frame_info_available_(false), |
90 encoded_frame_info_available_(false), | |
89 video_capture_manager_(video_capture_manager), | 91 video_capture_manager_(video_capture_manager), |
90 device_in_use_(false), | 92 device_in_use_(false), |
91 state_(VIDEO_CAPTURE_STATE_STOPPED) { | 93 state_(VIDEO_CAPTURE_STATE_STOPPED) { |
92 memset(¤t_params_, 0, sizeof(current_params_)); | 94 memset(¤t_params_, 0, sizeof(current_params_)); |
93 } | 95 } |
94 | 96 |
95 void VideoCaptureController::StartCapture( | 97 void VideoCaptureController::StartCapture( |
96 const VideoCaptureControllerID& id, | 98 const VideoCaptureControllerID& id, |
97 VideoCaptureControllerEventHandler* event_handler, | 99 VideoCaptureControllerEventHandler* event_handler, |
98 base::ProcessHandle render_process, | 100 base::ProcessHandle render_process, |
(...skipping 23 matching lines...) Expand all Loading... | |
122 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 124 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
123 // TODO(wjia): Temporarily disable restarting till client supports resampling. | 125 // TODO(wjia): Temporarily disable restarting till client supports resampling. |
124 #if 0 | 126 #if 0 |
125 // This client has higher resolution than what is currently requested. | 127 // This client has higher resolution than what is currently requested. |
126 // Need restart capturing. | 128 // Need restart capturing. |
127 if (params.width > current_params_.width || | 129 if (params.width > current_params_.width || |
128 params.height > current_params_.height) { | 130 params.height > current_params_.height) { |
129 video_capture_manager_->Stop(current_params_.session_id, | 131 video_capture_manager_->Stop(current_params_.session_id, |
130 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); | 132 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); |
131 frame_info_available_ = false; | 133 frame_info_available_ = false; |
134 encoded_frame_info_available_ = false; | |
132 state_ = VIDEO_CAPTURE_STATE_STOPPING; | 135 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
133 pending_clients_.push_back(client); | 136 pending_clients_.push_back(client); |
134 return; | 137 return; |
135 } | 138 } |
136 #endif | 139 #endif |
137 | 140 |
138 // This client's resolution is no larger than what's currently requested. | 141 // This client's resolution is no larger than what's currently requested. |
139 // When frame_info has been returned by device, send them to client. | 142 // When frame_info has been returned by device, send them to client. |
140 if (frame_info_available_) { | 143 if (frame_info_available_ || encoded_frame_info_available_) { |
141 SendFrameInfoAndBuffers(client); | 144 SendFrameInfoAndBuffers(client); |
142 } | 145 } |
143 controller_clients_.push_back(client); | 146 controller_clients_.push_back(client); |
144 return; | 147 return; |
145 } | 148 } |
146 | 149 |
147 // In case the device is in the middle of stopping, put the client in | 150 // In case the device is in the middle of stopping, put the client in |
148 // pending queue. | 151 // pending queue. |
149 if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 152 if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
150 pending_clients_.push_back(client); | 153 pending_clients_.push_back(client); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 delete client; | 195 delete client; |
193 controller_clients_.remove(client); | 196 controller_clients_.remove(client); |
194 | 197 |
195 // No more clients. Stop device. | 198 // No more clients. Stop device. |
196 if (controller_clients_.empty() && | 199 if (controller_clients_.empty() && |
197 (state_ == VIDEO_CAPTURE_STATE_STARTED || | 200 (state_ == VIDEO_CAPTURE_STATE_STARTED || |
198 state_ == VIDEO_CAPTURE_STATE_ERROR)) { | 201 state_ == VIDEO_CAPTURE_STATE_ERROR)) { |
199 video_capture_manager_->Stop(session_id, | 202 video_capture_manager_->Stop(session_id, |
200 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); | 203 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); |
201 frame_info_available_ = false; | 204 frame_info_available_ = false; |
205 encoded_frame_info_available_ = false; | |
202 state_ = VIDEO_CAPTURE_STATE_STOPPING; | 206 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
203 } | 207 } |
204 } | 208 } |
205 | 209 |
206 void VideoCaptureController::StopSession( | 210 void VideoCaptureController::StopSession( |
207 int session_id) { | 211 int session_id) { |
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
209 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; | 213 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; |
210 | 214 |
211 ControllerClient* client = FindClient(session_id, pending_clients_); | 215 ControllerClient* client = FindClient(session_id, pending_clients_); |
(...skipping 26 matching lines...) Expand all Loading... | |
238 | 242 |
239 // When all buffers have been returned by clients and device has been | 243 // When all buffers have been returned by clients and device has been |
240 // called to stop, check if restart is needed. This could happen when | 244 // called to stop, check if restart is needed. This could happen when |
241 // capture needs to be restarted due to resolution change. | 245 // capture needs to be restarted due to resolution change. |
242 if (!buffer_pool_->IsAnyBufferHeldForConsumers() && | 246 if (!buffer_pool_->IsAnyBufferHeldForConsumers() && |
243 state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 247 state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
244 PostStopping(); | 248 PostStopping(); |
245 } | 249 } |
246 } | 250 } |
247 | 251 |
248 scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveOutputBuffer() { | 252 void VideoCaptureController::TryConfigureEncodedBitstream( |
249 base::AutoLock lock(buffer_pool_lock_); | 253 const media::RuntimeVideoEncodingParameters& params) { |
250 if (!buffer_pool_.get()) | 254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
251 return NULL; | 255 video_capture_manager_->TryConfigureEncodedBitstream( |
252 return ReserveI420VideoFrame(buffer_pool_, gfx::Size(frame_info_.width, | 256 current_params_.session_id, |
253 frame_info_.height)); | 257 params); |
254 } | 258 } |
255 | 259 |
256 // Implements VideoCaptureDevice::EventHandler. | 260 // Implements VideoCaptureDevice::EventHandler. |
257 // OnIncomingCapturedFrame is called the thread running the capture device. | 261 // OnIncomingCapturedFrame is called the thread running the capture device. |
258 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. | 262 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. |
259 void VideoCaptureController::OnIncomingCapturedFrame( | 263 void VideoCaptureController::OnIncomingCapturedFrame( |
260 const uint8* data, | 264 const uint8* data, |
261 int length, | 265 int length, |
262 base::Time timestamp, | 266 base::Time timestamp, |
263 int rotation, | 267 int rotation, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 libyuv::kRotate0, libyuv::FOURCC_MJPG); | 354 libyuv::kRotate0, libyuv::FOURCC_MJPG); |
351 break; | 355 break; |
352 } | 356 } |
353 #endif | 357 #endif |
354 default: | 358 default: |
355 NOTREACHED(); | 359 NOTREACHED(); |
356 } | 360 } |
357 | 361 |
358 BrowserThread::PostTask(BrowserThread::IO, | 362 BrowserThread::PostTask(BrowserThread::IO, |
359 FROM_HERE, | 363 FROM_HERE, |
360 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, | 364 base::Bind( |
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
fwiw here and elsewhere you can move and the prece
| |
361 this, dst, timestamp)); | 365 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
366 this, | |
367 dst, | |
368 timestamp)); | |
362 } | 369 } |
363 | 370 |
364 // OnIncomingCapturedVideoFrame is called the thread running the capture device. | 371 // OnIncomingCapturedVideoFrame is called the thread running the capture device. |
365 void VideoCaptureController::OnIncomingCapturedVideoFrame( | 372 void VideoCaptureController::OnIncomingCapturedVideoFrame( |
366 const scoped_refptr<media::VideoFrame>& frame, | 373 const scoped_refptr<media::VideoFrame>& frame, |
367 base::Time timestamp) { | 374 base::Time timestamp) { |
368 | 375 |
369 scoped_refptr<media::VideoFrame> target; | 376 scoped_refptr<media::VideoFrame> target; |
370 { | 377 { |
371 base::AutoLock lock(buffer_pool_lock_); | 378 base::AutoLock lock(buffer_pool_lock_); |
372 | 379 |
373 if (!buffer_pool_.get()) | 380 if (!buffer_pool_.get()) |
374 return; | 381 return; |
375 | 382 |
376 // If this is a frame that belongs to the buffer pool, we can forward it | 383 // If this is a frame that belongs to the buffer pool, we can forward it |
377 // directly to the IO thread and be done. | 384 // directly to the IO thread and be done. |
378 if (buffer_pool_->RecognizeReservedBuffer( | 385 if (buffer_pool_->RecognizeReservedBuffer( |
379 frame->shared_memory_handle()) >= 0) { | 386 frame->shared_memory_handle()) >= 0) { |
380 BrowserThread::PostTask(BrowserThread::IO, | 387 BrowserThread::PostTask(BrowserThread::IO, |
381 FROM_HERE, | 388 FROM_HERE, |
382 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, | 389 base::Bind( |
383 this, frame, timestamp)); | 390 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
391 this, | |
392 frame, | |
393 timestamp)); | |
384 return; | 394 return; |
385 } | 395 } |
386 // Otherwise, this is a frame that belongs to the caller, and we must copy | 396 // Otherwise, this is a frame that belongs to the caller, and we must copy |
387 // it to a frame from the buffer pool. | 397 // it to a frame from the buffer pool. |
388 target = ReserveI420VideoFrame(buffer_pool_, gfx::Size(frame_info_.width, | 398 target = ReserveI420VideoFrame(buffer_pool_, gfx::Size(frame_info_.width, |
389 frame_info_.height)); | 399 frame_info_.height)); |
390 } | 400 } |
391 | 401 |
392 if (!target.get()) | 402 if (!target.get()) |
393 return; | 403 return; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 target->coded_size().height(), | 478 target->coded_size().height(), |
469 frame->stride(kRGBPlane), | 479 frame->stride(kRGBPlane), |
470 target->stride(kYPlane), | 480 target->stride(kYPlane), |
471 target->stride(kUPlane)); | 481 target->stride(kUPlane)); |
472 break; | 482 break; |
473 } | 483 } |
474 } | 484 } |
475 | 485 |
476 BrowserThread::PostTask(BrowserThread::IO, | 486 BrowserThread::PostTask(BrowserThread::IO, |
477 FROM_HERE, | 487 FROM_HERE, |
478 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, | 488 base::Bind( |
479 this, target, timestamp)); | 489 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
490 this, | |
491 target, | |
492 timestamp)); | |
493 } | |
494 | |
495 void VideoCaptureController::OnIncomingCapturedEncodedBitstreamBuffer( | |
496 const scoped_refptr<media::EncodedBitstreamBuffer>& buffer, | |
497 size_t data_size, | |
498 base::Time timestamp) { | |
499 | |
500 scoped_refptr<media::EncodedBitstreamBuffer> target; | |
501 { | |
502 base::AutoLock lock(buffer_pool_lock_); | |
503 if (!buffer_pool_.get()) | |
504 return; | |
505 // If this is a frame that belongs to the buffer pool, we can forward it | |
506 // directly to the IO thread and be done. | |
507 if (buffer_pool_->RecognizeReservedBuffer( | |
508 buffer->shared_memory_handle()) >= 0) { | |
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
indent
| |
509 BrowserThread::PostTask(BrowserThread::IO, | |
510 FROM_HERE, | |
511 base::Bind( | |
512 &VideoCaptureController:: | |
513 DoIncomingCapturedEncodedBitstreamBufferOnIOThread, | |
514 this, | |
515 buffer, | |
516 data_size, | |
517 timestamp)); | |
518 return; | |
519 } | |
520 // Otherwise, this is a frame that belongs to the caller, and we must copy | |
521 // it to a frame from the buffer pool. | |
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
Is it important to support this "legacy" case for
| |
522 target = ReserveOutputEncodedBitstreamBuffer(); | |
523 } | |
524 | |
525 if (!target.get()) | |
526 return; | |
527 if (data_size > target->size()) | |
528 return; | |
529 memcpy(buffer_pool_->GetMemory(target->buffer_id()), | |
530 buffer->buffer(), data_size); | |
531 BrowserThread::PostTask(BrowserThread::IO, | |
532 FROM_HERE, | |
533 base::Bind( | |
534 &VideoCaptureController:: | |
535 DoIncomingCapturedEncodedBitstreamBufferOnIOThread, | |
536 this, | |
537 target, | |
538 data_size, | |
539 timestamp)); | |
480 } | 540 } |
481 | 541 |
482 void VideoCaptureController::OnError() { | 542 void VideoCaptureController::OnError() { |
483 BrowserThread::PostTask(BrowserThread::IO, | 543 BrowserThread::PostTask(BrowserThread::IO, |
484 FROM_HERE, | 544 FROM_HERE, |
485 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); | 545 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); |
486 } | 546 } |
487 | 547 |
488 void VideoCaptureController::OnFrameInfo( | 548 void VideoCaptureController::OnFrameInfo( |
489 const media::VideoCaptureCapability& info) { | 549 const media::VideoCaptureCapability& info) { |
490 frame_info_= info; | 550 frame_info_= info; |
491 // Handle cases when |info| has odd numbers for width/height. | 551 // Handle cases when |info| has odd numbers for width/height. |
492 if (info.width & 1) { | 552 if (info.width & 1) { |
493 --frame_info_.width; | 553 --frame_info_.width; |
494 chopped_width_ = 1; | 554 chopped_width_ = 1; |
495 } else { | 555 } else { |
496 chopped_width_ = 0; | 556 chopped_width_ = 0; |
497 } | 557 } |
498 if (info.height & 1) { | 558 if (info.height & 1) { |
499 --frame_info_.height; | 559 --frame_info_.height; |
500 chopped_height_ = 1; | 560 chopped_height_ = 1; |
501 } else { | 561 } else { |
502 chopped_height_ = 0; | 562 chopped_height_ = 0; |
503 } | 563 } |
564 | |
565 BrowserThread::PostTask( | |
566 BrowserThread::IO, | |
567 FROM_HERE, | |
568 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this, false)); | |
569 } | |
570 | |
571 void VideoCaptureController::OnEncodedFrameInfo( | |
572 const media::VideoEncodingParameters& encoded_info) { | |
573 encoded_frame_info_ = encoded_info; | |
574 | |
575 BrowserThread::PostTask( | |
576 BrowserThread::IO, | |
577 FROM_HERE, | |
578 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this, true)); | |
579 } | |
580 | |
581 void VideoCaptureController::OnBitstreamConfigChanged( | |
582 const media::RuntimeVideoEncodingParameters& params) { | |
504 BrowserThread::PostTask(BrowserThread::IO, | 583 BrowserThread::PostTask(BrowserThread::IO, |
505 FROM_HERE, | 584 FROM_HERE, |
506 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this)); | 585 base::Bind(&VideoCaptureController::DoBitstreamConfigChangedOnIOThread, |
586 this, | |
587 params)); | |
507 } | 588 } |
508 | 589 |
509 // static | 590 scoped_refptr<media::VideoFrame> |
510 scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveI420VideoFrame( | 591 VideoCaptureController::ReserveOutputVideoFrame() { |
511 VideoCaptureBufferPool* buffer_pool, const gfx::Size& size) { | 592 base::AutoLock lock(buffer_pool_lock_); |
512 if ((size_t)(size.GetArea() * 3 / 2) > buffer_pool->GetMemorySize()) | 593 if (!buffer_pool_.get()) |
513 return NULL; | 594 return NULL; |
595 return ReserveI420VideoFrame(buffer_pool_, gfx::Size(frame_info_.width, | |
596 frame_info_.height)); | |
597 } | |
514 | 598 |
515 int buffer_id = buffer_pool->ReserveForProducer(); | 599 scoped_refptr<media::EncodedBitstreamBuffer> |
516 if (buffer_id < 0) | 600 VideoCaptureController::ReserveOutputEncodedBitstreamBuffer() { |
601 base::AutoLock lock(buffer_pool_lock_); | |
602 if (!buffer_pool_.get()) | |
517 return NULL; | 603 return NULL; |
518 | 604 return ReserveEncodedBitstreamBuffer(buffer_pool_); |
519 base::Closure disposal_handler = base::Bind( | |
520 &VideoCaptureBufferPool::RelinquishProducerReservation, | |
521 buffer_pool, | |
522 buffer_id); | |
523 | |
524 // Wrap the buffer in a VideoFrame container. | |
525 uint8* base_ptr = static_cast<uint8*>(buffer_pool->GetMemory(buffer_id)); | |
526 size_t u_offset = size.GetArea(); | |
527 size_t v_offset = u_offset + u_offset / 4; | |
528 scoped_refptr<media::VideoFrame> frame = | |
529 media::VideoFrame::WrapExternalYuvData( | |
530 buffer_pool->GetHandle(buffer_id), | |
531 media::VideoFrame::YV12, // Actually it's I420, but equivalent here. | |
532 size, gfx::Rect(size), size, | |
533 size.width(), // y stride | |
534 size.width() / 2, // u stride | |
535 size.width() / 2, // v stride | |
536 base_ptr, // y address | |
537 base_ptr + u_offset, // u address | |
538 base_ptr + v_offset, // v address | |
539 base::TimeDelta(), // timestamp (unused). | |
540 disposal_handler); | |
541 | |
542 return frame; | |
543 } | 605 } |
544 | 606 |
545 VideoCaptureController::~VideoCaptureController() { | 607 VideoCaptureController::~VideoCaptureController() { |
546 buffer_pool_ = NULL; // Release all buffers. | 608 buffer_pool_ = NULL; // Release all buffers. |
547 STLDeleteContainerPointers(controller_clients_.begin(), | 609 STLDeleteContainerPointers(controller_clients_.begin(), |
548 controller_clients_.end()); | 610 controller_clients_.end()); |
549 STLDeleteContainerPointers(pending_clients_.begin(), | 611 STLDeleteContainerPointers(pending_clients_.begin(), |
550 pending_clients_.end()); | 612 pending_clients_.end()); |
551 } | 613 } |
552 | 614 |
553 // Called by VideoCaptureManager when a device have been stopped. | 615 // Called by VideoCaptureManager when a device have been stopped. |
554 void VideoCaptureController::OnDeviceStopped() { | 616 void VideoCaptureController::OnDeviceStopped() { |
555 BrowserThread::PostTask(BrowserThread::IO, | 617 BrowserThread::PostTask(BrowserThread::IO, |
556 FROM_HERE, | 618 FROM_HERE, |
557 base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this)); | 619 base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this)); |
558 } | 620 } |
559 | 621 |
560 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( | 622 void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( |
561 const scoped_refptr<media::VideoFrame>& reserved_frame, | 623 const scoped_refptr<media::VideoFrame>& frame, |
624 base::Time timestamp) { | |
625 DoIncomingCapturedSharedMemoryOnIOThread( | |
626 frame->shared_memory_handle(), | |
627 frame->coded_size().GetArea() * 3 / 2, | |
628 timestamp); | |
629 } | |
630 | |
631 void VideoCaptureController::DoIncomingCapturedEncodedBitstreamBufferOnIOThread( | |
632 const scoped_refptr<media::EncodedBitstreamBuffer>& buffer, | |
633 size_t data_size, | |
634 base::Time timestamp) { | |
635 DoIncomingCapturedSharedMemoryOnIOThread( | |
636 buffer->shared_memory_handle(), | |
637 data_size, | |
638 timestamp); | |
639 } | |
640 | |
641 void VideoCaptureController::DoIncomingCapturedSharedMemoryOnIOThread( | |
642 base::SharedMemoryHandle reserved_handle, | |
643 size_t data_size, | |
562 base::Time timestamp) { | 644 base::Time timestamp) { |
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 645 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
564 | 646 |
565 if (!buffer_pool_.get()) | 647 if (!buffer_pool_.get()) |
566 return; | 648 return; |
567 | 649 |
568 int buffer_id = buffer_pool_->RecognizeReservedBuffer( | 650 int buffer_id = buffer_pool_->RecognizeReservedBuffer(reserved_handle); |
569 reserved_frame->shared_memory_handle()); | |
570 if (buffer_id < 0) { | 651 if (buffer_id < 0) { |
571 NOTREACHED(); | 652 NOTREACHED(); |
572 return; | 653 return; |
573 } | 654 } |
574 | 655 |
575 int count = 0; | 656 int count = 0; |
576 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 657 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
577 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 658 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
578 client_it != controller_clients_.end(); ++client_it) { | 659 client_it != controller_clients_.end(); ++client_it) { |
579 if ((*client_it)->session_closed) | 660 if ((*client_it)->session_closed) |
580 continue; | 661 continue; |
581 | 662 |
582 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, | 663 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, |
583 buffer_id, timestamp); | 664 buffer_id, data_size, |
665 timestamp, false); | |
584 (*client_it)->buffers.insert(buffer_id); | 666 (*client_it)->buffers.insert(buffer_id); |
585 count++; | 667 count++; |
586 } | 668 } |
587 } | 669 } |
588 | 670 |
589 buffer_pool_->HoldForConsumers(buffer_id, count); | 671 buffer_pool_->HoldForConsumers(buffer_id, count); |
590 } | 672 } |
591 | 673 |
592 void VideoCaptureController::DoFrameInfoOnIOThread() { | 674 void VideoCaptureController::DoFrameInfoOnIOThread(bool encoded) { |
593 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 675 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
594 DCHECK(!buffer_pool_.get()) | 676 DCHECK(!buffer_pool_.get()) |
595 << "Device is restarted without releasing shared memory."; | 677 << "Device is restarted without releasing shared memory."; |
596 | 678 |
597 // Allocate memory only when device has been started. | 679 // Allocate memory only when device has been started. |
598 if (state_ != VIDEO_CAPTURE_STATE_STARTED) | 680 if (state_ != VIDEO_CAPTURE_STATE_STARTED) |
599 return; | 681 return; |
600 | 682 |
601 scoped_refptr<VideoCaptureBufferPool> buffer_pool = | 683 scoped_refptr<VideoCaptureBufferPool> buffer_pool; |
602 new VideoCaptureBufferPool(frame_info_.width * frame_info_.height * 3 / 2, | 684 if (encoded) { |
603 kNoOfBuffers); | 685 buffer_pool = new VideoCaptureBufferPool( |
686 encoded_frame_info_.runtime_params.max_bitrate, kNoOfBuffers); | |
687 } else { | |
688 buffer_pool = new VideoCaptureBufferPool( | |
689 frame_info_.width * frame_info_.height * 3 / 2, kNoOfBuffers); | |
690 } | |
604 | 691 |
605 // Check whether all buffers were created successfully. | 692 // Check whether all buffers were created successfully. |
606 if (!buffer_pool->Allocate()) { | 693 if (!buffer_pool->Allocate()) { |
607 state_ = VIDEO_CAPTURE_STATE_ERROR; | 694 state_ = VIDEO_CAPTURE_STATE_ERROR; |
608 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 695 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
609 client_it != controller_clients_.end(); ++client_it) { | 696 client_it != controller_clients_.end(); ++client_it) { |
610 (*client_it)->event_handler->OnError((*client_it)->controller_id); | 697 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
611 } | 698 } |
612 return; | 699 return; |
613 } | 700 } |
614 | 701 |
615 { | 702 { |
616 base::AutoLock lock(buffer_pool_lock_); | 703 base::AutoLock lock(buffer_pool_lock_); |
617 buffer_pool_ = buffer_pool; | 704 buffer_pool_ = buffer_pool; |
618 } | 705 } |
619 frame_info_available_ = true; | 706 if (encoded) |
707 encoded_frame_info_available_ = true; | |
708 else | |
709 frame_info_available_ = true; | |
620 | 710 |
621 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 711 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
622 client_it != controller_clients_.end(); ++client_it) { | 712 client_it != controller_clients_.end(); ++client_it) { |
623 SendFrameInfoAndBuffers(*client_it); | 713 SendFrameInfoAndBuffers(*client_it); |
624 } | 714 } |
625 } | 715 } |
626 | 716 |
717 void VideoCaptureController::DoBitstreamConfigChangedOnIOThread( | |
718 const media::RuntimeVideoEncodingParameters& params) { | |
719 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
720 for (ControllerClients::iterator client_it = controller_clients_.begin(); | |
721 client_it != controller_clients_.end(); ++client_it) { | |
722 (*client_it)->event_handler->OnBitstreamConfigChanged( | |
723 (*client_it)->controller_id, | |
724 params); | |
725 } | |
726 } | |
727 | |
627 void VideoCaptureController::DoErrorOnIOThread() { | 728 void VideoCaptureController::DoErrorOnIOThread() { |
628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 729 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
629 state_ = VIDEO_CAPTURE_STATE_ERROR; | 730 state_ = VIDEO_CAPTURE_STATE_ERROR; |
630 ControllerClients::iterator client_it; | 731 ControllerClients::iterator client_it; |
631 for (client_it = controller_clients_.begin(); | 732 for (client_it = controller_clients_.begin(); |
632 client_it != controller_clients_.end(); ++client_it) { | 733 client_it != controller_clients_.end(); ++client_it) { |
633 (*client_it)->event_handler->OnError((*client_it)->controller_id); | 734 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
634 } | 735 } |
635 for (client_it = pending_clients_.begin(); | 736 for (client_it = pending_clients_.begin(); |
636 client_it != pending_clients_.end(); ++client_it) { | 737 client_it != pending_clients_.end(); ++client_it) { |
637 (*client_it)->event_handler->OnError((*client_it)->controller_id); | 738 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
638 } | 739 } |
639 } | 740 } |
640 | 741 |
641 void VideoCaptureController::DoDeviceStoppedOnIOThread() { | 742 void VideoCaptureController::DoDeviceStoppedOnIOThread() { |
642 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 743 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
643 device_in_use_ = false; | 744 device_in_use_ = false; |
644 if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 745 if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
645 PostStopping(); | 746 PostStopping(); |
646 } | 747 } |
647 } | 748 } |
648 | 749 |
649 void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) { | 750 void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) { |
650 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 751 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
651 DCHECK(frame_info_available_); | 752 DCHECK(frame_info_available_ || encoded_frame_info_available_); |
652 client->event_handler->OnFrameInfo(client->controller_id, | |
653 frame_info_.width, frame_info_.height, | |
654 frame_info_.frame_rate); | |
655 if (!buffer_pool_.get()) | |
656 return; | |
657 | 753 |
754 std::vector<base::SharedMemoryHandle> handles; | |
658 for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) { | 755 for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) { |
659 base::SharedMemoryHandle remote_handle = | 756 base::SharedMemoryHandle remote_handle = |
660 buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle); | 757 buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle); |
661 | 758 handles.push_back(remote_handle); |
662 client->event_handler->OnBufferCreated(client->controller_id, | 759 } |
663 remote_handle, | 760 if (frame_info_available_) { |
664 buffer_pool_->GetMemorySize(), | 761 DCHECK(!encoded_frame_info_available_); |
665 buffer_id); | 762 media::VideoCaptureParams params; |
763 params.width = frame_info_.width; | |
764 params.height = frame_info_.height; | |
765 params.frame_per_second = frame_info_.frame_rate; | |
766 params.session_id = client->parameters.session_id; | |
767 client->event_handler->OnFrameInfo(client->controller_id, | |
768 params, | |
769 handles, | |
770 buffer_pool_->GetMemorySize()); | |
771 } else { | |
772 DCHECK(!frame_info_available_); | |
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
did you mean to DCHECK(encoded_frame_info_availabl
| |
773 client->event_handler->OnEncodedFrameInfo(client->controller_id, | |
774 encoded_frame_info_, | |
775 handles, | |
776 buffer_pool_->GetMemorySize()); | |
666 } | 777 } |
667 } | 778 } |
668 | 779 |
669 VideoCaptureController::ControllerClient* | 780 VideoCaptureController::ControllerClient* |
670 VideoCaptureController::FindClient( | 781 VideoCaptureController::FindClient( |
671 const VideoCaptureControllerID& id, | 782 const VideoCaptureControllerID& id, |
672 VideoCaptureControllerEventHandler* handler, | 783 VideoCaptureControllerEventHandler* handler, |
673 const ControllerClients& clients) { | 784 const ControllerClients& clients) { |
674 for (ControllerClients::const_iterator client_it = clients.begin(); | 785 for (ControllerClients::const_iterator client_it = clients.begin(); |
675 client_it != clients.end(); ++client_it) { | 786 client_it != clients.end(); ++client_it) { |
(...skipping 11 matching lines...) Expand all Loading... | |
687 const ControllerClients& clients) { | 798 const ControllerClients& clients) { |
688 for (ControllerClients::const_iterator client_it = clients.begin(); | 799 for (ControllerClients::const_iterator client_it = clients.begin(); |
689 client_it != clients.end(); ++client_it) { | 800 client_it != clients.end(); ++client_it) { |
690 if ((*client_it)->parameters.session_id == session_id) { | 801 if ((*client_it)->parameters.session_id == session_id) { |
691 return *client_it; | 802 return *client_it; |
692 } | 803 } |
693 } | 804 } |
694 return NULL; | 805 return NULL; |
695 } | 806 } |
696 | 807 |
808 // static | |
809 scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveI420VideoFrame( | |
810 VideoCaptureBufferPool* buffer_pool, const gfx::Size& size) { | |
811 if ((size_t)(size.GetArea() * 3 / 2) > buffer_pool->GetMemorySize()) | |
812 return NULL; | |
813 | |
814 int buffer_id = buffer_pool->ReserveForProducer(); | |
815 if (buffer_id < 0) | |
816 return NULL; | |
817 | |
818 base::Closure disposal_handler = base::Bind( | |
819 &VideoCaptureBufferPool::RelinquishProducerReservation, | |
820 buffer_pool, | |
821 buffer_id); | |
822 | |
823 // Wrap the buffer in a VideoFrame container. | |
824 uint8* base_ptr = static_cast<uint8*>(buffer_pool->GetMemory(buffer_id)); | |
825 size_t u_offset = size.GetArea(); | |
826 size_t v_offset = u_offset + u_offset / 4; | |
827 scoped_refptr<media::VideoFrame> frame = | |
828 media::VideoFrame::WrapExternalYuvData( | |
829 buffer_pool->GetHandle(buffer_id), | |
830 media::VideoFrame::YV12, // Actually it's I420, but equivalent here. | |
831 size, gfx::Rect(size), size, | |
832 size.width(), // y stride | |
833 size.width() / 2, // u stride | |
834 size.width() / 2, // v stride | |
835 base_ptr, // y address | |
836 base_ptr + u_offset, // u address | |
837 base_ptr + v_offset, // v address | |
838 base::TimeDelta(), // timestamp (unused). | |
839 disposal_handler); | |
840 | |
841 return frame; | |
842 } | |
843 | |
844 // static | |
845 scoped_refptr<media::EncodedBitstreamBuffer> | |
846 VideoCaptureController::ReserveEncodedBitstreamBuffer( | |
847 VideoCaptureBufferPool* buffer_pool) { | |
848 int buffer_id = buffer_pool->ReserveForProducer(); | |
849 if (buffer_id < 0) | |
850 return NULL; | |
851 | |
852 base::Closure disposal_handler = base::Bind( | |
853 &VideoCaptureBufferPool::RelinquishProducerReservation, | |
854 buffer_pool, | |
855 buffer_id); | |
856 | |
857 // Wrap the buffer in a VideoFrame container. | |
858 media::BufferEncodingMetadata metadata; | |
859 metadata.key_frame = false; | |
860 scoped_refptr<media::EncodedBitstreamBuffer> frame = | |
861 new media::EncodedBitstreamBuffer( | |
862 buffer_id, | |
863 reinterpret_cast<uint8*>(buffer_pool->GetMemory(buffer_id)), | |
864 buffer_pool->GetMemorySize(), | |
865 buffer_pool->GetHandle(buffer_id), | |
866 metadata, | |
867 disposal_handler); | |
868 return frame; | |
869 } | |
870 | |
697 // This function is called when all buffers have been returned to controller, | 871 // This function is called when all buffers have been returned to controller, |
698 // or when device is stopped. It decides whether the device needs to be | 872 // or when device is stopped. It decides whether the device needs to be |
699 // restarted. | 873 // restarted. |
700 void VideoCaptureController::PostStopping() { | 874 void VideoCaptureController::PostStopping() { |
701 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 875 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
702 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPING); | 876 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPING); |
703 | 877 |
704 // When clients still have some buffers, or device has not been stopped yet, | 878 // When clients still have some buffers, or device has not been stopped yet, |
705 // do nothing. | 879 // do nothing. |
706 if ((buffer_pool_.get() && buffer_pool_->IsAnyBufferHeldForConsumers()) || | 880 if ((buffer_pool_.get() && buffer_pool_->IsAnyBufferHeldForConsumers()) || |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 controller_clients_.push_back((*client_it)); | 912 controller_clients_.push_back((*client_it)); |
739 pending_clients_.erase(client_it++); | 913 pending_clients_.erase(client_it++); |
740 } | 914 } |
741 // Request the manager to start the actual capture. | 915 // Request the manager to start the actual capture. |
742 video_capture_manager_->Start(current_params_, this); | 916 video_capture_manager_->Start(current_params_, this); |
743 state_ = VIDEO_CAPTURE_STATE_STARTED; | 917 state_ = VIDEO_CAPTURE_STATE_STARTED; |
744 device_in_use_ = true; | 918 device_in_use_ = true; |
745 } | 919 } |
746 | 920 |
747 } // namespace content | 921 } // namespace content |
OLD | NEW |