| Index: content/browser/renderer_host/media/video_capture_controller.cc
|
| diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
|
| index 83f264cd0ec5687db042e9ec5300c65f62bcb45b..5f226b65422b880d21a94c1fe6795ede553eb2a5 100644
|
| --- a/content/browser/renderer_host/media/video_capture_controller.cc
|
| +++ b/content/browser/renderer_host/media/video_capture_controller.cc
|
| @@ -46,40 +46,6 @@ static const int kInfiniteRatio = 99999;
|
| name, \
|
| (height) ? ((width) * 100) / (height) : kInfiniteRatio);
|
|
|
| -class SyncTokenClientImpl : public VideoFrame::SyncTokenClient {
|
| - public:
|
| - explicit SyncTokenClientImpl(display_compositor::GLHelper* gl_helper)
|
| - : gl_helper_(gl_helper) {}
|
| - ~SyncTokenClientImpl() override {}
|
| - void GenerateSyncToken(gpu::SyncToken* sync_token) override {
|
| - gl_helper_->GenerateSyncToken(sync_token);
|
| - }
|
| - void WaitSyncToken(const gpu::SyncToken& sync_token) override {
|
| - gl_helper_->WaitSyncToken(sync_token);
|
| - }
|
| -
|
| - private:
|
| - display_compositor::GLHelper* gl_helper_;
|
| -};
|
| -
|
| -void ReturnVideoFrame(const scoped_refptr<VideoFrame>& video_frame,
|
| - const gpu::SyncToken& sync_token) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -#if defined(OS_ANDROID)
|
| - NOTREACHED();
|
| -#else
|
| - display_compositor::GLHelper* gl_helper =
|
| - ImageTransportFactory::GetInstance()->GetGLHelper();
|
| - // UpdateReleaseSyncToken() creates a new sync_token using |gl_helper|, so
|
| - // wait the given |sync_token| using |gl_helper|.
|
| - if (gl_helper) {
|
| - gl_helper->WaitSyncToken(sync_token);
|
| - SyncTokenClientImpl client(gl_helper);
|
| - video_frame->UpdateReleaseSyncToken(&client);
|
| - }
|
| -#endif
|
| -}
|
| -
|
| std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
|
| const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) {
|
| return base::MakeUnique<VideoCaptureGpuJpegDecoder>(decode_done_cb);
|
| @@ -148,12 +114,10 @@ struct VideoCaptureController::ControllerClient {
|
| const media::VideoCaptureParams parameters;
|
|
|
| // Buffers that are currently known to this client.
|
| - std::set<int> known_buffers;
|
| + std::vector<int> known_buffers;
|
|
|
| - // Buffers currently held by this client, and sync token callback to call when
|
| - // they are returned from the client.
|
| - typedef std::map<int, scoped_refptr<VideoFrame>> ActiveBufferMap;
|
| - ActiveBufferMap active_buffers;
|
| + // Buffers currently held by this client.
|
| + std::vector<int> buffers_in_use;
|
|
|
| // State of capture session, controlled by VideoCaptureManager directly. This
|
| // transitions to true as soon as StopSession() occurs, at which point the
|
| @@ -172,10 +136,69 @@ struct VideoCaptureController::ControllerClient {
|
| bool paused;
|
| };
|
|
|
| +VideoCaptureController::BufferState::BufferState(
|
| + int buffer_id,
|
| + int frame_feedback_id,
|
| + media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer,
|
| + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool,
|
| + scoped_refptr<media::VideoFrame> frame)
|
| + : buffer_id_(buffer_id),
|
| + frame_feedback_id_(frame_feedback_id),
|
| + consumer_feedback_observer_(consumer_feedback_observer),
|
| + buffer_pool_(std::move(buffer_pool)),
|
| + frame_(std::move(frame)),
|
| + max_consumer_utilization_(
|
| + media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded),
|
| + consumer_hold_count_(0) {}
|
| +
|
| +VideoCaptureController::BufferState::~BufferState() = default;
|
| +
|
| +VideoCaptureController::BufferState::BufferState(
|
| + const VideoCaptureController::BufferState& other) = default;
|
| +
|
| +void VideoCaptureController::BufferState::RecordConsumerUtilization(
|
| + double utilization) {
|
| + if (std::isfinite(utilization) && utilization >= 0.0) {
|
| + max_consumer_utilization_ =
|
| + std::max(max_consumer_utilization_, utilization);
|
| + }
|
| +}
|
| +
|
| +void VideoCaptureController::BufferState::IncreaseConsumerCount() {
|
| + if (consumer_hold_count_ == 0)
|
| + buffer_pool_->HoldForConsumers(buffer_id_, 1);
|
| + consumer_hold_count_++;
|
| +}
|
| +
|
| +void VideoCaptureController::BufferState::DecreaseConsumerCount() {
|
| + consumer_hold_count_--;
|
| + if (consumer_hold_count_ == 0) {
|
| + if (consumer_feedback_observer_ != nullptr &&
|
| + max_consumer_utilization_ !=
|
| + media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) {
|
| + consumer_feedback_observer_->OnUtilizationReport(
|
| + frame_feedback_id_, max_consumer_utilization_);
|
| + }
|
| + buffer_pool_->RelinquishConsumerHold(buffer_id_, 1);
|
| + max_consumer_utilization_ =
|
| + media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded;
|
| + }
|
| +}
|
| +
|
| +bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() {
|
| + return consumer_hold_count_ == 0;
|
| +}
|
| +
|
| +void VideoCaptureController::BufferState::SetConsumerFeedbackObserver(
|
| + media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer) {
|
| + consumer_feedback_observer_ = consumer_feedback_observer;
|
| +}
|
| +
|
| VideoCaptureController::VideoCaptureController(int max_buffers)
|
| : buffer_pool_(new media::VideoCaptureBufferPoolImpl(
|
| base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(),
|
| max_buffers)),
|
| + consumer_feedback_observer_(nullptr),
|
| state_(VIDEO_CAPTURE_STATE_STARTED),
|
| has_received_frames_(false),
|
| weak_ptr_factory_(this) {
|
| @@ -187,6 +210,16 @@ VideoCaptureController::GetWeakPtrForIOThread() {
|
| return weak_ptr_factory_.GetWeakPtr();
|
| }
|
|
|
| +void VideoCaptureController::SetConsumerFeedbackObserver(
|
| + std::unique_ptr<media::VideoFrameConsumerFeedbackObserver>
|
| + consumer_feedback_observer) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + consumer_feedback_observer_ = std::move(consumer_feedback_observer);
|
| + // Update existing BufferState entries.
|
| + for (auto& entry : buffer_id_to_state_map_)
|
| + entry.second.SetConsumerFeedbackObserver(consumer_feedback_observer_.get());
|
| +}
|
| +
|
| std::unique_ptr<media::VideoCaptureDevice::Client>
|
| VideoCaptureController::NewDeviceClient() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| @@ -259,9 +292,9 @@ int VideoCaptureController::RemoveClient(
|
| return kInvalidMediaCaptureSessionId;
|
|
|
| // Take back all buffers held by the |client|.
|
| - for (const auto& buffer : client->active_buffers)
|
| - buffer_pool_->RelinquishConsumerHold(buffer.first, 1);
|
| - client->active_buffers.clear();
|
| + for (const auto& buffer_id : client->buffers_in_use)
|
| + buffer_id_to_state_map_.at(buffer_id).DecreaseConsumerCount();
|
| + client->buffers_in_use.clear();
|
|
|
| int session_id = client->session_id;
|
| controller_clients_.remove_if(
|
| @@ -353,42 +386,22 @@ void VideoCaptureController::ReturnBuffer(
|
|
|
| // If this buffer is not held by this client, or this client doesn't exist
|
| // in controller, do nothing.
|
| - ControllerClient::ActiveBufferMap::iterator iter;
|
| - if (!client || (iter = client->active_buffers.find(buffer_id)) ==
|
| - client->active_buffers.end()) {
|
| + if (!client) {
|
| NOTREACHED();
|
| return;
|
| }
|
| -
|
| - // Set the RESOURCE_UTILIZATION to the maximum of those provided by each
|
| - // consumer (via separate calls to this method that refer to the same
|
| - // VideoFrame). The producer of this VideoFrame may check this value, after
|
| - // all consumer holds are relinquished, to make quality versus performance
|
| - // trade-off decisions.
|
| - scoped_refptr<VideoFrame> frame = iter->second;
|
| - if (std::isfinite(consumer_resource_utilization) &&
|
| - consumer_resource_utilization >= 0.0) {
|
| - double resource_utilization = -1.0;
|
| - if (frame->metadata()->GetDouble(VideoFrameMetadata::RESOURCE_UTILIZATION,
|
| - &resource_utilization)) {
|
| - frame->metadata()->SetDouble(VideoFrameMetadata::RESOURCE_UTILIZATION,
|
| - std::max(consumer_resource_utilization,
|
| - resource_utilization));
|
| - } else {
|
| - frame->metadata()->SetDouble(VideoFrameMetadata::RESOURCE_UTILIZATION,
|
| - consumer_resource_utilization);
|
| - }
|
| + auto buffers_in_use_entry_iter =
|
| + std::find(std::begin(client->buffers_in_use),
|
| + std::end(client->buffers_in_use), buffer_id);
|
| + if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) {
|
| + NOTREACHED();
|
| + return;
|
| }
|
|
|
| - client->active_buffers.erase(iter);
|
| - buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
|
| -
|
| -#if defined(OS_ANDROID)
|
| - DCHECK(!sync_token.HasData());
|
| -#endif
|
| - if (sync_token.HasData())
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&ReturnVideoFrame, frame, sync_token));
|
| + BufferState& buffer_state = buffer_id_to_state_map_.at(buffer_id);
|
| + buffer_state.RecordConsumerUtilization(consumer_resource_utilization);
|
| + buffer_state.DecreaseConsumerCount();
|
| + client->buffers_in_use.erase(buffers_in_use_entry_iter);
|
| }
|
|
|
| const media::VideoCaptureFormat&
|
| @@ -407,7 +420,17 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
|
| const int buffer_id = buffer->id();
|
| DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId);
|
|
|
| - int count = 0;
|
| + // Insert if not exists.
|
| + const auto it =
|
| + buffer_id_to_state_map_
|
| + .insert(std::make_pair(
|
| + buffer_id, BufferState(buffer_id, buffer->frame_feedback_id(),
|
| + consumer_feedback_observer_.get(),
|
| + buffer_pool_, frame)))
|
| + .first;
|
| + BufferState& buffer_state = it->second;
|
| + DCHECK(buffer_state.HasZeroConsumerHoldCount());
|
| +
|
| if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
|
| if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) {
|
| frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
|
| @@ -436,17 +459,28 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
|
| continue;
|
|
|
| // On the first use of a buffer on a client, share the memory handles.
|
| - const bool is_new_buffer = client->known_buffers.insert(buffer_id).second;
|
| + auto known_buffers_entry_iter =
|
| + std::find(std::begin(client->known_buffers),
|
| + std::end(client->known_buffers), buffer_id);
|
| + bool is_new_buffer = false;
|
| + if (known_buffers_entry_iter == std::end(client->known_buffers)) {
|
| + client->known_buffers.push_back(buffer_id);
|
| + is_new_buffer = true;
|
| + }
|
| if (is_new_buffer)
|
| DoNewBufferOnIOThread(client.get(), buffer.get(), frame);
|
|
|
| client->event_handler->OnBufferReady(client->controller_id, buffer_id,
|
| frame);
|
| - const bool inserted =
|
| - client->active_buffers.insert(std::make_pair(buffer_id, frame))
|
| - .second;
|
| - DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer_id;
|
| - count++;
|
| +
|
| + auto buffers_in_use_entry_iter =
|
| + std::find(std::begin(client->buffers_in_use),
|
| + std::end(client->buffers_in_use), buffer_id);
|
| + if (buffers_in_use_entry_iter == std::end(client->buffers_in_use))
|
| + client->buffers_in_use.push_back(buffer_id);
|
| + else
|
| + DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id;
|
| + buffer_state.IncreaseConsumerCount();
|
| }
|
| }
|
|
|
| @@ -466,8 +500,6 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
|
| UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate);
|
| has_received_frames_ = true;
|
| }
|
| -
|
| - buffer_pool_->HoldForConsumers(buffer_id, count);
|
| }
|
|
|
| void VideoCaptureController::OnError() {
|
| @@ -493,11 +525,17 @@ void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) {
|
| if (client->session_closed)
|
| continue;
|
|
|
| - if (client->known_buffers.erase(buffer_id_to_drop)) {
|
| + auto known_buffers_entry_iter =
|
| + std::find(std::begin(client->known_buffers),
|
| + std::end(client->known_buffers), buffer_id_to_drop);
|
| + if (known_buffers_entry_iter != std::end(client->known_buffers)) {
|
| + client->known_buffers.erase(known_buffers_entry_iter);
|
| client->event_handler->OnBufferDestroyed(client->controller_id,
|
| buffer_id_to_drop);
|
| }
|
| }
|
| +
|
| + buffer_id_to_state_map_.erase(buffer_id_to_drop);
|
| }
|
|
|
| void VideoCaptureController::DoNewBufferOnIOThread(
|
|
|