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

Unified Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 2607203002: [Mojo Video Capture] Retire buffers when Android Chromium goes to the background (Closed)
Patch Set: Support reused buffer ids in Controller Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
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 5f2136bd6f79bd48fe3c8f4c297772a6a4d3e6e6..63a79b05197969335d38a4c1a77fbb2c5eb4c939 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -42,9 +42,8 @@ namespace {
static const int kInfiniteRatio = 99999;
#define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \
- UMA_HISTOGRAM_SPARSE_SLOWLY( \
- name, \
- (height) ? ((width) * 100) / (height) : kInfiniteRatio);
+ UMA_HISTOGRAM_SPARSE_SLOWLY( \
+ name, (height) ? ((width)*100) / (height) : kInfiniteRatio);
} // anonymous namespace
@@ -69,10 +68,8 @@ struct VideoCaptureController::ControllerClient {
const media::VideoCaptureSessionId session_id;
const media::VideoCaptureParams parameters;
- // Buffers that are currently known to this client.
- std::vector<int> known_buffers;
-
- // Buffers currently held by this client.
+ std::vector<int> known_buffer_context_ids;
+ // |buffer_context_id|s of buffers currently being consumed by this client.
std::vector<int> buffers_in_use;
// State of capture session, controlled by VideoCaptureManager directly. This
@@ -92,25 +89,28 @@ struct VideoCaptureController::ControllerClient {
bool paused;
};
-VideoCaptureController::BufferState::BufferState(
+VideoCaptureController::BufferContext::BufferContext(
+ int buffer_context_id,
int buffer_id,
- int frame_feedback_id,
media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer,
media::FrameBufferPool* frame_buffer_pool)
- : buffer_id_(buffer_id),
- frame_feedback_id_(frame_feedback_id),
+ : buffer_context_id_(buffer_context_id),
+ buffer_id_(buffer_id),
consumer_feedback_observer_(consumer_feedback_observer),
frame_buffer_pool_(frame_buffer_pool),
max_consumer_utilization_(
media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded),
consumer_hold_count_(0) {}
-VideoCaptureController::BufferState::~BufferState() = default;
+VideoCaptureController::BufferContext::~BufferContext() = default;
+
+VideoCaptureController::BufferContext::BufferContext(
+ const VideoCaptureController::BufferContext& other) = default;
-VideoCaptureController::BufferState::BufferState(
- const VideoCaptureController::BufferState& other) = default;
+VideoCaptureController::BufferContext& VideoCaptureController::BufferContext::
+operator=(const BufferContext& other) = default;
-void VideoCaptureController::BufferState::RecordConsumerUtilization(
+void VideoCaptureController::BufferContext::RecordConsumerUtilization(
double utilization) {
if (std::isfinite(utilization) && utilization >= 0.0) {
max_consumer_utilization_ =
@@ -118,14 +118,14 @@ void VideoCaptureController::BufferState::RecordConsumerUtilization(
}
}
-void VideoCaptureController::BufferState::IncreaseConsumerCount() {
+void VideoCaptureController::BufferContext::IncreaseConsumerCount() {
if (consumer_hold_count_ == 0)
if (frame_buffer_pool_ != nullptr)
frame_buffer_pool_->SetBufferHold(buffer_id_);
consumer_hold_count_++;
}
-void VideoCaptureController::BufferState::DecreaseConsumerCount() {
+void VideoCaptureController::BufferContext::DecreaseConsumerCount() {
consumer_hold_count_--;
if (consumer_hold_count_ == 0) {
if (consumer_feedback_observer_ != nullptr &&
@@ -141,27 +141,10 @@ void VideoCaptureController::BufferState::DecreaseConsumerCount() {
}
}
-bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() {
+bool VideoCaptureController::BufferContext::HasZeroConsumerHoldCount() {
return consumer_hold_count_ == 0;
}
-void VideoCaptureController::BufferState::SetFrameFeedbackId(int id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- frame_feedback_id_ = id;
-}
-
-void VideoCaptureController::BufferState::SetConsumerFeedbackObserver(
- media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- consumer_feedback_observer_ = consumer_feedback_observer;
-}
-
-void VideoCaptureController::BufferState::SetFrameBufferPool(
- media::FrameBufferPool* frame_buffer_pool) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- frame_buffer_pool_ = frame_buffer_pool;
-}
-
VideoCaptureController::VideoCaptureController()
: frame_buffer_pool_(nullptr),
consumer_feedback_observer_(nullptr),
@@ -182,9 +165,9 @@ void VideoCaptureController::SetFrameBufferPool(
std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) {
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());
+ // Update existing BufferContext entries.
+ for (auto& entry : buffer_contexts_)
+ entry.set_frame_buffer_pool(frame_buffer_pool_.get());
}
void VideoCaptureController::SetConsumerFeedbackObserver(
@@ -192,9 +175,9 @@ void VideoCaptureController::SetConsumerFeedbackObserver(
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());
+ // Update existing BufferContext entries.
+ for (auto& entry : buffer_contexts_)
+ entry.set_consumer_feedback_observer(consumer_feedback_observer_.get());
}
void VideoCaptureController::AddClient(
@@ -204,8 +187,7 @@ void VideoCaptureController::AddClient(
const media::VideoCaptureParams& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id
- << ", session_id=" << session_id
- << ", params.requested_format="
+ << ", session_id=" << session_id << ", params.requested_format="
<< media::VideoCaptureFormat::ToString(params.requested_format);
// Check that requested VideoCaptureParams are valid and supported. If not,
@@ -256,9 +238,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;
@@ -361,15 +345,14 @@ 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&
-VideoCaptureController::GetVideoCaptureFormat() const {
+const media::VideoCaptureFormat& VideoCaptureController::GetVideoCaptureFormat()
+ const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return video_capture_format_;
}
@@ -378,20 +361,20 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
media::VideoCaptureDevice::Client::Buffer buffer,
scoped_refptr<VideoFrame> frame) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const int buffer_id = buffer.id();
- DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId);
-
- // Insert if not exists.
- const auto insert_result = 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())));
- BufferState& buffer_state = insert_result.first->second;
- DCHECK(buffer_state.HasZeroConsumerHoldCount());
- // If a BufferState for |buffer_id| already existed, we must update the
- // |frame_feedback_id| of the existing entry.
- if (!insert_result.second)
- buffer_state.SetFrameFeedbackId(buffer.frame_feedback_id());
+ const int buffer_id_from_producer = buffer.id();
+ DCHECK_NE(buffer_id_from_producer, media::VideoCaptureBufferPool::kInvalidId);
+ auto buffer_context_iter =
+ FindUnretiredBufferContextFromBufferId(buffer_id_from_producer);
+ if (buffer_context_iter == buffer_contexts_.end()) {
+ // A new buffer has been shared with us. Create new BufferContext.
+ buffer_contexts_.emplace_back(
+ next_buffer_context_id_++, buffer_id_from_producer,
+ consumer_feedback_observer_.get(), frame_buffer_pool_.get());
+ buffer_context_iter = buffer_contexts_.end() - 1;
+ }
+ buffer_context_iter->set_frame_feedback_id(buffer.frame_feedback_id());
+ DCHECK(buffer_context_iter->HasZeroConsumerHoldCount());
+ const int buffer_context_id = buffer_context_iter->buffer_context_id();
mcasas 2017/02/03 23:24:21 Move to l. 401? Only needed inside the for loop l.
chfremer 2017/02/06 18:16:35 Done.
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) {
@@ -420,13 +403,15 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
if (client->session_closed || client->paused)
continue;
- // On the first use of a buffer on a client, share the memory handles.
- auto known_buffers_entry_iter =
- std::find(std::begin(client->known_buffers),
- std::end(client->known_buffers), buffer_id);
+ // On the first use of a BufferContext on a client, share the memory
+ // handles.
+ auto known_buffers_entry_iter = std::find(
+ std::begin(client->known_buffer_context_ids),
+ std::end(client->known_buffer_context_ids), buffer_context_id);
bool is_new_buffer = false;
- if (known_buffers_entry_iter == std::end(client->known_buffers)) {
- client->known_buffers.push_back(buffer_id);
+ if (known_buffers_entry_iter ==
+ std::end(client->known_buffer_context_ids)) {
+ client->known_buffer_context_ids.push_back(buffer_context_id);
is_new_buffer = true;
}
if (is_new_buffer) {
@@ -434,19 +419,19 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
buffer.handle_provider()->GetHandleForInterProcessTransit();
client->event_handler->OnBufferCreated(
client->controller_id, std::move(handle),
- buffer_access->mapped_size(), buffer_id);
+ buffer_access->mapped_size(), buffer_context_id);
}
- client->event_handler->OnBufferReady(client->controller_id, buffer_id,
- frame);
+ client->event_handler->OnBufferReady(client->controller_id,
+ buffer_context_id, frame);
auto buffers_in_use_entry_iter =
std::find(std::begin(client->buffers_in_use),
- std::end(client->buffers_in_use), buffer_id);
+ std::end(client->buffers_in_use), buffer_context_id);
if (buffers_in_use_entry_iter == std::end(client->buffers_in_use))
- client->buffers_in_use.push_back(buffer_id);
+ client->buffers_in_use.push_back(buffer_context_id);
else
- DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id;
- buffer_state.IncreaseConsumerCount();
+ DCHECK(false) << "Unexpected duplicate buffer: " << buffer_context_id;
+ buffer_context_iter->IncreaseConsumerCount();
}
}
@@ -474,7 +459,7 @@ void VideoCaptureController::OnError() {
for (const auto& client : controller_clients_) {
if (client->session_closed)
- continue;
+ continue;
client->event_handler->OnError(client->controller_id);
}
}
@@ -484,24 +469,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 buffer_context_iter = FindUnretiredBufferContextFromBufferId(buffer_id);
+ DCHECK(buffer_context_iter != buffer_contexts_.end());
- 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);
+ // If there are any clients still using the buffer, we need to allow them
+ // to finish up. We need to hold on to the BufferContext entry until then,
+ // because it contains the consumer hold.
+ if (buffer_context_iter->HasZeroConsumerHoldCount())
+ ReleaseBufferContext(buffer_context_iter);
+ else
+ buffer_context_iter->set_is_retired();
}
VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
@@ -525,4 +505,59 @@ VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
return nullptr;
}
+std::vector<VideoCaptureController::BufferContext>::iterator
+VideoCaptureController::FindBufferContextFromBufferContextId(
+ int buffer_context_id) {
+ auto buffer_context_iter =
+ std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
+ [buffer_context_id](const BufferContext& entry) {
+ return entry.buffer_context_id() == buffer_context_id;
+ });
+ return buffer_context_iter;
mcasas 2017/02/03 23:24:21 return directly the std::find() statement? Also i
chfremer 2017/02/06 18:16:34 Done.
+}
+
+std::vector<VideoCaptureController::BufferContext>::iterator
+VideoCaptureController::FindUnretiredBufferContextFromBufferId(int buffer_id) {
+ auto buffer_context_iter =
+ std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
+ [buffer_id](const BufferContext& entry) {
+ return (entry.buffer_id() == buffer_id) &&
+ (entry.is_retired() == false);
+ });
+ return buffer_context_iter;
+}
+
+void VideoCaptureController::OnClientFinishedConsumingBuffer(
+ ControllerClient* client,
+ int buffer_context_id,
+ double consumer_resource_utilization) {
+ auto buffer_context_iter =
+ FindBufferContextFromBufferContextId(buffer_context_id);
+ DCHECK(buffer_context_iter != buffer_contexts_.end());
+
+ buffer_context_iter->RecordConsumerUtilization(consumer_resource_utilization);
+ buffer_context_iter->DecreaseConsumerCount();
+ if (buffer_context_iter->HasZeroConsumerHoldCount() &&
+ buffer_context_iter->is_retired()) {
+ ReleaseBufferContext(buffer_context_iter);
+ }
+}
+
+void VideoCaptureController::ReleaseBufferContext(
+ const std::vector<BufferContext>::iterator& buffer_context_iter) {
+ for (const auto& client : controller_clients_) {
+ if (client->session_closed)
+ continue;
+ auto entry_iter = std::find(std::begin(client->known_buffer_context_ids),
+ std::end(client->known_buffer_context_ids),
+ buffer_context_iter->buffer_context_id());
+ if (entry_iter != std::end(client->known_buffer_context_ids)) {
+ client->known_buffer_context_ids.erase(entry_iter);
+ client->event_handler->OnBufferDestroyed(
+ client->controller_id, buffer_context_iter->buffer_context_id());
+ }
+ }
+ buffer_contexts_.erase(buffer_context_iter);
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698