summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorwjia@chromium.org <wjia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-04 16:53:12 +0000
committerwjia@chromium.org <wjia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-04 16:53:12 +0000
commit216e2be340f2203c6d188f1f14a5833f7ad1b305 (patch)
tree2f5f182797675f6b2cd0abc66bb29f2c38ea82aa /content/browser
parent904b19af79ea2f08b5645659bb169cb13e3b7eeb (diff)
downloadchromium_src-216e2be340f2203c6d188f1f14a5833f7ad1b305.zip
chromium_src-216e2be340f2203c6d188f1f14a5833f7ad1b305.tar.gz
chromium_src-216e2be340f2203c6d188f1f14a5833f7ad1b305.tar.bz2
Fix media stream stop.
When a capture session is closed, that capture session should be stopped in VideoCaptureController as well. This use case is a bit strange since <video> is not aware of the closure of the captrue session and it will hang there. BUG=124994 TEST=run with the html page in the bug. Review URL: https://chromiumcodereview.appspot.com/10250004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135363 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/renderer_host/media/video_capture_controller.cc41
-rw-r--r--content/browser/renderer_host/media/video_capture_controller.h8
-rw-r--r--content/browser/renderer_host/media/video_capture_host.cc8
-rw-r--r--content/browser/renderer_host/media/video_capture_manager.cc22
4 files changed, 75 insertions, 4 deletions
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index cee8106..bda3d8b 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -27,6 +27,7 @@ struct VideoCaptureController::ControllerClient {
event_handler(handler),
render_process_handle(render_process),
parameters(params),
+ session_closed(false),
report_ready_to_delete(false) {
}
@@ -43,6 +44,9 @@ struct VideoCaptureController::ControllerClient {
// Buffers used by this client.
std::list<int> buffers;
+ // State of capture session, controlled by VideoCaptureManager directly.
+ bool session_closed;
+
// Record client's status when it has called StopCapture, but haven't
// returned all buffers.
bool report_ready_to_delete;
@@ -79,6 +83,13 @@ void VideoCaptureController::StartCapture(
base::ProcessHandle render_process,
const media::VideoCaptureParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureController::StartCapture, id " << id.device_id
+ << ", (" << params.width
+ << ", " << params.height
+ << ", " << params.frame_per_second
+ << ", " << params.session_id
+ << ")";
+
// Signal error in case device is already in error state.
if (state_ == video_capture::kError) {
event_handler->OnError(id);
@@ -136,6 +147,7 @@ void VideoCaptureController::StopCapture(
VideoCaptureControllerEventHandler* event_handler,
bool force_buffer_return) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id;
ControllerClient* client = FindClient(id, event_handler, pending_clients_);
// If the client is still in pending queue, just remove it.
@@ -193,6 +205,19 @@ void VideoCaptureController::StopCapture(
}
}
+void VideoCaptureController::StopSession(
+ int session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id;
+
+ ControllerClient* client = FindClient(session_id, pending_clients_);
+ if (!client)
+ client = FindClient(session_id, controller_clients_);
+
+ if (client)
+ client->session_closed = true;
+}
+
void VideoCaptureController::ReturnBuffer(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
@@ -376,7 +401,8 @@ void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
if (state_ == video_capture::kStarted) {
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); client_it++) {
- if ((*client_it)->report_ready_to_delete)
+ if ((*client_it)->report_ready_to_delete ||
+ (*client_it)->session_closed)
continue;
(*client_it)->event_handler->OnBufferReady((*client_it)->controller_id,
@@ -486,6 +512,19 @@ VideoCaptureController::FindClient(
return NULL;
}
+VideoCaptureController::ControllerClient*
+VideoCaptureController::FindClient(
+ int session_id,
+ const ControllerClients& clients) {
+ for (ControllerClients::const_iterator client_it = clients.begin();
+ client_it != clients.end(); client_it++) {
+ if ((*client_it)->parameters.session_id == session_id) {
+ return *client_it;
+ }
+ }
+ return NULL;
+}
+
// 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.
diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h
index 1d7e2da..94111cc 100644
--- a/content/browser/renderer_host/media/video_capture_controller.h
+++ b/content/browser/renderer_host/media/video_capture_controller.h
@@ -59,6 +59,10 @@ class VideoCaptureController
VideoCaptureControllerEventHandler* event_handler,
bool force_buffer_return);
+ // API called directly by VideoCaptureManager in case the device is
+ // prematurely closed.
+ void StopSession(int session_id);
+
// Return a buffer previously given in
// VideoCaptureControllerEventHandler::OnBufferReady.
void ReturnBuffer(const VideoCaptureControllerID& id,
@@ -100,6 +104,10 @@ class VideoCaptureController
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* handler,
const ControllerClients& clients);
+ // Find a client of |session_id| in |clients|.
+ ControllerClient* FindClient(
+ int session_id,
+ const ControllerClients& clients);
// Decide what to do after kStopping state. Dependent on events, controller
// can stay in kStopping state, or go to kStopped, or restart capture.
void PostStopping();
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc
index 09f6981..a0c7941 100644
--- a/content/browser/renderer_host/media/video_capture_host.cc
+++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -177,6 +177,12 @@ bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
void VideoCaptureHost::OnStartCapture(int device_id,
const media::VideoCaptureParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
+ << ", (" << params.width
+ << ", " << params.height
+ << ", " << params.frame_per_second
+ << ", " << params.session_id
+ << ")";
VideoCaptureControllerID controller_id(device_id);
DCHECK(entries_.find(controller_id) == entries_.end());
@@ -223,6 +229,8 @@ void VideoCaptureHost::DoControllerAddedOnIOThread(
void VideoCaptureHost::OnStopCapture(int device_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
+
VideoCaptureControllerID controller_id(device_id);
EntryMap::iterator it = entries_.find(controller_id);
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index 4b0102e..806b189 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -154,6 +154,7 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
const StreamDeviceInfo& device) {
DCHECK(IsOnCaptureDeviceThread());
DCHECK(devices_.find(capture_session_id) == devices_.end());
+ DVLOG(1) << "VideoCaptureManager::OnOpen, id " << capture_session_id;
// Check if another session has already opened this device. If so, just
// use that opened device.
@@ -186,6 +187,7 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
void VideoCaptureManager::OnClose(int capture_session_id) {
DCHECK(IsOnCaptureDeviceThread());
+ DVLOG(1) << "VideoCaptureManager::OnClose, id " << capture_session_id;
media::VideoCaptureDevice* video_capture_device = NULL;
VideoCaptureDevices::iterator device_it = devices_.find(capture_session_id);
@@ -203,6 +205,14 @@ void VideoCaptureManager::OnClose(int capture_session_id) {
controllers_.erase(cit);
}
delete video_capture_device;
+ } else {
+ Controllers::iterator cit = controllers_.find(video_capture_device);
+ if (cit != controllers_.end()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&VideoCaptureController::StopSession,
+ cit->second->controller, capture_session_id));
+ }
}
}
PostOnClosed(capture_session_id);
@@ -213,6 +223,11 @@ void VideoCaptureManager::OnStart(
media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
DCHECK(IsOnCaptureDeviceThread());
DCHECK(video_capture_receiver != NULL);
+ DVLOG(1) << "VideoCaptureManager::OnStart, (" << capture_params.width
+ << ", " << capture_params.height
+ << ", " << capture_params.frame_per_second
+ << ", " << capture_params.session_id
+ << ")";
media::VideoCaptureDevice* video_capture_device =
GetDeviceInternal(capture_params.session_id);
@@ -238,6 +253,7 @@ void VideoCaptureManager::OnStop(
const media::VideoCaptureSessionId capture_session_id,
base::Closure stopped_cb) {
DCHECK(IsOnCaptureDeviceThread());
+ DVLOG(1) << "VideoCaptureManager::OnStop, id " << capture_session_id;
VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
if (it != devices_.end()) {
@@ -318,9 +334,9 @@ void VideoCaptureManager::PostOnOpened(int capture_session_id) {
void VideoCaptureManager::PostOnClosed(int capture_session_id) {
DCHECK(IsOnCaptureDeviceThread());
BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnClosed, this,
- capture_session_id));
+ FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnClosed, this,
+ capture_session_id));
}
void VideoCaptureManager::PostOnDevicesEnumerated(