| 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 9902d94dad4e4b80de214b7b342299a6720d697c..28c900f3d06a045050029861b9a4eb7485e7f787 100644
|
| --- a/content/browser/renderer_host/media/video_capture_controller.cc
|
| +++ b/content/browser/renderer_host/media/video_capture_controller.cc
|
| @@ -110,6 +110,9 @@ VideoCaptureController::BufferState::~BufferState() = default;
|
| VideoCaptureController::BufferState::BufferState(
|
| const VideoCaptureController::BufferState& other) = default;
|
|
|
| +VideoCaptureController::BufferState& VideoCaptureController::BufferState::
|
| +operator=(const BufferState& other) = default;
|
| +
|
| void VideoCaptureController::BufferState::RecordConsumerUtilization(
|
| double utilization) {
|
| if (std::isfinite(utilization) && utilization >= 0.0) {
|
| @@ -178,8 +181,8 @@ void VideoCaptureController::SetFrameBufferPool(
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| frame_buffer_pool_ = std::move(frame_buffer_pool);
|
| // Update existing BufferState entries.
|
| - for (auto& entry : buffer_id_to_state_map_)
|
| - entry.second.SetFrameBufferPool(frame_buffer_pool_.get());
|
| + for (auto& entry : buffer_states_)
|
| + entry.SetFrameBufferPool(frame_buffer_pool_.get());
|
| }
|
|
|
| void VideoCaptureController::SetConsumerFeedbackObserver(
|
| @@ -188,8 +191,8 @@ void VideoCaptureController::SetConsumerFeedbackObserver(
|
| 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());
|
| + for (auto& entry : buffer_states_)
|
| + entry.SetConsumerFeedbackObserver(consumer_feedback_observer_.get());
|
| }
|
|
|
| void VideoCaptureController::AddClient(
|
| @@ -251,9 +254,11 @@ int VideoCaptureController::RemoveClient(
|
| if (!client)
|
| return kInvalidMediaCaptureSessionId;
|
|
|
| - // Take back all buffers held by the |client|.
|
| - for (const auto& buffer_id : client->buffers_in_use)
|
| - buffer_id_to_state_map_.at(buffer_id).DecreaseConsumerCount();
|
| + for (const auto& buffer_id : client->buffers_in_use) {
|
| + OnClientFinishedConsumingBuffer(
|
| + client, buffer_id,
|
| + media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded);
|
| + }
|
| client->buffers_in_use.clear();
|
|
|
| int session_id = client->session_id;
|
| @@ -356,11 +361,10 @@ void VideoCaptureController::ReturnBuffer(
|
| NOTREACHED();
|
| return;
|
| }
|
| -
|
| - 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);
|
| +
|
| + OnClientFinishedConsumingBuffer(client, buffer_id,
|
| + consumer_resource_utilization);
|
| }
|
|
|
| const media::VideoCaptureFormat&
|
| @@ -375,17 +379,14 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| const int buffer_id = buffer.id();
|
| DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId);
|
| -
|
| - // 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(),
|
| - frame_buffer_pool_.get())))
|
| - .first;
|
| - BufferState& buffer_state = it->second;
|
| - DCHECK(buffer_state.HasZeroConsumerHoldCount());
|
| + auto buffer_state_iter = FindBufferState(buffer_id);
|
| + if (buffer_state_iter == buffer_states_.end()) {
|
| + buffer_states_.emplace_back(buffer_id, buffer.frame_feedback_id(),
|
| + consumer_feedback_observer_.get(),
|
| + frame_buffer_pool_.get());
|
| + buffer_state_iter = buffer_states_.end() - 1;
|
| + }
|
| + DCHECK(buffer_state_iter->HasZeroConsumerHoldCount());
|
|
|
| if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
|
| if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) {
|
| @@ -440,7 +441,7 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
|
| client->buffers_in_use.push_back(buffer_id);
|
| else
|
| DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id;
|
| - buffer_state.IncreaseConsumerCount();
|
| + buffer_state_iter->IncreaseConsumerCount();
|
| }
|
| }
|
|
|
| @@ -468,7 +469,7 @@ void VideoCaptureController::OnError() {
|
|
|
| for (const auto& client : controller_clients_) {
|
| if (client->session_closed)
|
| - continue;
|
| + continue;
|
| client->event_handler->OnError(client->controller_id);
|
| }
|
| }
|
| @@ -478,24 +479,19 @@ void VideoCaptureController::OnLog(const std::string& message) {
|
| MediaStreamManager::SendMessageToNativeLog("Video capture: " + message);
|
| }
|
|
|
| -void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) {
|
| +void VideoCaptureController::OnBufferRetired(int buffer_id) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - for (const auto& client : controller_clients_) {
|
| - if (client->session_closed)
|
| - continue;
|
| -
|
| - 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);
|
| - }
|
| - }
|
| + auto buffer_state_iter = FindBufferState(buffer_id);
|
| + DCHECK(buffer_state_iter != buffer_states_.end());
|
|
|
| - buffer_id_to_state_map_.erase(buffer_id_to_drop);
|
| + // If there are any clients still using the buffer, we need to allow them
|
| + // to finish up. We need to hold on to the BufferState entry until then,
|
| + // because it contains the consumer hold.
|
| + if (buffer_state_iter->HasZeroConsumerHoldCount())
|
| + ReleaseBufferState(buffer_state_iter);
|
| + else
|
| + buffer_state_iter->set_is_retired();
|
| }
|
|
|
| VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
|
| @@ -519,4 +515,47 @@ VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
|
| return nullptr;
|
| }
|
|
|
| +std::vector<VideoCaptureController::BufferState>::iterator
|
| +VideoCaptureController::FindBufferState(int buffer_id) {
|
| + auto buffer_state_iter =
|
| + std::find_if(buffer_states_.begin(), buffer_states_.end(),
|
| + [buffer_id](const BufferState& entry) {
|
| + return entry.buffer_id() == buffer_id;
|
| + });
|
| + return buffer_state_iter;
|
| +}
|
| +
|
| +void VideoCaptureController::OnClientFinishedConsumingBuffer(
|
| + ControllerClient* client,
|
| + int buffer_id,
|
| + double consumer_resource_utilization) {
|
| + auto buffer_state_iter = FindBufferState(buffer_id);
|
| + DCHECK(buffer_state_iter != buffer_states_.end());
|
| +
|
| + buffer_state_iter->RecordConsumerUtilization(consumer_resource_utilization);
|
| + buffer_state_iter->DecreaseConsumerCount();
|
| + if (buffer_state_iter->HasZeroConsumerHoldCount() &&
|
| + buffer_state_iter->is_retired()) {
|
| + ReleaseBufferState(buffer_state_iter);
|
| + }
|
| +}
|
| +
|
| +void VideoCaptureController::ReleaseBufferState(
|
| + const std::vector<BufferState>::iterator& buffer_state_iter) {
|
| + for (const auto& client : controller_clients_) {
|
| + if (client->session_closed)
|
| + continue;
|
| +
|
| + auto known_buffers_entry_iter = std::find(std::begin(client->known_buffers),
|
| + std::end(client->known_buffers),
|
| + buffer_state_iter->buffer_id());
|
| + 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_state_iter->buffer_id());
|
| + }
|
| + }
|
| + buffer_states_.erase(buffer_state_iter);
|
| +}
|
| +
|
| } // namespace content
|
|
|