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

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

Issue 15906019: Hook up EncodedVideoSource on the browser side (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@screencast_cl_6
Patch Set: bbd3b746f Rebase. Created 7 years, 6 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 9b1196285f7ef57668008ccd2771df93462f9e51..4af1b1ae09a75429ee498d64c4d3bc4e144502d9 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -12,6 +12,7 @@
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "media/base/encoded_bitstream_buffer.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/base/yuv_convert.h"
@@ -86,6 +87,7 @@ VideoCaptureController::VideoCaptureController(
: chopped_width_(0),
chopped_height_(0),
frame_info_available_(false),
+ encoded_frame_info_available_(false),
video_capture_manager_(video_capture_manager),
device_in_use_(false),
state_(VIDEO_CAPTURE_STATE_STOPPED) {
@@ -129,6 +131,7 @@ void VideoCaptureController::StartCapture(
video_capture_manager_->Stop(current_params_.session_id,
base::Bind(&VideoCaptureController::OnDeviceStopped, this));
frame_info_available_ = false;
+ encoded_frame_info_available_ = false;
state_ = VIDEO_CAPTURE_STATE_STOPPING;
pending_clients_.push_back(client);
return;
@@ -137,7 +140,7 @@ void VideoCaptureController::StartCapture(
// This client's resolution is no larger than what's currently requested.
// When frame_info has been returned by device, send them to client.
- if (frame_info_available_) {
+ if (frame_info_available_ || encoded_frame_info_available_) {
SendFrameInfoAndBuffers(client);
}
controller_clients_.push_back(client);
@@ -199,6 +202,7 @@ void VideoCaptureController::StopCapture(
video_capture_manager_->Stop(session_id,
base::Bind(&VideoCaptureController::OnDeviceStopped, this));
frame_info_available_ = false;
+ encoded_frame_info_available_ = false;
state_ = VIDEO_CAPTURE_STATE_STOPPING;
}
}
@@ -245,12 +249,12 @@ void VideoCaptureController::ReturnBuffer(
}
}
-scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveOutputBuffer() {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return NULL;
- return ReserveI420VideoFrame(buffer_pool_, gfx::Size(frame_info_.width,
- frame_info_.height));
+void VideoCaptureController::TryConfigureEncodedBitstream(
+ const media::RuntimeVideoEncodingParameters& params) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ video_capture_manager_->TryConfigureEncodedBitstream(
+ current_params_.session_id,
+ params);
}
// Implements VideoCaptureDevice::EventHandler.
@@ -357,8 +361,11 @@ void VideoCaptureController::OnIncomingCapturedFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, dst, timestamp));
+ base::Bind(
+ &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread,
+ this,
+ dst,
+ timestamp));
}
// OnIncomingCapturedVideoFrame is called the thread running the capture device.
@@ -379,8 +386,11 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
frame->shared_memory_handle()) >= 0) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, frame, timestamp));
+ base::Bind(
+ &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread,
+ this,
+ frame,
+ timestamp));
return;
}
// Otherwise, this is a frame that belongs to the caller, and we must copy
@@ -475,8 +485,58 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, target, timestamp));
+ base::Bind(
+ &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread,
+ this,
+ target,
+ timestamp));
+}
+
+void VideoCaptureController::OnIncomingCapturedEncodedBitstreamBuffer(
+ const scoped_refptr<media::EncodedBitstreamBuffer>& buffer,
+ size_t data_size,
+ base::Time timestamp) {
+
+ scoped_refptr<media::EncodedBitstreamBuffer> target;
+ {
+ base::AutoLock lock(buffer_pool_lock_);
+ if (!buffer_pool_.get())
+ return;
+ // If this is a frame that belongs to the buffer pool, we can forward it
+ // directly to the IO thread and be done.
+ if (buffer_pool_->RecognizeReservedBuffer(
+ buffer->shared_memory_handle()) >= 0) {
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &VideoCaptureController::
+ DoIncomingCapturedEncodedBitstreamBufferOnIOThread,
+ this,
+ buffer,
+ data_size,
+ timestamp));
+ return;
+ }
+ // Otherwise, this is a frame that belongs to the caller, and we must copy
+ // it to a frame from the buffer pool.
+ target = ReserveOutputEncodedBitstreamBuffer();
+ }
+
+ if (!target.get())
+ return;
+ if (data_size > target->size())
+ return;
+ memcpy(buffer_pool_->GetMemory(target->buffer_id()),
+ buffer->buffer(), data_size);
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &VideoCaptureController::
+ DoIncomingCapturedEncodedBitstreamBufferOnIOThread,
+ this,
+ target,
+ data_size,
+ timestamp));
}
void VideoCaptureController::OnError() {
@@ -501,45 +561,47 @@ void VideoCaptureController::OnFrameInfo(
} else {
chopped_height_ = 0;
}
- BrowserThread::PostTask(BrowserThread::IO,
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this, false));
}
-// static
-scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveI420VideoFrame(
- VideoCaptureBufferPool* buffer_pool, const gfx::Size& size) {
- if ((size_t)(size.GetArea() * 3 / 2) > buffer_pool->GetMemorySize())
- return NULL;
+void VideoCaptureController::OnEncodedFrameInfo(
+ const media::VideoEncodingParameters& encoded_info) {
+ encoded_frame_info_ = encoded_info;
- int buffer_id = buffer_pool->ReserveForProducer();
- if (buffer_id < 0)
- return NULL;
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this, true));
+}
- base::Closure disposal_handler = base::Bind(
- &VideoCaptureBufferPool::RelinquishProducerReservation,
- buffer_pool,
- buffer_id);
+void VideoCaptureController::OnBitstreamConfigChanged(
+ const media::RuntimeVideoEncodingParameters& params) {
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoBitstreamConfigChangedOnIOThread,
+ this,
+ params));
+}
- // Wrap the buffer in a VideoFrame container.
- uint8* base_ptr = static_cast<uint8*>(buffer_pool->GetMemory(buffer_id));
- size_t u_offset = size.GetArea();
- size_t v_offset = u_offset + u_offset / 4;
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalYuvData(
- buffer_pool->GetHandle(buffer_id),
- media::VideoFrame::YV12, // Actually it's I420, but equivalent here.
- size, gfx::Rect(size), size,
- size.width(), // y stride
- size.width() / 2, // u stride
- size.width() / 2, // v stride
- base_ptr, // y address
- base_ptr + u_offset, // u address
- base_ptr + v_offset, // v address
- base::TimeDelta(), // timestamp (unused).
- disposal_handler);
+scoped_refptr<media::VideoFrame>
+VideoCaptureController::ReserveOutputVideoFrame() {
+ base::AutoLock lock(buffer_pool_lock_);
+ if (!buffer_pool_.get())
+ return NULL;
+ return ReserveI420VideoFrame(buffer_pool_, gfx::Size(frame_info_.width,
+ frame_info_.height));
+}
- return frame;
+scoped_refptr<media::EncodedBitstreamBuffer>
+VideoCaptureController::ReserveOutputEncodedBitstreamBuffer() {
+ base::AutoLock lock(buffer_pool_lock_);
+ if (!buffer_pool_.get())
+ return NULL;
+ return ReserveEncodedBitstreamBuffer(buffer_pool_);
}
VideoCaptureController::~VideoCaptureController() {
@@ -557,16 +619,35 @@ void VideoCaptureController::OnDeviceStopped() {
base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this));
}
-void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
- const scoped_refptr<media::VideoFrame>& reserved_frame,
+void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
+ const scoped_refptr<media::VideoFrame>& frame,
+ base::Time timestamp) {
+ DoIncomingCapturedSharedMemoryOnIOThread(
+ frame->shared_memory_handle(),
+ frame->coded_size().GetArea() * 3 / 2,
+ timestamp);
+}
+
+void VideoCaptureController::DoIncomingCapturedEncodedBitstreamBufferOnIOThread(
+ const scoped_refptr<media::EncodedBitstreamBuffer>& buffer,
+ size_t data_size,
+ base::Time timestamp) {
+ DoIncomingCapturedSharedMemoryOnIOThread(
+ buffer->shared_memory_handle(),
+ data_size,
+ timestamp);
+}
+
+void VideoCaptureController::DoIncomingCapturedSharedMemoryOnIOThread(
+ base::SharedMemoryHandle reserved_handle,
+ size_t data_size,
base::Time timestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!buffer_pool_.get())
return;
- int buffer_id = buffer_pool_->RecognizeReservedBuffer(
- reserved_frame->shared_memory_handle());
+ int buffer_id = buffer_pool_->RecognizeReservedBuffer(reserved_handle);
if (buffer_id < 0) {
NOTREACHED();
return;
@@ -580,7 +661,8 @@ void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
continue;
(*client_it)->event_handler->OnBufferReady((*client_it)->controller_id,
- buffer_id, timestamp);
+ buffer_id, data_size,
+ timestamp, false);
(*client_it)->buffers.insert(buffer_id);
count++;
}
@@ -589,7 +671,7 @@ void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
buffer_pool_->HoldForConsumers(buffer_id, count);
}
-void VideoCaptureController::DoFrameInfoOnIOThread() {
+void VideoCaptureController::DoFrameInfoOnIOThread(bool encoded) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!buffer_pool_.get())
<< "Device is restarted without releasing shared memory.";
@@ -598,9 +680,14 @@ void VideoCaptureController::DoFrameInfoOnIOThread() {
if (state_ != VIDEO_CAPTURE_STATE_STARTED)
return;
- scoped_refptr<VideoCaptureBufferPool> buffer_pool =
- new VideoCaptureBufferPool(frame_info_.width * frame_info_.height * 3 / 2,
- kNoOfBuffers);
+ scoped_refptr<VideoCaptureBufferPool> buffer_pool;
+ if (encoded) {
+ buffer_pool = new VideoCaptureBufferPool(
+ encoded_frame_info_.runtime_params.max_bitrate, kNoOfBuffers);
+ } else {
+ buffer_pool = new VideoCaptureBufferPool(
+ frame_info_.width * frame_info_.height * 3 / 2, kNoOfBuffers);
+ }
// Check whether all buffers were created successfully.
if (!buffer_pool->Allocate()) {
@@ -616,7 +703,10 @@ void VideoCaptureController::DoFrameInfoOnIOThread() {
base::AutoLock lock(buffer_pool_lock_);
buffer_pool_ = buffer_pool;
}
- frame_info_available_ = true;
+ if (encoded)
+ encoded_frame_info_available_ = true;
+ else
+ frame_info_available_ = true;
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
@@ -624,6 +714,17 @@ void VideoCaptureController::DoFrameInfoOnIOThread() {
}
}
+void VideoCaptureController::DoBitstreamConfigChangedOnIOThread(
+ const media::RuntimeVideoEncodingParameters& params) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ for (ControllerClients::iterator client_it = controller_clients_.begin();
+ client_it != controller_clients_.end(); ++client_it) {
+ (*client_it)->event_handler->OnBitstreamConfigChanged(
+ (*client_it)->controller_id,
+ params);
+ }
+}
+
void VideoCaptureController::DoErrorOnIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
state_ = VIDEO_CAPTURE_STATE_ERROR;
@@ -648,21 +749,31 @@ void VideoCaptureController::DoDeviceStoppedOnIOThread() {
void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(frame_info_available_);
- client->event_handler->OnFrameInfo(client->controller_id,
- frame_info_.width, frame_info_.height,
- frame_info_.frame_rate);
- if (!buffer_pool_.get())
- return;
+ DCHECK(frame_info_available_ || encoded_frame_info_available_);
+ std::vector<base::SharedMemoryHandle> handles;
for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) {
base::SharedMemoryHandle remote_handle =
buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle);
-
- client->event_handler->OnBufferCreated(client->controller_id,
- remote_handle,
- buffer_pool_->GetMemorySize(),
- buffer_id);
+ handles.push_back(remote_handle);
+ }
+ if (frame_info_available_) {
+ DCHECK(!encoded_frame_info_available_);
+ media::VideoCaptureParams params;
+ params.width = frame_info_.width;
+ params.height = frame_info_.height;
+ params.frame_per_second = frame_info_.frame_rate;
+ params.session_id = client->parameters.session_id;
+ client->event_handler->OnFrameInfo(client->controller_id,
+ params,
+ handles,
+ buffer_pool_->GetMemorySize());
+ } else {
+ DCHECK(!frame_info_available_);
+ client->event_handler->OnEncodedFrameInfo(client->controller_id,
+ encoded_frame_info_,
+ handles,
+ buffer_pool_->GetMemorySize());
}
}
@@ -694,6 +805,69 @@ VideoCaptureController::FindClient(
return NULL;
}
+// static
+scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveI420VideoFrame(
+ VideoCaptureBufferPool* buffer_pool, const gfx::Size& size) {
+ if ((size_t)(size.GetArea() * 3 / 2) > buffer_pool->GetMemorySize())
+ return NULL;
+
+ int buffer_id = buffer_pool->ReserveForProducer();
+ if (buffer_id < 0)
+ return NULL;
+
+ base::Closure disposal_handler = base::Bind(
+ &VideoCaptureBufferPool::RelinquishProducerReservation,
+ buffer_pool,
+ buffer_id);
+
+ // Wrap the buffer in a VideoFrame container.
+ uint8* base_ptr = static_cast<uint8*>(buffer_pool->GetMemory(buffer_id));
+ size_t u_offset = size.GetArea();
+ size_t v_offset = u_offset + u_offset / 4;
+ scoped_refptr<media::VideoFrame> frame =
+ media::VideoFrame::WrapExternalYuvData(
+ buffer_pool->GetHandle(buffer_id),
+ media::VideoFrame::YV12, // Actually it's I420, but equivalent here.
+ size, gfx::Rect(size), size,
+ size.width(), // y stride
+ size.width() / 2, // u stride
+ size.width() / 2, // v stride
+ base_ptr, // y address
+ base_ptr + u_offset, // u address
+ base_ptr + v_offset, // v address
+ base::TimeDelta(), // timestamp (unused).
+ disposal_handler);
+
+ return frame;
+}
+
+// static
+scoped_refptr<media::EncodedBitstreamBuffer>
+VideoCaptureController::ReserveEncodedBitstreamBuffer(
+ VideoCaptureBufferPool* buffer_pool) {
+ int buffer_id = buffer_pool->ReserveForProducer();
+ if (buffer_id < 0)
+ return NULL;
+
+ base::Closure disposal_handler = base::Bind(
+ &VideoCaptureBufferPool::RelinquishProducerReservation,
+ buffer_pool,
+ buffer_id);
+
+ // Wrap the buffer in a VideoFrame container.
+ media::BufferEncodingMetadata metadata;
+ metadata.key_frame = false;
+ scoped_refptr<media::EncodedBitstreamBuffer> frame =
+ new media::EncodedBitstreamBuffer(
+ buffer_id,
+ reinterpret_cast<uint8*>(buffer_pool->GetMemory(buffer_id)),
+ buffer_pool->GetMemorySize(),
+ buffer_pool->GetHandle(buffer_id),
+ metadata,
+ disposal_handler);
+ return frame;
+}
+
// This function is called when all buffers have been returned to controller,
// or when device is stopped. It decides whether the device needs to be
// restarted.

Powered by Google App Engine
This is Rietveld 408576698