| 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 <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 // VideoCaptureDevice::Client implementation. | 168 // VideoCaptureDevice::Client implementation. |
| 169 void OnIncomingCapturedData(const uint8* data, | 169 void OnIncomingCapturedData(const uint8* data, |
| 170 int length, | 170 int length, |
| 171 const VideoCaptureFormat& frame_format, | 171 const VideoCaptureFormat& frame_format, |
| 172 int rotation, | 172 int rotation, |
| 173 const base::TimeTicks& timestamp) override; | 173 const base::TimeTicks& timestamp) override; |
| 174 scoped_refptr<Buffer> ReserveOutputBuffer(media::VideoFrame::Format format, | 174 scoped_refptr<Buffer> ReserveOutputBuffer(media::VideoFrame::Format format, |
| 175 const gfx::Size& size) override; | 175 const gfx::Size& size) override; |
| 176 void OnIncomingCapturedVideoFrame( | 176 void OnIncomingCapturedVideoFrame( |
| 177 const scoped_refptr<Buffer>& buffer, | 177 const scoped_refptr<Buffer>& buffer, |
| 178 const VideoCaptureFormat& buffer_format, | |
| 179 const scoped_refptr<media::VideoFrame>& frame, | 178 const scoped_refptr<media::VideoFrame>& frame, |
| 180 const base::TimeTicks& timestamp) override; | 179 const base::TimeTicks& timestamp) override; |
| 181 void OnError(const std::string& reason) override; | 180 void OnError(const std::string& reason) override; |
| 182 void OnLog(const std::string& message) override; | 181 void OnLog(const std::string& message) override; |
| 183 | 182 |
| 184 private: | 183 private: |
| 185 // The controller to which we post events. | 184 // The controller to which we post events. |
| 186 const base::WeakPtr<VideoCaptureController> controller_; | 185 const base::WeakPtr<VideoCaptureController> controller_; |
| 187 | 186 |
| 188 // The pool of shared-memory buffers used for capturing. | 187 // The pool of shared-memory buffers used for capturing. |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 gfx::Rect(dimensions), | 539 gfx::Rect(dimensions), |
| 541 dimensions, | 540 dimensions, |
| 542 yplane, | 541 yplane, |
| 543 media::VideoFrame::AllocationSize(media::VideoFrame::I420, | 542 media::VideoFrame::AllocationSize(media::VideoFrame::I420, |
| 544 dimensions), | 543 dimensions), |
| 545 base::SharedMemory::NULLHandle(), | 544 base::SharedMemory::NULLHandle(), |
| 546 0, | 545 0, |
| 547 base::TimeDelta(), | 546 base::TimeDelta(), |
| 548 base::Closure()); | 547 base::Closure()); |
| 549 DCHECK(frame.get()); | 548 DCHECK(frame.get()); |
| 549 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 550 frame_format.frame_rate); |
| 550 | 551 |
| 551 VideoCaptureFormat format( | |
| 552 dimensions, frame_format.frame_rate, media::PIXEL_FORMAT_I420); | |
| 553 BrowserThread::PostTask( | 552 BrowserThread::PostTask( |
| 554 BrowserThread::IO, | 553 BrowserThread::IO, |
| 555 FROM_HERE, | 554 FROM_HERE, |
| 556 base::Bind( | 555 base::Bind( |
| 557 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | 556 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
| 558 controller_, | 557 controller_, |
| 559 buffer, | 558 buffer, |
| 560 format, | |
| 561 frame, | 559 frame, |
| 562 timestamp)); | 560 timestamp)); |
| 563 } | 561 } |
| 564 | 562 |
| 565 void | 563 void |
| 566 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( | 564 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
| 567 const scoped_refptr<Buffer>& buffer, | 565 const scoped_refptr<Buffer>& buffer, |
| 568 const VideoCaptureFormat& buffer_format, | |
| 569 const scoped_refptr<media::VideoFrame>& frame, | 566 const scoped_refptr<media::VideoFrame>& frame, |
| 570 const base::TimeTicks& timestamp) { | 567 const base::TimeTicks& timestamp) { |
| 571 BrowserThread::PostTask( | 568 BrowserThread::PostTask( |
| 572 BrowserThread::IO, | 569 BrowserThread::IO, |
| 573 FROM_HERE, | 570 FROM_HERE, |
| 574 base::Bind( | 571 base::Bind( |
| 575 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | 572 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
| 576 controller_, | 573 controller_, |
| 577 buffer, | 574 buffer, |
| 578 buffer_format, | |
| 579 frame, | 575 frame, |
| 580 timestamp)); | 576 timestamp)); |
| 581 } | 577 } |
| 582 | 578 |
| 583 void VideoCaptureController::VideoCaptureDeviceClient::OnError( | 579 void VideoCaptureController::VideoCaptureDeviceClient::OnError( |
| 584 const std::string& reason) { | 580 const std::string& reason) { |
| 585 const std::string log_message = base::StringPrintf( | 581 const std::string log_message = base::StringPrintf( |
| 586 "Error on video capture: %s, OS message: %s", | 582 "Error on video capture: %s, OS message: %s", |
| 587 reason.c_str(), | 583 reason.c_str(), |
| 588 logging::SystemErrorCodeToString( | 584 logging::SystemErrorCodeToString( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 599 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); | 595 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); |
| 600 } | 596 } |
| 601 | 597 |
| 602 VideoCaptureController::~VideoCaptureController() { | 598 VideoCaptureController::~VideoCaptureController() { |
| 603 STLDeleteContainerPointers(controller_clients_.begin(), | 599 STLDeleteContainerPointers(controller_clients_.begin(), |
| 604 controller_clients_.end()); | 600 controller_clients_.end()); |
| 605 } | 601 } |
| 606 | 602 |
| 607 void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( | 603 void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( |
| 608 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, | 604 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, |
| 609 const media::VideoCaptureFormat& buffer_format, | |
| 610 const scoped_refptr<media::VideoFrame>& frame, | 605 const scoped_refptr<media::VideoFrame>& frame, |
| 611 const base::TimeTicks& timestamp) { | 606 const base::TimeTicks& timestamp) { |
| 612 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 607 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 613 DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); | 608 DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); |
| 614 | 609 |
| 615 int count = 0; | 610 int count = 0; |
| 616 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 611 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 612 if (!frame->metadata()->HasKey(media::VideoFrameMetadata::FRAME_RATE)) { |
| 613 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 614 video_capture_format_.frame_rate); |
| 615 } |
| 616 scoped_ptr<base::DictionaryValue> metadata(new base::DictionaryValue()); |
| 617 frame->metadata()->MergeInternalValuesInto(metadata.get()); |
| 618 |
| 617 for (const auto& client : controller_clients_) { | 619 for (const auto& client : controller_clients_) { |
| 618 if (client->session_closed || client->paused) | 620 if (client->session_closed || client->paused) |
| 619 continue; | 621 continue; |
| 620 | 622 |
| 623 scoped_ptr<base::DictionaryValue> copy_of_metadata; |
| 624 if (client == controller_clients_.back()) |
| 625 copy_of_metadata = metadata.Pass(); |
| 626 else |
| 627 copy_of_metadata.reset(metadata->DeepCopy()); |
| 628 |
| 621 if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { | 629 if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { |
| 630 DCHECK(frame->coded_size() == frame->visible_rect().size()) |
| 631 << "Textures are always supposed to be tightly packed."; |
| 622 client->event_handler->OnMailboxBufferReady(client->controller_id, | 632 client->event_handler->OnMailboxBufferReady(client->controller_id, |
| 623 buffer->id(), | 633 buffer->id(), |
| 624 *frame->mailbox_holder(), | 634 *frame->mailbox_holder(), |
| 625 buffer_format, | 635 frame->coded_size(), |
| 626 timestamp); | 636 timestamp, |
| 627 } else { | 637 copy_of_metadata.Pass()); |
| 638 } else if (frame->format() == media::VideoFrame::I420) { |
| 628 bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; | 639 bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; |
| 629 if (is_new_buffer) { | 640 if (is_new_buffer) { |
| 630 // On the first use of a buffer on a client, share the memory handle. | 641 // On the first use of a buffer on a client, share the memory handle. |
| 631 size_t memory_size = 0; | 642 size_t memory_size = 0; |
| 632 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( | 643 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( |
| 633 buffer->id(), client->render_process_handle, &memory_size); | 644 buffer->id(), client->render_process_handle, &memory_size); |
| 634 client->event_handler->OnBufferCreated( | 645 client->event_handler->OnBufferCreated( |
| 635 client->controller_id, remote_handle, memory_size, buffer->id()); | 646 client->controller_id, remote_handle, memory_size, buffer->id()); |
| 636 } | 647 } |
| 637 | 648 |
| 638 client->event_handler->OnBufferReady( | 649 client->event_handler->OnBufferReady( |
| 639 client->controller_id, buffer->id(), buffer_format, | 650 client->controller_id, buffer->id(), frame->coded_size(), |
| 640 frame->visible_rect(), timestamp); | 651 frame->visible_rect(), timestamp, copy_of_metadata.Pass()); |
| 652 } else { |
| 653 // VideoFrame format not supported. |
| 654 NOTREACHED(); |
| 655 break; |
| 641 } | 656 } |
| 642 | 657 |
| 643 bool inserted = | 658 bool inserted = |
| 644 client->active_buffers.insert(std::make_pair(buffer->id(), frame)) | 659 client->active_buffers.insert(std::make_pair(buffer->id(), frame)) |
| 645 .second; | 660 .second; |
| 646 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id(); | 661 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id(); |
| 647 count++; | 662 count++; |
| 648 } | 663 } |
| 649 } | 664 } |
| 650 | 665 |
| 651 if (!has_received_frames_) { | 666 if (!has_received_frames_) { |
| 652 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", | 667 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", |
| 653 buffer_format.frame_size.width()); | 668 frame->visible_rect().width()); |
| 654 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", | 669 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", |
| 655 buffer_format.frame_size.height()); | 670 frame->visible_rect().height()); |
| 656 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", | 671 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", |
| 657 buffer_format.frame_size.width(), | 672 frame->visible_rect().width(), |
| 658 buffer_format.frame_size.height()); | 673 frame->visible_rect().height()); |
| 659 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", | 674 double frame_rate; |
| 660 buffer_format.frame_rate); | 675 if (!frame->metadata()->GetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 676 &frame_rate)) |
| 677 frame_rate = video_capture_format_.frame_rate; |
| 678 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate); |
| 661 has_received_frames_ = true; | 679 has_received_frames_ = true; |
| 662 } | 680 } |
| 663 | 681 |
| 664 buffer_pool_->HoldForConsumers(buffer->id(), count); | 682 buffer_pool_->HoldForConsumers(buffer->id(), count); |
| 665 } | 683 } |
| 666 | 684 |
| 667 void VideoCaptureController::DoErrorOnIOThread() { | 685 void VideoCaptureController::DoErrorOnIOThread() { |
| 668 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 686 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 669 state_ = VIDEO_CAPTURE_STATE_ERROR; | 687 state_ = VIDEO_CAPTURE_STATE_ERROR; |
| 670 | 688 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 750 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 733 int active_client_count = 0; | 751 int active_client_count = 0; |
| 734 for (ControllerClient* client : controller_clients_) { | 752 for (ControllerClient* client : controller_clients_) { |
| 735 if (!client->paused) | 753 if (!client->paused) |
| 736 ++active_client_count; | 754 ++active_client_count; |
| 737 } | 755 } |
| 738 return active_client_count; | 756 return active_client_count; |
| 739 } | 757 } |
| 740 | 758 |
| 741 } // namespace content | 759 } // namespace content |
| OLD | NEW |