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

Side by Side Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 10537057: refactor VideoCaptureHost and VideoCaptureController. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/media/video_capture_controller.h" 5 #include "content/browser/renderer_host/media/video_capture_controller.h"
6 6
7 #include <set>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h" 11 #include "base/stl_util.h"
10 #include "content/browser/renderer_host/media/media_stream_manager.h" 12 #include "content/browser/renderer_host/media/media_stream_manager.h"
11 #include "content/browser/renderer_host/media/video_capture_manager.h" 13 #include "content/browser/renderer_host/media/video_capture_manager.h"
12 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
13 #include "media/base/yuv_convert.h" 15 #include "media/base/yuv_convert.h"
14 16
15 using content::BrowserThread; 17 using content::BrowserThread;
16 18
17 // The number of DIBs VideoCaptureController allocate. 19 // The number of DIBs VideoCaptureController allocate.
18 static const size_t kNoOfDIBS = 3; 20 static const size_t kNoOfDIBS = 3;
19 21
20 struct VideoCaptureController::ControllerClient { 22 struct VideoCaptureController::ControllerClient {
21 ControllerClient( 23 ControllerClient(
22 const VideoCaptureControllerID& id, 24 const VideoCaptureControllerID& id,
23 VideoCaptureControllerEventHandler* handler, 25 VideoCaptureControllerEventHandler* handler,
24 base::ProcessHandle render_process, 26 base::ProcessHandle render_process,
25 const media::VideoCaptureParams& params) 27 const media::VideoCaptureParams& params)
26 : controller_id(id), 28 : controller_id(id),
27 event_handler(handler), 29 event_handler(handler),
28 render_process_handle(render_process), 30 render_process_handle(render_process),
29 parameters(params), 31 parameters(params),
30 session_closed(false), 32 session_closed(false) {
31 report_ready_to_delete(false) {
32 } 33 }
33 34
34 ~ControllerClient() {} 35 ~ControllerClient() {}
35 36
36 // ID used for identifying this object. 37 // ID used for identifying this object.
37 VideoCaptureControllerID controller_id; 38 VideoCaptureControllerID controller_id;
38 VideoCaptureControllerEventHandler* event_handler; 39 VideoCaptureControllerEventHandler* event_handler;
39 40
40 // Handle to the render process that will receive the DIBs. 41 // Handle to the render process that will receive the DIBs.
41 base::ProcessHandle render_process_handle; 42 base::ProcessHandle render_process_handle;
42 media::VideoCaptureParams parameters; 43 media::VideoCaptureParams parameters;
43 44
44 // Buffers used by this client. 45 // Buffers used by this client.
45 std::list<int> buffers; 46 std::set<int> buffers;
46 47
47 // State of capture session, controlled by VideoCaptureManager directly. 48 // State of capture session, controlled by VideoCaptureManager directly.
48 bool session_closed; 49 bool session_closed;
49
50 // Record client's status when it has called StopCapture, but haven't
51 // returned all buffers.
52 bool report_ready_to_delete;
53 }; 50 };
54 51
55 struct VideoCaptureController::SharedDIB { 52 struct VideoCaptureController::SharedDIB {
56 SharedDIB(base::SharedMemory* ptr) 53 SharedDIB(base::SharedMemory* ptr)
57 : shared_memory(ptr), 54 : shared_memory(ptr),
58 references(0) { 55 references(0) {
59 } 56 }
60 57
61 ~SharedDIB() {} 58 ~SharedDIB() {}
62 59
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 controller_clients_.push_back(client); 135 controller_clients_.push_back(client);
139 current_params_ = params; 136 current_params_ = params;
140 // Order the manager to start the actual capture. 137 // Order the manager to start the actual capture.
141 video_capture_manager_->Start(params, this); 138 video_capture_manager_->Start(params, this);
142 state_ = video_capture::kStarted; 139 state_ = video_capture::kStarted;
143 device_in_use_ = true; 140 device_in_use_ = true;
144 } 141 }
145 142
146 void VideoCaptureController::StopCapture( 143 void VideoCaptureController::StopCapture(
147 const VideoCaptureControllerID& id, 144 const VideoCaptureControllerID& id,
148 VideoCaptureControllerEventHandler* event_handler, 145 VideoCaptureControllerEventHandler* event_handler) {
149 bool force_buffer_return) {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
151 DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id; 147 DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id;
152 148
153 ControllerClient* client = FindClient(id, event_handler, pending_clients_); 149 ControllerClient* client = FindClient(id, event_handler, pending_clients_);
154 // If the client is still in pending queue, just remove it. 150 // If the client is still in pending queue, just remove it.
155 if (client) { 151 if (client) {
156 client->event_handler->OnReadyToDelete(client->controller_id);
157 pending_clients_.remove(client); 152 pending_clients_.remove(client);
158 return; 153 return;
159 } 154 }
160 155
161 client = FindClient(id, event_handler, controller_clients_); 156 client = FindClient(id, event_handler, controller_clients_);
162 DCHECK(client) << "Client should have called StartCapture()"; 157 if (!client)
158 return;
163 159
164 if (force_buffer_return) { 160 // Take back all buffers held by the |client|.
165 // The client requests to return buffers which means it can't return 161 for (std::set<int>::iterator buffer_it = client->buffers.begin();
166 // buffers normally. After buffers are returned, client is free to 162 buffer_it != client->buffers.end(); ++buffer_it) {
167 // delete itself. No need to call OnReadyToDelete. 163 int buffer_id = *buffer_it;
164 DIBMap::iterator dib_it = owned_dibs_.find(buffer_id);
165 if (dib_it == owned_dibs_.end())
166 continue;
168 167
169 // Return all buffers held by the clients. 168 {
170 for (std::list<int>::iterator buffer_it = client->buffers.begin(); 169 base::AutoLock lock(lock_);
171 buffer_it != client->buffers.end(); ++buffer_it) { 170 DCHECK_GT(dib_it->second->references, 0)
172 int buffer_id = *buffer_it; 171 << "The buffer is not used by renderer.";
173 DIBMap::iterator dib_it = owned_dibs_.find(buffer_id); 172 dib_it->second->references -= 1;
174 if (dib_it == owned_dibs_.end())
175 continue;
176
177 {
178 base::AutoLock lock(lock_);
179 DCHECK_GT(dib_it->second->references, 0)
180 << "The buffer is not used by renderer.";
181 dib_it->second->references -= 1;
182 }
183 } 173 }
184 client->buffers.clear();
185 } else {
186 // Normal way to stop capture.
187 if (!client->buffers.empty()) {
188 // There are still some buffers held by the client.
189 client->report_ready_to_delete = true;
190 return;
191 }
192 // No buffer is held by the client. Ready to delete.
193 client->event_handler->OnReadyToDelete(client->controller_id);
194 } 174 }
175 client->buffers.clear();
195 176
196 int session_id = client->parameters.session_id; 177 int session_id = client->parameters.session_id;
197 delete client; 178 delete client;
198 controller_clients_.remove(client); 179 controller_clients_.remove(client);
199 180
200 // No more clients. Stop device. 181 // No more clients. Stop device.
201 if (controller_clients_.empty()) { 182 if (controller_clients_.empty() && state_ == video_capture::kStarted) {
202 video_capture_manager_->Stop(session_id, 183 video_capture_manager_->Stop(session_id,
203 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); 184 base::Bind(&VideoCaptureController::OnDeviceStopped, this));
204 frame_info_available_ = false; 185 frame_info_available_ = false;
205 state_ = video_capture::kStopping; 186 state_ = video_capture::kStopping;
206 } 187 }
207 } 188 }
208 189
209 void VideoCaptureController::StopSession( 190 void VideoCaptureController::StopSession(
210 int session_id) { 191 int session_id) {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 13 matching lines...) Expand all
225 const VideoCaptureControllerID& id, 206 const VideoCaptureControllerID& id,
226 VideoCaptureControllerEventHandler* event_handler, 207 VideoCaptureControllerEventHandler* event_handler,
227 int buffer_id) { 208 int buffer_id) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229 210
230 ControllerClient* client = FindClient(id, event_handler, 211 ControllerClient* client = FindClient(id, event_handler,
231 controller_clients_); 212 controller_clients_);
232 DIBMap::iterator dib_it = owned_dibs_.find(buffer_id); 213 DIBMap::iterator dib_it = owned_dibs_.find(buffer_id);
233 // If this buffer is not held by this client, or this client doesn't exist 214 // If this buffer is not held by this client, or this client doesn't exist
234 // in controller, do nothing. 215 // in controller, do nothing.
235 if (!client || dib_it == owned_dibs_.end()) 216 if (!client ||
217 client->buffers.find(buffer_id) == client->buffers.end() ||
218 dib_it == owned_dibs_.end())
236 return; 219 return;
237 220
238 client->buffers.remove(buffer_id); 221 client->buffers.erase(buffer_id);
239 // If this client has called StopCapture and doesn't hold any buffer after
240 // after this return, ready to delete this client.
241 if (client->report_ready_to_delete && client->buffers.empty()) {
242 client->event_handler->OnReadyToDelete(client->controller_id);
243 delete client;
244 controller_clients_.remove(client);
245
246 if (controller_clients_.empty()) {
247 // No more clients. Stop device.
248 video_capture_manager_->Stop(current_params_.session_id,
249 base::Bind(&VideoCaptureController::OnDeviceStopped, this));
250 frame_info_available_ = false;
251 state_ = video_capture::kStopping;
252 }
253 }
254 { 222 {
255 base::AutoLock lock(lock_); 223 base::AutoLock lock(lock_);
256 DCHECK_GT(dib_it->second->references, 0) 224 DCHECK_GT(dib_it->second->references, 0)
257 << "The buffer is not used by renderer."; 225 << "The buffer is not used by renderer.";
258 dib_it->second->references -= 1; 226 dib_it->second->references -= 1;
259 if (dib_it->second->references > 0) 227 if (dib_it->second->references > 0)
260 return; 228 return;
261 } 229 }
262 230
263 // When all buffers have been returned by clients and device has been 231 // When all buffers have been returned by clients and device has been
264 // called to stop, check if restart is needed. This could happen when 232 // called to stop, check if restart is needed. This could happen when
265 // some clients call StopCapture before returning all buffers. 233 // capture needs to be restarted due to resolution change.
266 if (!ClientHasDIB() && state_ == video_capture::kStopping) { 234 if (!ClientHasDIB() && state_ == video_capture::kStopping) {
267 PostStopping(); 235 PostStopping();
268 } 236 }
269 } 237 }
270 238
271 /////////////////////////////////////////////////////////////////////////////// 239 ///////////////////////////////////////////////////////////////////////////////
272 // Implements VideoCaptureDevice::EventHandler. 240 // Implements VideoCaptureDevice::EventHandler.
273 // OnIncomingCapturedFrame is called the thread running the capture device. 241 // OnIncomingCapturedFrame is called the thread running the capture device.
274 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. 242 // I.e.- DirectShow thread on windows and v4l2_thread on Linux.
275 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, 243 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 365 }
398 366
399 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( 367 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
400 int buffer_id, base::Time timestamp) { 368 int buffer_id, base::Time timestamp) {
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
402 370
403 int count = 0; 371 int count = 0;
404 if (state_ == video_capture::kStarted) { 372 if (state_ == video_capture::kStarted) {
405 for (ControllerClients::iterator client_it = controller_clients_.begin(); 373 for (ControllerClients::iterator client_it = controller_clients_.begin();
406 client_it != controller_clients_.end(); client_it++) { 374 client_it != controller_clients_.end(); client_it++) {
407 if ((*client_it)->report_ready_to_delete || 375 if ((*client_it)->session_closed)
408 (*client_it)->session_closed)
409 continue; 376 continue;
410 377
411 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, 378 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id,
412 buffer_id, timestamp); 379 buffer_id, timestamp);
413 (*client_it)->buffers.push_back(buffer_id); 380 (*client_it)->buffers.insert(buffer_id);
414 count++; 381 count++;
415 } 382 }
416 } 383 }
417 384
418 base::AutoLock lock(lock_); 385 base::AutoLock lock(lock_);
419 if (owned_dibs_.find(buffer_id) != owned_dibs_.end()) { 386 if (owned_dibs_.find(buffer_id) != owned_dibs_.end()) {
420 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); 387 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1);
421 owned_dibs_[buffer_id]->references = count; 388 owned_dibs_[buffer_id]->references = count;
422 } 389 }
423 } 390 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 bool VideoCaptureController::ClientHasDIB() { 549 bool VideoCaptureController::ClientHasDIB() {
583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
584 base::AutoLock lock(lock_); 551 base::AutoLock lock(lock_);
585 for (DIBMap::iterator dib_it = owned_dibs_.begin(); 552 for (DIBMap::iterator dib_it = owned_dibs_.begin();
586 dib_it != owned_dibs_.end(); dib_it++) { 553 dib_it != owned_dibs_.end(); dib_it++) {
587 if (dib_it->second->references > 0) 554 if (dib_it->second->references > 0)
588 return true; 555 return true;
589 } 556 }
590 return false; 557 return false;
591 } 558 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698