Chromium Code Reviews| Index: content/browser/renderer_host/media/video_capture_host.cc |
| diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc |
| index 9c4fc77a2dafaee5b5b2e81963776577fd1e6e74..81fab52df64b4c8562eda4fa4513b7069e5bf512 100644 |
| --- a/content/browser/renderer_host/media/video_capture_host.cc |
| +++ b/content/browser/renderer_host/media/video_capture_host.cc |
| @@ -10,17 +10,21 @@ |
| #include "content/browser/browser_main_loop.h" |
| #include "content/browser/renderer_host/media/media_stream_manager.h" |
| #include "content/browser/renderer_host/media/video_capture_manager.h" |
| +#include "content/common/media/encoded_video_capture_messages.h" |
| #include "content/common/media/video_capture_messages.h" |
| +#include "media/video/video_encode_types.h" |
| namespace content { |
| struct VideoCaptureHost::Entry { |
| Entry(VideoCaptureController* controller) |
| - : controller(controller) {} |
| + : controller(controller), |
| + encoded(false) {} |
| ~Entry() {} |
| scoped_refptr<VideoCaptureController> controller; |
| + bool encoded; |
| }; |
| VideoCaptureHost::VideoCaptureHost() {} |
| @@ -57,36 +61,58 @@ void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) { |
| this, controller_id)); |
| } |
| -void VideoCaptureHost::OnBufferCreated( |
| - const VideoCaptureControllerID& controller_id, |
| - base::SharedMemoryHandle handle, |
| - int length, |
| - int buffer_id) { |
| - BrowserThread::PostTask( |
| - BrowserThread::IO, FROM_HERE, |
| - base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread, |
| - this, controller_id, handle, length, buffer_id)); |
| -} |
| - |
| void VideoCaptureHost::OnBufferReady( |
| const VideoCaptureControllerID& controller_id, |
| int buffer_id, |
| - base::Time timestamp) { |
| + size_t data_size, |
| + base::Time timestamp, |
| + bool key_frame) { |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread, |
| - this, controller_id, buffer_id, timestamp)); |
| + this, controller_id, buffer_id, data_size, timestamp, |
| + key_frame)); |
| } |
| void VideoCaptureHost::OnFrameInfo( |
| const VideoCaptureControllerID& controller_id, |
| - int width, |
| - int height, |
| - int frame_per_second) { |
| + const media::VideoCaptureParams& params, |
| + const std::vector<base::SharedMemoryHandle>& buffers, |
| + size_t buffer_size) { |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&VideoCaptureHost::DoSendFrameInfoOnIOThread, |
| - this, controller_id, width, height, frame_per_second)); |
| + this, |
| + controller_id, |
| + params, |
| + buffers, |
| + buffer_size)); |
| +} |
| + |
| +void VideoCaptureHost::OnEncodedFrameInfo( |
| + const VideoCaptureControllerID& controller_id, |
| + const media::VideoEncodingParameters& params, |
| + const std::vector<base::SharedMemoryHandle>& buffers, |
| + size_t buffer_size) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&VideoCaptureHost::DoSendEncodedFrameInfoOnIOThread, |
| + this, |
| + controller_id, |
| + params, |
| + buffers, |
| + buffer_size)); |
| +} |
| + |
| +void VideoCaptureHost::OnBitstreamConfigChanged( |
| + const VideoCaptureControllerID& controller_id, |
| + const media::RuntimeVideoEncodingParameters& params) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&VideoCaptureHost::DoBitstreamConfigChangedOnIOThread, |
| + this, |
| + controller_id, |
| + params)); |
| } |
| void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) { |
| @@ -96,71 +122,120 @@ void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) { |
| base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id)); |
| } |
| -void VideoCaptureHost::DoSendNewBufferOnIOThread( |
| +void VideoCaptureHost::DoSendFilledBufferOnIOThread( |
| const VideoCaptureControllerID& controller_id, |
| - base::SharedMemoryHandle handle, |
| - int length, |
| - int buffer_id) { |
| + int buffer_id, size_t size, base::Time timestamp, bool key_frame) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - if (entries_.find(controller_id) == entries_.end()) |
| + EntryMap::iterator iter = entries_.find(controller_id); |
| + if (iter == entries_.end()) |
| return; |
| - Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle, |
| - length, buffer_id)); |
| + if (iter->second->encoded) { |
| + media::BufferEncodingMetadata metadata; |
| + metadata.timestamp = timestamp; |
| + metadata.key_frame = key_frame; |
| + Send(new EncodedVideoCaptureMsg_BitstreamReady(controller_id.device_id, |
| + buffer_id, |
| + size, |
| + metadata)); |
| + } else { |
| + Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id, |
| + timestamp)); |
| + } |
| } |
| -void VideoCaptureHost::DoSendFilledBufferOnIOThread( |
| - const VideoCaptureControllerID& controller_id, |
| - int buffer_id, base::Time timestamp) { |
| +void VideoCaptureHost::DoHandleErrorOnIOThread( |
| + const VideoCaptureControllerID& controller_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - if (entries_.find(controller_id) == entries_.end()) |
| + EntryMap::iterator iter = entries_.find(controller_id); |
| + if (iter == entries_.end()) |
| return; |
| - Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id, |
| - timestamp)); |
| + if (iter->second->encoded) { |
| + Send(new EncodedVideoCaptureHostMsg_DestroyBitstream( |
| + controller_id.device_id)); |
|
hshi1
2013/06/20 22:51:02
How can browser send EncodedVideoCaptureHostMsg to
sheu
2013/08/22 22:40:31
Done.
|
| + } else { |
| + Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, |
| + VIDEO_CAPTURE_STATE_ERROR)); |
| + } |
| + DeleteVideoCaptureControllerOnIOThread(controller_id); |
| } |
| -void VideoCaptureHost::DoHandleErrorOnIOThread( |
| - const VideoCaptureControllerID& controller_id) { |
| +void VideoCaptureHost::DoSendFrameInfoOnIOThread( |
| + const VideoCaptureControllerID& controller_id, |
| + const media::VideoCaptureParams& params, |
| + const std::vector<base::SharedMemoryHandle>& buffers, |
| + size_t buffer_size) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - if (entries_.find(controller_id) == entries_.end()) |
| + EntryMap::iterator iter = entries_.find(controller_id); |
| + if (iter == entries_.end()) |
| return; |
| + DCHECK(!iter->second->encoded); |
| + Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params)); |
| Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, |
| - VIDEO_CAPTURE_STATE_ERROR)); |
| - DeleteVideoCaptureControllerOnIOThread(controller_id); |
| + VIDEO_CAPTURE_STATE_STARTED)); |
| + for (size_t i = 0; i < buffers.size(); ++i) { |
| + Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, |
| + buffers[i], |
| + buffer_size, |
| + i)); |
| + } |
| +} |
| + |
| +void VideoCaptureHost::DoSendEncodedFrameInfoOnIOThread( |
| + const VideoCaptureControllerID& controller_id, |
| + const media::VideoEncodingParameters& params, |
| + const std::vector<base::SharedMemoryHandle>& buffers, |
| + size_t buffer_size) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + EntryMap::iterator iter = entries_.find(controller_id); |
| + if (iter == entries_.end()) |
| + return; |
| + |
| + DCHECK(iter->second->encoded); |
| + Send(new EncodedVideoCaptureMsg_BitstreamCreated(controller_id.device_id, |
| + params, |
| + buffers, |
| + buffer_size)); |
| } |
| void VideoCaptureHost::DoEndedOnIOThread( |
| const VideoCaptureControllerID& controller_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread"; |
| - if (entries_.find(controller_id) == entries_.end()) |
| + |
| + EntryMap::iterator iter = entries_.find(controller_id); |
| + if (iter == entries_.end()) |
| return; |
| - Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, |
| - VIDEO_CAPTURE_STATE_ENDED)); |
| + if (iter->second->encoded) { |
| + Send(new EncodedVideoCaptureHostMsg_DestroyBitstream( |
| + controller_id.device_id)); |
| + } else { |
| + Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, |
| + VIDEO_CAPTURE_STATE_ENDED)); |
| + } |
| DeleteVideoCaptureControllerOnIOThread(controller_id); |
| } |
| -void VideoCaptureHost::DoSendFrameInfoOnIOThread( |
| +void VideoCaptureHost::DoBitstreamConfigChangedOnIOThread( |
| const VideoCaptureControllerID& controller_id, |
| - int width, int height, int frame_per_second) { |
| + const media::RuntimeVideoEncodingParameters& params) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - if (entries_.find(controller_id) == entries_.end()) |
| + EntryMap::iterator iter = entries_.find(controller_id); |
| + if (iter == entries_.end()) |
| return; |
| - |
| - media::VideoCaptureParams params; |
| - params.width = width; |
| - params.height = height; |
| - params.frame_per_second = frame_per_second; |
| - Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params)); |
| - Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, |
| - VIDEO_CAPTURE_STATE_STARTED)); |
| + if (!iter->second->encoded) |
| + return; |
| + Send(new EncodedVideoCaptureMsg_BitstreamConfigChanged( |
| + controller_id.device_id, |
| + params)); |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -173,6 +248,16 @@ bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message, |
| IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture) |
| IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture) |
| IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer) |
| + IPC_MESSAGE_HANDLER(EncodedVideoCaptureHostMsg_GetCapabilities, |
| + OnGetCapabilities) |
| + IPC_MESSAGE_HANDLER(EncodedVideoCaptureHostMsg_CreateBitstream, |
| + OnCreateBitstream) |
| + IPC_MESSAGE_HANDLER(EncodedVideoCaptureHostMsg_DestroyBitstream, |
| + OnDestroyBitstream) |
| + IPC_MESSAGE_HANDLER(EncodedVideoCaptureHostMsg_TryConfigureBitstream, |
| + OnTryConfigureBitstream) |
| + IPC_MESSAGE_HANDLER(EncodedVideoCaptureHostMsg_BitstreamBufferConsumed, |
| + OnBitstreamBufferConsumed) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP_EX() |
| @@ -230,6 +315,13 @@ void VideoCaptureHost::DoControllerAddedOnIOThread( |
| controller->StartCapture(controller_id, this, peer_handle(), params); |
| } |
| +void VideoCaptureHost::OnPauseCapture(int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id; |
| + // Not used. |
|
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
NOTREACHED?
piman
2013/06/19 18:33:51
Not NOTREACHED since it can be reached by a malici
|
| + Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR)); |
| +} |
| + |
| void VideoCaptureHost::OnStopCapture(int device_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id; |
| @@ -241,25 +333,98 @@ void VideoCaptureHost::OnStopCapture(int device_id) { |
| DeleteVideoCaptureControllerOnIOThread(controller_id); |
| } |
| -void VideoCaptureHost::OnPauseCapture(int device_id) { |
| +void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id; |
| - // Not used. |
| - Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR)); |
| + |
| + VideoCaptureControllerID controller_id(device_id); |
| + EntryMap::iterator it = entries_.find(controller_id); |
| + if (it != entries_.end()) { |
| + scoped_refptr<VideoCaptureController> controller = it->second->controller; |
| + if (controller.get()) |
| + controller->ReturnBuffer(controller_id, this, buffer_id); |
| + } |
| } |
| -void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) { |
| +void VideoCaptureHost::OnGetCapabilities( |
| + int device_id, |
| + const media::VideoCaptureSessionId& session_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DVLOG(1) << "VideoCaptureHost::OnGetCapabilities, session_id " << session_id; |
| + GetVideoCaptureManager()->RequestEncodingCapabilities( |
| + session_id, |
| + base::Bind(&VideoCaptureHost::OnEncodingCapabilitiesFound, |
| + this, |
| + device_id)); |
| +} |
| + |
| +void VideoCaptureHost::OnEncodingCapabilitiesFound( |
| + int device_id, |
| + const media::VideoEncodingCapabilities& capabilities) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&VideoCaptureHost::DoEncodingCapabilitiesFoundOnIOThread, |
| + this, device_id, capabilities)); |
| +} |
| + |
| +void VideoCaptureHost::DoEncodingCapabilitiesFoundOnIOThread( |
| + int device_id, |
| + const media::VideoEncodingCapabilities& capabilities) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + Send(new EncodedVideoCaptureMsg_CapabilitiesAvailable(device_id, |
| + capabilities)); |
| +} |
| + |
| +void VideoCaptureHost::OnCreateBitstream( |
| + int device_id, |
| + const media::VideoCaptureSessionId& session_id, |
| + const media::VideoEncodingParameters& params) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DVLOG(1) << "VideoCaptureHost::OnCreateBitstream, device_id " << device_id |
| + << ", session_id " << session_id; |
| + media::VideoCaptureParams cap_params; |
| + memset(&cap_params, 0, sizeof(cap_params)); |
| + cap_params.width = params.resolution.width(); |
| + cap_params.height = params.resolution.height(); |
| + cap_params.session_id = session_id; |
| + |
| + VideoCaptureControllerID controller_id(device_id); |
| + DCHECK(entries_.find(controller_id) == entries_.end()); |
|
piman
2013/06/19 18:33:51
This data comes from the untrusted renderer.
This
sheu
2013/08/22 22:40:31
Done. Fixed also for OnStartCapture.
|
| + Entry* entry = new Entry(NULL); |
| + entry->encoded = true; |
| + entries_[controller_id] = entry; |
| + GetVideoCaptureManager()->AddController( |
| + cap_params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this, |
| + device_id, cap_params)); |
| +} |
| + |
| +void VideoCaptureHost::OnDestroyBitstream(int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DVLOG(1) << "VideoCaptureHost::OnDestroyBitstream, device_id " << device_id; |
| + // Proxy over to OnStopCapture. |
| + OnStopCapture(device_id); |
| +} |
| + |
| +void VideoCaptureHost::OnTryConfigureBitstream( |
| + int device_id, |
| + const media::RuntimeVideoEncodingParameters& params) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DVLOG(1) << "VideoCaptureHost::OnTryConfigureBitstream, device_id " |
| + << device_id; |
| VideoCaptureControllerID controller_id(device_id); |
| EntryMap::iterator it = entries_.find(controller_id); |
| if (it != entries_.end()) { |
| scoped_refptr<VideoCaptureController> controller = it->second->controller; |
| if (controller.get()) |
| - controller->ReturnBuffer(controller_id, this, buffer_id); |
| + controller->TryConfigureEncodedBitstream(params); |
| } |
| } |
| +void VideoCaptureHost::OnBitstreamBufferConsumed(int device_id, int buffer_id) { |
| + // Proxy over to OnReceiveEmptyBuffer. |
| + OnReceiveEmptyBuffer(device_id, buffer_id); |
| +} |
| + |
| void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( |
| const VideoCaptureControllerID& controller_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |