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

Side by Side Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 15906019: Hook up EncodedVideoSource on the browser side (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@screencast_cl_6
Patch Set: 516738a8 IPC/struct changes, courtesy hshi@ Created 7 years, 6 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 unified diff | Download patch
OLDNEW
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
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(&current_params_, 0, sizeof(current_params_)); 94 memset(&current_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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698