Chromium Code Reviews| 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..2bb1b0cc03df8d557297d468ad8c2c3350ed641e 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); |
| @@ -150,10 +116,8 @@ struct VideoCaptureController::ControllerClient { |
| // Buffers that are currently known to this client. |
| std::set<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::set<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,71 @@ struct VideoCaptureController::ControllerClient { |
| bool paused; |
| }; |
| +VideoCaptureController::BufferState::BufferState() |
| + : buffer_id_(0), |
| + frame_receiver_observer_(nullptr), |
| + max_consumer_utilization_(0), |
| + consumer_hold_count_(0) {} |
| + |
| +VideoCaptureController::BufferState::BufferState( |
| + int buffer_id, |
| + media::FrameReceiverObserver* frame_receiver_observer, |
| + const scoped_refptr<media::VideoCaptureBufferPool>& buffer_pool, |
| + const scoped_refptr<media::VideoFrame>& frame) |
| + : buffer_id_(buffer_id), |
| + frame_receiver_observer_(frame_receiver_observer), |
| + buffer_pool_(buffer_pool), |
| + frame_(frame), |
| + max_consumer_utilization_( |
| + media::FrameReceiverObserver::no_utilization_recorded()), |
| + consumer_hold_count_(0) {} |
| + |
| +VideoCaptureController::BufferState::BufferState( |
| + VideoCaptureController::BufferState&& other) = default; |
| + |
| +VideoCaptureController::BufferState::~BufferState() = default; |
| + |
| +VideoCaptureController::BufferState& VideoCaptureController::BufferState:: |
| +operator=(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); |
|
miu
2016/12/01 05:25:17
Looks like the "hold count" tracking isn't needed
chfremer
2016/12/02 01:28:28
Excellent observation. I put it on the list of fut
|
| + consumer_hold_count_++; |
| +} |
| + |
| +void VideoCaptureController::BufferState::DecreaseConsumerCount() { |
| + consumer_hold_count_--; |
| + if (consumer_hold_count_ == 0) { |
| + if (frame_receiver_observer_ != nullptr && |
| + max_consumer_utilization_ != |
| + media::FrameReceiverObserver::no_utilization_recorded()) { |
| + frame_receiver_observer_->OnReceiverReportingUtilization( |
| + buffer_id_, max_consumer_utilization_); |
| + } |
| + buffer_pool_->RelinquishConsumerHold(buffer_id_, 1); |
| + max_consumer_utilization_ = |
| + media::FrameReceiverObserver::no_utilization_recorded(); |
| + } |
| +} |
| + |
| +bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() { |
| + return consumer_hold_count_ == 0; |
| +} |
| + |
| VideoCaptureController::VideoCaptureController(int max_buffers) |
| : buffer_pool_(new media::VideoCaptureBufferPoolImpl( |
| base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(), |
| max_buffers)), |
| + frame_receiver_observer_(nullptr), |
| state_(VIDEO_CAPTURE_STATE_STARTED), |
| has_received_frames_(false), |
| weak_ptr_factory_(this) { |
| @@ -187,7 +212,13 @@ VideoCaptureController::GetWeakPtrForIOThread() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| -std::unique_ptr<media::VideoCaptureDevice::Client> |
| +void VideoCaptureController::SetFrameReceiverObserver( |
| + media::FrameReceiverObserver* frame_receiver_observer) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + frame_receiver_observer_ = frame_receiver_observer; |
| +} |
| + |
| +std::unique_ptr<media::VideoCaptureDeviceClient> |
| VideoCaptureController::NewDeviceClient() { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| return base::MakeUnique<media::VideoCaptureDeviceClient>( |
| @@ -196,7 +227,8 @@ VideoCaptureController::NewDeviceClient() { |
| buffer_pool_, |
| base::Bind(&CreateGpuJpegDecoder, |
| base::Bind(&VideoFrameReceiver::OnIncomingCapturedVideoFrame, |
| - this->GetWeakPtrForIOThread()))); |
| + this->GetWeakPtrForIOThread())), |
| + base::ThreadTaskRunnerHandle::Get()); |
| } |
| void VideoCaptureController::AddClient( |
| @@ -259,9 +291,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_[buffer_id].DecreaseConsumerCount(); |
| + client->buffers_in_use.clear(); |
| int session_id = client->session_id; |
| controller_clients_.remove_if( |
| @@ -353,42 +385,16 @@ 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 || (client->buffers_in_use.find(buffer_id) == |
| + client->buffers_in_use.end())) { |
| 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); |
| - } |
| - } |
| - |
| - 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_[buffer_id]; |
| + buffer_state.RecordConsumerUtilization(consumer_resource_utilization); |
| + buffer_state.DecreaseConsumerCount(); |
| + client->buffers_in_use.erase(buffer_id); |
| } |
| const media::VideoCaptureFormat& |
| @@ -407,7 +413,15 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame( |
| const int buffer_id = buffer->id(); |
| DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId); |
| - int count = 0; |
| + if (buffer_id_to_state_map_.find(buffer_id) == |
|
miu
2016/12/01 05:25:17
As mentioned in the header file, you might be able
chfremer
2016/12/02 01:28:28
Very nice solution. Thanks.
Unfortunately, in orde
|
| + buffer_id_to_state_map_.end()) { |
| + BufferState new_buffer_state(buffer_id, frame_receiver_observer_, |
| + buffer_pool_, frame); |
| + buffer_id_to_state_map_[buffer_id] = std::move(new_buffer_state); |
| + } |
| + BufferState& buffer_state = buffer_id_to_state_map_[buffer_id]; |
| + DCHECK(buffer_state.HasZeroConsumerHoldCount()); |
| + |
| if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) { |
| frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, |
| @@ -442,11 +456,9 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame( |
| client->event_handler->OnBufferReady(client->controller_id, buffer_id, |
| frame); |
| - const bool inserted = |
| - client->active_buffers.insert(std::make_pair(buffer_id, frame)) |
| - .second; |
| + const bool inserted = client->buffers_in_use.insert(buffer_id).second; |
| DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer_id; |
| - count++; |
| + buffer_state.IncreaseConsumerCount(); |
| } |
| } |
| @@ -466,8 +478,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() { |
| @@ -498,6 +508,8 @@ void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) { |
| buffer_id_to_drop); |
| } |
| } |
| + |
| + buffer_id_to_state_map_.erase(buffer_id_to_drop); |
| } |
| void VideoCaptureController::DoNewBufferOnIOThread( |