Chromium Code Reviews| Index: content/browser/renderer_host/video_capture_host.cc |
| =================================================================== |
| --- content/browser/renderer_host/video_capture_host.cc (revision 0) |
| +++ content/browser/renderer_host/video_capture_host.cc (revision 0) |
| @@ -0,0 +1,249 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/video_capture_host.h" |
| + |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/stl_util-inl.h" |
| +#include "content/browser/media_stream/video_capture_manager.h" |
| +#include "content/common/video_capture_messages.h" |
| + |
| +VideoCaptureHost::VideoCaptureHost() {} |
| + |
| +VideoCaptureHost::~VideoCaptureHost() { |
| + DCHECK(vc_entries_.empty()); |
| + // Delete all Memory handlers that have been stopped but not returned all |
| + // TransportDIBs. |
| + STLDeleteContainerPairSecondPointers(vc_stoped_entries_.begin(), |
| + vc_stoped_entries_.end()); |
| + vc_stoped_entries_.clear(); |
| +} |
| + |
| +void VideoCaptureHost::OnChannelClosing() { |
| + BrowserMessageFilter::OnChannelClosing(); |
| + |
| + // Since the IPC channel is gone, close all requested VideCaptureDevices. |
| + for (VCEntryMap::iterator it = vc_entries_.begin(); |
| + it != vc_entries_.end(); it++) { |
| + StopVideoCapture(it->second->entry_id()); |
| + } |
| +} |
| + |
| +void VideoCaptureHost::OnDestruct() const { |
| + BrowserThread::DeleteOnIOThread::Destruct(this); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +// Implements VideoCaptureMemory::EventHandler. |
| +void VideoCaptureHost::OnError(VideoCaptureMemory::VCEntryId entry) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod(this, &VideoCaptureHost::DoHandleError, entry)); |
| +} |
| + |
| +void VideoCaptureHost::OnBufferReady(VideoCaptureMemory::VCEntryId entry, |
| + TransportDIB::Handle handle, |
| + base::Time timestamp) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod(this, &VideoCaptureHost::DoSendFilledBuffer, entry, |
| + handle, timestamp)); |
| +} |
| + |
| +void VideoCaptureHost::OnFrameInfo(VideoCaptureMemory::VCEntryId entry, |
| + int width, |
| + int height, |
| + int frame_per_second) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod(this, &VideoCaptureHost::DoSendFrameInfo, entry, width, |
| + height, frame_per_second)); |
| +} |
| + |
| +void VideoCaptureHost::DoSendFilledBuffer(VideoCaptureMemory::VCEntryId entry, |
| + TransportDIB::Handle handle, |
| + base::Time timestamp) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + Send(new VideoCaptureMsg_BufferReady(entry.render_id, entry.device_id, handle, |
| + timestamp)); |
| +} |
| + |
| +void VideoCaptureHost::DoHandleError(VideoCaptureMemory::VCEntryId entry) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + SendErrorMessage(entry.render_id, entry.device_id); |
| + StopVideoCapture(entry); |
| +} |
| + |
| +void VideoCaptureHost::DoSendFrameInfo(VideoCaptureMemory::VCEntryId entry, |
| + int width, |
| + int height, |
| + int frame_per_second) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + media::VideoCaptureParams params; |
| + params.width = width; |
| + params.height = height; |
| + params.frame_per_second = frame_per_second; |
| + Send(new VideoCaptureMsg_DeviceInfo(entry.render_id, |
| + entry.device_id, |
| + params)); |
| + Send(new VideoCaptureMsg_StateChanged(entry.render_id, entry.device_id, |
| + media::VideoCapture::kStarted)); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| +// IPC Messages handler. |
| +bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message, |
| + bool* message_was_ok) { |
| + bool handled = true; |
| + IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost, message, *message_was_ok) |
| + IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture) |
| + IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture) |
| + IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture) |
| + IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer) |
| + IPC_MESSAGE_UNHANDLED(handled = false) |
| + IPC_END_MESSAGE_MAP_EX() |
| + |
| + return handled; |
| +} |
| + |
| +void VideoCaptureHost::OnStartCapture( |
| + const IPC::Message& msg, int device_id, |
|
wjia(left Chromium)
2011/05/11 23:23:31
indent
Per K
2011/05/16 11:49:39
Done.
|
| + const media::VideoCaptureParams& params) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + VideoCaptureMemory::VCEntryId entry(msg.routing_id(), |
| + device_id, |
| + params.session_id); |
| + // Check that it is not already started. |
| + DCHECK(LookupStartedDevicesById(device_id) == NULL); |
| + VideoCaptureMemory* memory_handler = new VideoCaptureMemory(this, entry); |
| + if (!memory_handler) { |
| + SendErrorMessage(msg.routing_id(), device_id); |
| + return; |
| + } |
| + |
| + media_stream::VideoCaptureManager* manager = |
| + media_stream::VideoCaptureManager::Get(); |
| + // Order the manager to start the actual capture. |
| + manager->Start(params, memory_handler); |
| + |
| + vc_entries_.insert(std::make_pair(device_id, memory_handler)); |
|
wjia(left Chromium)
2011/05/11 23:23:31
Some thoughts about the modules:
1. Host only nee
Per K
2011/05/16 11:49:39
VCEntryId moved to VideoCaptureHost and called Vid
|
| +} |
| + |
| +void VideoCaptureHost::OnStopCapture(const IPC::Message& msg, int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + VideoCaptureMemory* memory_handler = LookupStartedDevicesById(device_id); |
|
wjia(left Chromium)
2011/05/11 23:23:31
would it be good to pass Stop command to memory_ha
Per K
2011/05/16 11:49:39
Done.
|
| + if (!memory_handler) { |
| + // Check if the device is being stopped |
| + if (!LookupStopedDevicesById(device_id)) { |
| + // It does not exist so it must have been stopped already. |
| + Send(new VideoCaptureMsg_StateChanged(msg.routing_id(), device_id, |
| + media::VideoCapture::kStopped)); |
| + } |
| + return; |
| + } |
| + StopVideoCapture(memory_handler->entry_id()); |
| +} |
| + |
| +void VideoCaptureHost::OnPauseCapture(const IPC::Message& msg, int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + // Not used. |
| + SendErrorMessage(msg.routing_id(), device_id); |
| +} |
| + |
| +void VideoCaptureHost::OnReceiveEmptyBuffer(const IPC::Message& msg, |
| + int device_id, |
| + TransportDIB::Handle handle) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + VideoCaptureMemory* memory_handler = LookupStartedDevicesById(device_id); |
| + if (!memory_handler || memory_handler->AddTransportDIB(handle) != 0) { |
| + // This buffer do not belong to an active VideoCaptureMemory instance |
| + // Check the Stopped Devices. |
| + memory_handler = LookupStopedDevicesById(device_id); |
| + if (memory_handler) { |
| + memory_handler->AddTransportDIB(handle); |
| + if (memory_handler->ReadyToDelete()) { |
| + SendDeviceStopped(msg.routing_id(), device_id); |
| + scoped_ptr<VideoCaptureMemory> item_to_delete(memory_handler); |
| + vc_stoped_entries_.erase(device_id); |
| + } |
| + } |
| + } |
| +} |
| + |
| +void VideoCaptureHost::StopVideoCapture(VideoCaptureMemory::VCEntryId entry) { |
| + media_stream::VideoCaptureManager* manager = |
| + media_stream::VideoCaptureManager::Get(); |
| + manager->Stop(entry.session_id, |
| + NewRunnableMethod(this, &VideoCaptureHost::OnDeviceStoped, |
| + entry.device_id)); |
| +} |
| + |
| +void VideoCaptureHost::OnDeviceStoped(int device_id) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod(this, &VideoCaptureHost::DoDeviceStoped, device_id)); |
| +} |
| + |
| +void VideoCaptureHost::DoDeviceStoped(int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + scoped_ptr<VideoCaptureMemory> memory_handler( |
| + LookupStartedDevicesById(device_id)); |
| + if (!memory_handler.get()) { |
| + return; |
| + } |
| + |
| + vc_entries_.erase(device_id); |
| + |
| + // If we can not delete the memory_handler now because all |
| + // DIBS have not been returned we add the vc_entry to the list of stopped |
| + // devices and do it later and hopefully get the missing DIB back soon. |
| + if (!memory_handler->ReadyToDelete()) { |
| + vc_stoped_entries_.insert( |
| + std::make_pair(device_id, memory_handler.release())); |
| + } else { |
| + // We have received all buffers and is ready to delete the memory pool. |
| + const VideoCaptureMemory::VCEntryId entry_id = memory_handler->entry_id(); |
| + SendDeviceStopped(entry_id.render_id, entry_id.device_id); |
| + } |
| +} |
| + |
| +void VideoCaptureHost::SendDeviceStopped(int32 render_view_id, int device_id) { |
| + // Report that the device have successfully been stopped. |
| + Send(new VideoCaptureMsg_StateChanged(render_view_id, device_id, |
| + media::VideoCapture::kStopped)); |
| +} |
| + |
| +void VideoCaptureHost::SendErrorMessage(int32 render_view_id, int32 device_id) { |
| + Send(new VideoCaptureMsg_StateChanged(render_view_id, device_id, |
| + media::VideoCapture::kError)); |
|
wjia(left Chromium)
2011/05/11 23:23:31
Is it needed for renderer process to distinguish d
Per K
2011/05/16 11:49:39
I am not really sure we will be able to distinguis
|
| +} |
| + |
| +VideoCaptureMemory* VideoCaptureHost::LookupStartedDevicesById(int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + VCEntryMap::iterator it = vc_entries_.find(device_id); |
| + if (it != vc_entries_.end()) { |
| + return it->second; |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| +VideoCaptureMemory* VideoCaptureHost::LookupStopedDevicesById(int device_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + VCEntryMap::iterator it = vc_stoped_entries_.find(device_id); |
| + if (it != vc_stoped_entries_.end()) { |
| + return it->second; |
| + } |
| + |
| + return NULL; |
| +} |