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

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

Issue 2583603002: [Mojo Video Capture] Split OnIncomingCapturedVideoFrame() to OnNewBuffer() + OnFrameReadyInBuffer() (Closed)
Patch Set: Improve naming and fix Android background issue Created 4 years 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 a6a2f0f1b676d887dcffd503b4b88e4c80dd0fa3..550a8b06740a20b8a46a33dcf68687c0470ffa6e 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -19,6 +19,7 @@
#include "components/display_compositor/gl_helper.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/common/video_capture.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "media/base/video_frame.h"
@@ -46,6 +47,21 @@ static const int kInfiniteRatio = 99999;
name, \
(height) ? ((width) * 100) / (height) : kInfiniteRatio);
+// This manual copy routine is needed because base::DictionaryValue does not
+// allow the default copy operator.
+media::mojom::VideoFrameInfoPtr CloneFrameInfo(
+ media::mojom::VideoFrameInfoPtr* frame_info) {
+ auto result = media::mojom::VideoFrameInfo::New();
+ result->timestamp = (*frame_info)->timestamp;
+ result->pixel_format = (*frame_info)->pixel_format;
+ result->storage_type = (*frame_info)->storage_type;
+ result->coded_size = (*frame_info)->coded_size;
+ result->visible_rect = (*frame_info)->visible_rect;
+ result->metadata = base::MakeUnique<base::DictionaryValue>();
+ result->metadata->MergeDictionary((*frame_info)->metadata.get());
+ return result;
+}
+
} // anonymous namespace
struct VideoCaptureController::ControllerClient {
@@ -94,13 +110,12 @@ struct VideoCaptureController::ControllerClient {
VideoCaptureController::BufferState::BufferState(
int buffer_id,
- int frame_feedback_id,
media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer,
- media::FrameBufferPool* frame_buffer_pool)
+ mojo::ScopedSharedBufferHandle handle)
: buffer_id_(buffer_id),
- frame_feedback_id_(frame_feedback_id),
+ frame_feedback_id_(0),
consumer_feedback_observer_(consumer_feedback_observer),
- frame_buffer_pool_(frame_buffer_pool),
+ buffer_handle_(std::move(handle)),
max_consumer_utilization_(
media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded),
consumer_hold_count_(0) {}
@@ -108,7 +123,20 @@ VideoCaptureController::BufferState::BufferState(
VideoCaptureController::BufferState::~BufferState() = default;
VideoCaptureController::BufferState::BufferState(
- const VideoCaptureController::BufferState& other) = default;
+ VideoCaptureController::BufferState&& other) = default;
+
+VideoCaptureController::BufferState& VideoCaptureController::BufferState::
+operator=(BufferState&& other) = default;
+
+void VideoCaptureController::BufferState::set_read_permission(
+ std::unique_ptr<media::Ownership> buffer_read_permission) {
+ buffer_read_permission_ = std::move(buffer_read_permission);
+}
+
+void VideoCaptureController::BufferState::set_frame_feedback_id(
+ int frame_feedback_id) {
+ frame_feedback_id_ = frame_feedback_id;
+}
void VideoCaptureController::BufferState::RecordConsumerUtilization(
double utilization) {
@@ -119,13 +147,11 @@ void VideoCaptureController::BufferState::RecordConsumerUtilization(
}
void VideoCaptureController::BufferState::IncreaseConsumerCount() {
- if (consumer_hold_count_ == 0)
- if (frame_buffer_pool_ != nullptr)
- frame_buffer_pool_->SetBufferHold(buffer_id_);
consumer_hold_count_++;
}
void VideoCaptureController::BufferState::DecreaseConsumerCount() {
+ LOG(ERROR) << "1";
consumer_hold_count_--;
if (consumer_hold_count_ == 0) {
if (consumer_feedback_observer_ != nullptr &&
@@ -134,8 +160,7 @@ void VideoCaptureController::BufferState::DecreaseConsumerCount() {
consumer_feedback_observer_->OnUtilizationReport(
frame_feedback_id_, max_consumer_utilization_);
}
- if (frame_buffer_pool_ != nullptr)
- frame_buffer_pool_->ReleaseBufferHold(buffer_id_);
+ buffer_read_permission_.reset();
max_consumer_utilization_ =
media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded;
}
@@ -145,19 +170,18 @@ bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() {
return consumer_hold_count_ == 0;
}
+mojo::ScopedSharedBufferHandle
+VideoCaptureController::BufferState::CreateHandleCopy() {
+ return buffer_handle_->Clone();
+}
+
void VideoCaptureController::BufferState::SetConsumerFeedbackObserver(
media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer) {
consumer_feedback_observer_ = consumer_feedback_observer;
}
-void VideoCaptureController::BufferState::SetFrameBufferPool(
- media::FrameBufferPool* frame_buffer_pool) {
- frame_buffer_pool_ = frame_buffer_pool;
-}
-
VideoCaptureController::VideoCaptureController()
- : frame_buffer_pool_(nullptr),
- consumer_feedback_observer_(nullptr),
+ : consumer_feedback_observer_(nullptr),
state_(VIDEO_CAPTURE_STATE_STARTED),
has_received_frames_(false),
weak_ptr_factory_(this) {
@@ -171,23 +195,14 @@ VideoCaptureController::GetWeakPtrForIOThread() {
return weak_ptr_factory_.GetWeakPtr();
}
-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());
-}
-
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());
+ for (auto& entry : buffer_states_)
+ entry.SetConsumerFeedbackObserver(consumer_feedback_observer_.get());
}
void VideoCaptureController::AddClient(
@@ -249,9 +264,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;
@@ -355,11 +372,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&
@@ -368,51 +384,42 @@ VideoCaptureController::GetVideoCaptureFormat() const {
return video_capture_format_;
}
-void VideoCaptureController::OnIncomingCapturedVideoFrame(
- media::VideoCaptureDevice::Client::Buffer buffer,
- scoped_refptr<VideoFrame> frame) {
+void VideoCaptureController::OnNewBufferHandle(
+ int buffer_id,
+ std::unique_ptr<media::BufferHandleProvider> handle_provider) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(std::find_if(buffer_states_.begin(), buffer_states_.end(),
+ [buffer_id](const BufferState& entry) {
+ return entry.buffer_id() == buffer_id;
+ }) == buffer_states_.end());
+ buffer_states_.emplace_back(
+ buffer_id, consumer_feedback_observer_.get(),
+ handle_provider->GetHandleForInterProcessTransit());
+}
+
+void VideoCaptureController::OnFrameReadyInBuffer(
+ int buffer_id,
+ int frame_feedback_id,
+ std::unique_ptr<media::Ownership> buffer_read_permission,
+ media::mojom::VideoFrameInfoPtr frame_info) {
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 =
+ std::find_if(buffer_states_.begin(), buffer_states_.end(),
+ [buffer_id](const BufferState& entry) {
+ return entry.buffer_id() == buffer_id;
+ });
+ DCHECK(buffer_state_iter != buffer_states_.end());
+ DCHECK(buffer_state_iter->HasZeroConsumerHoldCount());
+ buffer_state_iter->set_frame_feedback_id(frame_feedback_id);
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
- if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) {
- frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
- video_capture_format_.frame_rate);
- }
- std::unique_ptr<base::DictionaryValue> metadata =
- frame->metadata()->CopyInternalValues();
-
- // Only I420 and Y16 pixel formats are currently supported.
- DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_Y16)
- << "Unsupported pixel format: "
- << media::VideoPixelFormatToString(frame->format());
-
- // Sanity-checks to confirm |frame| is actually being backed by |buffer|.
- auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess();
- DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM);
- DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer_access->data() &&
- (frame->data(media::VideoFrame::kYPlane) <
- (buffer_access->data() + buffer_access->mapped_size())))
- << "VideoFrame does not appear to be backed by Buffer";
-
for (const auto& client : controller_clients_) {
if (client->session_closed || client->paused)
continue;
- // On the first use of a buffer on a client, share the memory handles.
+ // On the first use of a buffer on a client, call OnBufferCreated().
auto known_buffers_entry_iter =
std::find(std::begin(client->known_buffers),
std::end(client->known_buffers), buffer_id);
@@ -422,15 +429,19 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
is_new_buffer = true;
}
if (is_new_buffer) {
- mojo::ScopedSharedBufferHandle handle =
- buffer.handle_provider->GetHandleForInterProcessTransit();
+ size_t mapped_size =
+ media::VideoCaptureFormat(frame_info->coded_size, 0.0f,
+ frame_info->pixel_format,
+ frame_info->storage_type)
+ .ImageAllocationSize();
client->event_handler->OnBufferCreated(
- client->controller_id, std::move(handle),
- buffer_access->mapped_size(), buffer_id);
+ client->controller_id, buffer_state_iter->CreateHandleCopy(),
+ mapped_size, buffer_id);
}
- client->event_handler->OnBufferReady(client->controller_id, buffer_id,
- frame);
+ auto frame_info_copy = CloneFrameInfo(&frame_info);
+ client->event_handler->OnBufferReady(client->controller_id, buffer_id,
+ std::move(frame_info_copy));
auto buffers_in_use_entry_iter =
std::find(std::begin(client->buffers_in_use),
std::end(client->buffers_in_use), buffer_id);
@@ -438,21 +449,28 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
client->buffers_in_use.push_back(buffer_id);
else
DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id;
- buffer_state.IncreaseConsumerCount();
+ // Use if-check, because we are in a loop and only want to do this
+ // move operation once.
+ if (buffer_read_permission) {
+ buffer_state_iter->set_read_permission(
+ std::move(buffer_read_permission));
+ }
+ buffer_state_iter->IncreaseConsumerCount();
}
}
if (!has_received_frames_) {
UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width",
- frame->visible_rect().width());
+ frame_info->coded_size.width());
UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height",
- frame->visible_rect().height());
+ frame_info->coded_size.height());
UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio",
- frame->visible_rect().width(),
- frame->visible_rect().height());
+ frame_info->coded_size.width(),
+ frame_info->coded_size.height());
double frame_rate = 0.0f;
- if (!frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE,
- &frame_rate)) {
+ media::VideoFrameMetadata metadata;
+ metadata.MergeInternalValuesFrom(*frame_info->metadata);
+ if (!metadata.GetDouble(VideoFrameMetadata::FRAME_RATE, &frame_rate)) {
frame_rate = video_capture_format_.frame_rate;
}
UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate);
@@ -460,6 +478,26 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
}
}
+void VideoCaptureController::OnBufferRetired(int buffer_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto buffer_state_iter =
+ std::find_if(buffer_states_.begin(), buffer_states_.end(),
+ [buffer_id](const BufferState& entry) {
+ return entry.buffer_id() == buffer_id;
+ });
+ DCHECK(buffer_state_iter != buffer_states_.end());
+
+ // 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 |read_access_permission|.
+ if (buffer_state_iter->HasZeroConsumerHoldCount()) {
+ ReleaseBufferState(buffer_state_iter);
+ } else {
+ buffer_state_iter->set_is_retired();
+ }
+}
+
void VideoCaptureController::OnError() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
state_ = VIDEO_CAPTURE_STATE_ERROR;
@@ -476,26 +514,6 @@ void VideoCaptureController::OnLog(const std::string& message) {
MediaStreamManager::SendMessageToNativeLog("Video capture: " + message);
}
-void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) {
- 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);
- }
- }
-
- buffer_id_to_state_map_.erase(buffer_id_to_drop);
-}
-
VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
VideoCaptureControllerID id,
VideoCaptureControllerEventHandler* handler,
@@ -517,4 +535,41 @@ VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
return nullptr;
}
+void VideoCaptureController::OnClientFinishedConsumingBuffer(
+ ControllerClient* client,
+ int buffer_id,
+ double consumer_resource_utilization) {
+ auto buffer_state_iter =
+ std::find_if(buffer_states_.begin(), buffer_states_.end(),
+ [buffer_id](const BufferState& entry) {
+ return entry.buffer_id() == 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

Powered by Google App Engine
This is Rietveld 408576698