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 f23f50f82b2a771746ce012cbccebb0dc82cce94..1330a72a6e99ff8cb56c367783a2d89d738fbf2b 100644 |
--- a/content/browser/renderer_host/media/video_capture_controller.cc |
+++ b/content/browser/renderer_host/media/video_capture_controller.cc |
@@ -4,6 +4,7 @@ |
#include "content/browser/renderer_host/media/video_capture_controller.h" |
+#include <map> |
#include <set> |
#include "base/bind.h" |
@@ -12,6 +13,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 "gpu/command_buffer/common/mailbox_holder.h" |
#include "media/base/video_frame.h" |
#include "media/base/video_util.h" |
#include "media/base/yuv_convert.h" |
@@ -74,8 +76,9 @@ struct VideoCaptureController::ControllerClient { |
// Buffers that are currently known to this client. |
std::set<int> known_buffers; |
- // Buffers currently held by this client. |
- std::set<int> active_buffers; |
+ // Buffers currently held by this client, and syncpoint callback to call when |
+ // they are returned from the client. |
+ std::map<int, scoped_refptr<media::VideoFrame> > active_buffers; |
// State of capture session, controlled by VideoCaptureManager directly. This |
// transitions to true as soon as StopSession() occurs, at which point the |
@@ -112,15 +115,14 @@ class VideoCaptureController::VideoCaptureDeviceClient |
const gfx::Size& size) OVERRIDE; |
virtual void OnIncomingCapturedFrame(const uint8* data, |
int length, |
- base::TimeTicks timestamp, |
+ const VideoCaptureFormat& frame_format, |
int rotation, |
- const VideoCaptureFormat& frame_format) |
- OVERRIDE; |
- virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer, |
- media::VideoFrame::Format format, |
- const gfx::Size& dimensions, |
- base::TimeTicks timestamp, |
- int frame_rate) OVERRIDE; |
+ base::TimeTicks timestamp) OVERRIDE; |
+ virtual void OnIncomingCapturedVideoFrame( |
+ const scoped_refptr<Buffer>& buffer, |
+ const VideoCaptureFormat& buffer_format, |
+ const scoped_refptr<media::VideoFrame>& frame, |
+ base::TimeTicks timestamp) OVERRIDE; |
virtual void OnError() OVERRIDE; |
private: |
@@ -206,11 +208,11 @@ int VideoCaptureController::RemoveClient( |
return kInvalidMediaCaptureSessionId; |
// Take back all buffers held by the |client|. |
- for (std::set<int>::iterator buffer_it = client->active_buffers.begin(); |
+ for (std::map<int, scoped_refptr<media::VideoFrame> >::iterator buffer_it = |
+ client->active_buffers.begin(); |
buffer_it != client->active_buffers.end(); |
++buffer_it) { |
- int buffer_id = *buffer_it; |
- buffer_pool_->RelinquishConsumerHold(buffer_id, 1); |
+ buffer_pool_->RelinquishConsumerHold(buffer_it->first, 1); |
} |
client->active_buffers.clear(); |
@@ -236,17 +238,25 @@ void VideoCaptureController::StopSession(int session_id) { |
void VideoCaptureController::ReturnBuffer( |
const VideoCaptureControllerID& id, |
VideoCaptureControllerEventHandler* event_handler, |
- int buffer_id) { |
+ int buffer_id, |
+ uint32 sync_point) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
ControllerClient* client = FindClient(id, event_handler, controller_clients_); |
// If this buffer is not held by this client, or this client doesn't exist |
// in controller, do nothing. |
- if (!client || !client->active_buffers.erase(buffer_id)) { |
+ std::map<int, scoped_refptr<media::VideoFrame> >::iterator iter; |
+ if (!client || (iter = client->active_buffers.find(buffer_id)) == |
+ client->active_buffers.end()) { |
NOTREACHED(); |
return; |
} |
+ scoped_refptr<media::VideoFrame> frame = iter->second; |
+ client->active_buffers.erase(iter); |
+ |
+ if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) |
+ frame->mailbox_holder()->sync_point = sync_point; |
buffer_pool_->RelinquishConsumerHold(buffer_id, 1); |
} |
@@ -267,9 +277,9 @@ VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer( |
void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( |
const uint8* data, |
int length, |
- base::TimeTicks timestamp, |
+ const VideoCaptureFormat& frame_format, |
int rotation, |
- const VideoCaptureFormat& frame_format) { |
+ base::TimeTicks timestamp) { |
TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); |
if (!frame_format.IsValid()) |
@@ -394,37 +404,48 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( |
// address all these #ifdef parts, see http://crbug.com/299611 . |
NOTREACHED(); |
#endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) |
+ VideoCaptureFormat format( |
+ dimensions, frame_format.frame_rate, media::PIXEL_FORMAT_I420); |
+ scoped_refptr<media::VideoFrame> frame = |
+ media::VideoFrame::WrapExternalPackedMemory( |
+ media::VideoFrame::I420, |
+ dimensions, |
+ gfx::Rect(dimensions), |
+ dimensions, |
+ yplane, |
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420, |
+ dimensions), |
+ base::SharedMemory::NULLHandle(), |
+ base::TimeDelta(), |
+ base::Closure()); |
+ DCHECK(frame); |
BrowserThread::PostTask( |
BrowserThread::IO, |
FROM_HERE, |
base::Bind( |
- &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread, |
+ &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
controller_, |
buffer, |
- dimensions, |
- frame_format.frame_rate, |
+ format, |
+ frame, |
timestamp)); |
} |
-void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
+void |
+VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
const scoped_refptr<Buffer>& buffer, |
- media::VideoFrame::Format format, |
- const gfx::Size& dimensions, |
- base::TimeTicks timestamp, |
- int frame_rate) { |
- // The capture pipeline expects I420 for now. |
- DCHECK_EQ(format, media::VideoFrame::I420) |
- << "Non-I420 output buffer returned"; |
- |
+ const VideoCaptureFormat& buffer_format, |
+ const scoped_refptr<media::VideoFrame>& frame, |
+ base::TimeTicks timestamp) { |
BrowserThread::PostTask( |
BrowserThread::IO, |
FROM_HERE, |
base::Bind( |
- &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread, |
+ &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
mcasas
2014/01/21 14:34:02
I think the "unification" of VCC::VCDC::OnIncoming
|
controller_, |
buffer, |
- dimensions, |
- frame_rate, |
+ buffer_format, |
+ frame, |
timestamp)); |
} |
@@ -438,14 +459,18 @@ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> |
VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer( |
media::VideoFrame::Format format, |
const gfx::Size& dimensions) { |
- // The capture pipeline expects I420 for now. |
- DCHECK_EQ(format, media::VideoFrame::I420) |
- << "Non-I420 output buffer requested"; |
+ size_t frame_bytes = 0; |
+ if (format == media::VideoFrame::NATIVE_TEXTURE) { |
+ DCHECK_EQ(dimensions.width(), 0); |
+ DCHECK_EQ(dimensions.height(), 0); |
+ } else { |
+ // The capture pipeline expects I420 for now. |
+ DCHECK_EQ(format, media::VideoFrame::I420) |
+ << "Non-I420 output buffer format " << format << " requested"; |
mcasas
2014/01/21 14:34:02
Being |format| numeric, not sure this DCHECK would
sheu
2014/01/29 01:19:20
Not very informative, but I think sufficient for a
|
+ frame_bytes = media::VideoFrame::AllocationSize(format, dimensions); |
+ } |
int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
- const size_t frame_bytes = |
- media::VideoFrame::AllocationSize(format, dimensions); |
- |
int buffer_id = |
buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); |
if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
@@ -472,17 +497,14 @@ VideoCaptureController::~VideoCaptureController() { |
controller_clients_.end()); |
} |
-void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread( |
- scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
- const gfx::Size& dimensions, |
- int frame_rate, |
+void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( |
+ const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, |
+ const media::VideoCaptureFormat& buffer_format, |
+ const scoped_refptr<media::VideoFrame>& frame, |
base::TimeTicks timestamp) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); |
- VideoCaptureFormat frame_format( |
- dimensions, frame_rate, media::PIXEL_FORMAT_I420); |
- |
int count = 0; |
if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
for (ControllerClients::iterator client_it = controller_clients_.begin(); |
@@ -491,19 +513,30 @@ void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread( |
if (client->session_closed) |
continue; |
- bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; |
- if (is_new_buffer) { |
- // On the first use of a buffer on a client, share the memory handle. |
- size_t memory_size = 0; |
- base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( |
- buffer->id(), client->render_process_handle, &memory_size); |
- client->event_handler->OnBufferCreated( |
- client->controller_id, remote_handle, memory_size, buffer->id()); |
+ if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { |
+ client->event_handler->OnMailboxBufferReady(client->controller_id, |
+ buffer->id(), |
+ *frame->mailbox_holder(), |
+ buffer_format, |
+ timestamp); |
+ } else { |
+ bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; |
+ if (is_new_buffer) { |
+ // On the first use of a buffer on a client, share the memory handle. |
+ size_t memory_size = 0; |
+ base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( |
+ buffer->id(), client->render_process_handle, &memory_size); |
+ client->event_handler->OnBufferCreated( |
+ client->controller_id, remote_handle, memory_size, buffer->id()); |
+ } |
+ |
+ client->event_handler->OnBufferReady( |
+ client->controller_id, buffer->id(), buffer_format, timestamp); |
} |
- client->event_handler->OnBufferReady( |
- client->controller_id, buffer->id(), timestamp, frame_format); |
- bool inserted = client->active_buffers.insert(buffer->id()).second; |
+ bool inserted = |
+ client->active_buffers.insert(std::make_pair(buffer->id(), frame)) |
+ .second; |
DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id(); |
count++; |
} |