OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <stdio.h> | |
perkj_chrome
2011/10/21 14:54:00
needed?
wjia(left Chromium)
2011/10/21 23:54:16
Oops, this is leftover for debugging printf. Remov
| |
7 #include "base/bind.h" | 8 #include "base/bind.h" |
8 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
9 #include "content/browser/browser_thread.h" | 10 #include "content/browser/browser_thread.h" |
10 #include "content/browser/renderer_host/media/media_stream_manager.h" | 11 #include "content/browser/renderer_host/media/media_stream_manager.h" |
11 #include "content/browser/renderer_host/media/video_capture_manager.h" | 12 #include "content/browser/renderer_host/media/video_capture_manager.h" |
12 #include "media/base/yuv_convert.h" | 13 #include "media/base/yuv_convert.h" |
13 | 14 |
14 // The number of TransportDIBs VideoCaptureController allocate. | 15 // The number of DIBs VideoCaptureController allocate. |
perkj_chrome
2011/10/21 14:54:00
per host?
wjia(left Chromium)
2011/10/21 23:54:16
No. The controller is one per device and allocates
| |
15 static const size_t kNoOfDIBS = 3; | 16 static const size_t kNoOfDIBS = 3; |
16 | 17 |
18 struct VideoCaptureController::ControllerClient { | |
19 ControllerClient( | |
20 const VideoCaptureControllerID& id, | |
21 VideoCaptureControllerEventHandler* handler, | |
22 base::ProcessHandle render_process, | |
23 const media::VideoCaptureParams& params) | |
24 : controller_id(id), | |
25 event_handler(handler), | |
26 render_process_handle(render_process), | |
27 parameters(params), | |
28 report_ready_to_delete(false) { | |
29 } | |
30 | |
31 ~ControllerClient() {} | |
32 | |
33 // ID used for identifying this object. | |
34 VideoCaptureControllerID controller_id; | |
35 VideoCaptureControllerEventHandler* event_handler; | |
36 // Handle to the render process that will receive the DIBs. | |
37 base::ProcessHandle render_process_handle; | |
38 const media::VideoCaptureParams parameters; | |
39 // Buffers used by this client. | |
40 std::list<int> buffers; | |
41 bool report_ready_to_delete; | |
42 }; | |
43 | |
17 VideoCaptureController::VideoCaptureController( | 44 VideoCaptureController::VideoCaptureController( |
18 const VideoCaptureControllerID& id, | |
19 base::ProcessHandle render_process, | |
20 VideoCaptureControllerEventHandler* event_handler, | |
21 media_stream::VideoCaptureManager* video_capture_manager) | 45 media_stream::VideoCaptureManager* video_capture_manager) |
22 : render_handle_(render_process), | 46 : frame_info_available_(false), |
23 report_ready_to_delete_(false), | 47 video_capture_manager_(video_capture_manager), |
24 event_handler_(event_handler), | 48 device_in_use_(false), |
25 id_(id), | 49 state_(media::VideoCapture::kStopped) { |
26 video_capture_manager_(video_capture_manager) { | 50 memset(¤t_params_, 0, sizeof(current_params_)); |
27 memset(¶ms_, 0, sizeof(params_)); | |
28 } | 51 } |
29 | 52 |
30 VideoCaptureController::~VideoCaptureController() { | 53 VideoCaptureController::~VideoCaptureController() { |
31 // Delete all TransportDIBs. | 54 // Delete all DIBs. |
32 STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), | 55 STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), |
33 owned_dibs_.end()); | 56 owned_dibs_.end()); |
57 STLDeleteContainerPointers(controller_clients_.begin(), | |
58 controller_clients_.end()); | |
34 } | 59 } |
35 | 60 |
36 void VideoCaptureController::StartCapture( | 61 void VideoCaptureController::StartCapture( |
perkj_chrome
2011/10/21 14:54:00
Can you please document the different cases this f
wjia(left Chromium)
2011/10/21 23:54:16
Comments have been added in each condition.
| |
62 const VideoCaptureControllerID& id, | |
63 VideoCaptureControllerEventHandler* event_handler, | |
64 base::ProcessHandle render_process, | |
37 const media::VideoCaptureParams& params) { | 65 const media::VideoCaptureParams& params) { |
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
67 if (state_ == media::VideoCapture::kError) { | |
68 event_handler->OnError(id); | |
69 return; | |
70 } | |
39 | 71 |
40 params_ = params; | 72 if (FindClient(id, event_handler, controller_clients_) != |
73 controller_clients_.end() || | |
74 FindClient(id, event_handler, pending_clients_) != | |
75 pending_clients_.end()) | |
76 return; | |
perkj_chrome
2011/10/21 14:54:00
DCHECK? Is this a programming error?
wjia(left Chromium)
2011/10/21 23:54:16
I kind of allow this behaviors. Strictly speaking,
| |
77 | |
78 ControllerClient* client = new ControllerClient(id, event_handler, | |
79 render_process, params); | |
80 if (state_ == media::VideoCapture::kStarted) { | |
81 if (!frame_info_available_) { | |
82 pending_clients_.push_back(client); | |
83 return; | |
84 } | |
85 | |
86 if (params.width > frame_info_.width || | |
perkj_chrome
2011/10/21 14:54:00
You might want to compare with what was actually r
wjia(left Chromium)
2011/10/21 23:54:16
That would be a todo to add code to query the max
| |
87 params.height > frame_info_.height) { | |
88 video_capture_manager_->Stop(current_params_.session_id, base::Closure()); | |
89 frame_info_available_ = false; | |
90 state_ = media::VideoCapture::kStopping; | |
91 pending_clients_.push_back(client); | |
92 return; | |
93 } | |
94 | |
95 SendFrameInfoAndBuffers(client); | |
96 controller_clients_.push_back(client); | |
97 return; | |
98 } | |
99 | |
100 if (state_ == media::VideoCapture::kStopping) { | |
101 pending_clients_.push_back(client); | |
102 return; | |
103 } | |
104 | |
105 controller_clients_.push_back(client); | |
106 current_params_ = params; | |
41 // Order the manager to start the actual capture. | 107 // Order the manager to start the actual capture. |
42 video_capture_manager_->Start(params, this); | 108 video_capture_manager_->Start(params, this); |
109 state_ = media::VideoCapture::kStarted; | |
43 } | 110 } |
44 | 111 |
45 void VideoCaptureController::StopCapture(base::Closure stopped_cb) { | 112 void VideoCaptureController::StopCapture( |
perkj_chrome
2011/10/21 14:54:00
Can you please document what this function is doin
wjia(left Chromium)
2011/10/21 23:54:16
Done.
| |
113 const VideoCaptureControllerID& id, | |
114 VideoCaptureControllerEventHandler* event_handler, | |
115 bool force_buffer_return) { | |
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
47 | 117 |
48 video_capture_manager_->Stop(params_.session_id, | 118 ControllerClients::iterator cit; |
49 base::Bind(&VideoCaptureController::OnDeviceStopped, this, stopped_cb)); | 119 cit = FindClient(id, event_handler, pending_clients_); |
120 if (cit != pending_clients_.end()) { | |
121 (*cit)->event_handler->OnReadyToDelete((*cit)->controller_id); | |
122 pending_clients_.erase(cit); | |
123 return; | |
124 } | |
125 | |
126 cit = FindClient(id, event_handler, controller_clients_); | |
127 DCHECK(cit != controller_clients_.end()); | |
128 | |
129 if (force_buffer_return) { | |
130 for (std::list<int>::iterator bit = (*cit)->buffers.begin(); | |
131 bit != (*cit)->buffers.end(); ++bit) { | |
132 int buffer_id = *bit; | |
133 ClientSideDIBCount::iterator dit = client_side_dib_count_.find(buffer_id); | |
134 if (dit == client_side_dib_count_.end()) | |
135 continue; | |
136 | |
137 if (--dit->second > 0) | |
138 continue; | |
139 | |
140 // Now this |buffer_id| is not used by any client. | |
141 client_side_dib_count_.erase(buffer_id); | |
142 { | |
143 base::AutoLock lock(lock_); | |
144 free_dibs_.push_back(buffer_id); | |
145 } | |
146 } | |
147 (*cit)->buffers.clear(); | |
148 } else { | |
149 if ((*cit)->buffers.size() > 0) { | |
150 (*cit)->report_ready_to_delete = true; | |
151 return; | |
152 } | |
153 (*cit)->event_handler->OnReadyToDelete((*cit)->controller_id); | |
154 } | |
155 | |
156 controller_clients_.erase(cit); | |
157 | |
158 if (controller_clients_.size() == 0) { | |
159 video_capture_manager_->Stop(current_params_.session_id, base::Closure()); | |
160 frame_info_available_ = false; | |
161 state_ = media::VideoCapture::kStopping; | |
162 } | |
50 } | 163 } |
51 | 164 |
52 void VideoCaptureController::ReturnBuffer(int buffer_id) { | 165 void VideoCaptureController::ReturnBuffer( |
perkj_chrome
2011/10/21 14:54:00
Please document.
wjia(left Chromium)
2011/10/21 23:54:16
Done.
| |
166 const VideoCaptureControllerID& id, | |
167 VideoCaptureControllerEventHandler* event_handler, | |
168 int buffer_id) { | |
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
54 | 170 |
55 bool ready_to_delete; | 171 ControllerClients::iterator cit = FindClient(id, event_handler, |
172 controller_clients_); | |
173 ClientSideDIBCount::iterator dit = client_side_dib_count_.find(buffer_id); | |
174 if (cit == controller_clients_.end() || dit == client_side_dib_count_.end()) | |
175 return; | |
176 | |
177 (*cit)->buffers.remove(buffer_id); | |
178 if ((*cit)->report_ready_to_delete && (*cit)->buffers.size() == 0) { | |
179 (*cit)->event_handler->OnReadyToDelete((*cit)->controller_id); | |
180 controller_clients_.erase(cit); | |
181 } | |
182 if (--dit->second > 0) | |
183 return; | |
184 | |
185 // Now this |buffer_id| is not used by any client. | |
186 client_side_dib_count_.erase(buffer_id); | |
56 { | 187 { |
57 base::AutoLock lock(lock_); | 188 base::AutoLock lock(lock_); |
58 free_dibs_.push_back(buffer_id); | 189 free_dibs_.push_back(buffer_id); |
59 ready_to_delete = (free_dibs_.size() == owned_dibs_.size()) && | |
60 report_ready_to_delete_; | |
61 } | 190 } |
62 if (ready_to_delete) { | 191 |
63 event_handler_->OnReadyToDelete(id_); | 192 if (!ClientHasDIB() && state_ == media::VideoCapture::kStopping) { |
193 PostStopping(); | |
64 } | 194 } |
65 } | 195 } |
66 | 196 |
67 /////////////////////////////////////////////////////////////////////////////// | 197 /////////////////////////////////////////////////////////////////////////////// |
68 // Implements VideoCaptureDevice::EventHandler. | 198 // Implements VideoCaptureDevice::EventHandler. |
69 // OnIncomingCapturedFrame is called the thread running the capture device. | 199 // OnIncomingCapturedFrame is called the thread running the capture device. |
70 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. | 200 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. |
71 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, | 201 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, |
72 int length, | 202 int length, |
73 base::Time timestamp) { | 203 base::Time timestamp) { |
74 int buffer_id = 0; | 204 int buffer_id = 0; |
75 base::SharedMemory* dib = NULL; | 205 base::SharedMemory* dib = NULL; |
76 // Check if there is a TransportDIB to fill. | 206 // Check if there is a DIB to fill. |
77 bool buffer_exist = false; | 207 bool buffer_exist = false; |
78 { | 208 { |
79 base::AutoLock lock(lock_); | 209 base::AutoLock lock(lock_); |
80 if (!report_ready_to_delete_ && free_dibs_.size() > 0) { | 210 if (free_dibs_.size() > 0) { |
81 buffer_id = free_dibs_.front(); | 211 buffer_id = free_dibs_.front(); |
82 free_dibs_.pop_front(); | 212 free_dibs_.pop_front(); |
83 DIBMap::iterator it = owned_dibs_.find(buffer_id); | 213 DIBMap::iterator it = owned_dibs_.find(buffer_id); |
84 if (it != owned_dibs_.end()) { | 214 if (it != owned_dibs_.end()) { |
85 dib = it->second; | 215 dib = it->second; |
86 buffer_exist = true; | 216 buffer_exist = true; |
87 } | 217 } |
88 } | 218 } |
89 } | 219 } |
90 | 220 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; | 273 uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; |
144 media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width, | 274 media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width, |
145 frame_info_.height, frame_info_.width * 4, | 275 frame_info_.height, frame_info_.width * 4, |
146 frame_info_.width, frame_info_.width / 2); | 276 frame_info_.width, frame_info_.width / 2); |
147 break; | 277 break; |
148 } | 278 } |
149 default: | 279 default: |
150 NOTREACHED(); | 280 NOTREACHED(); |
151 } | 281 } |
152 | 282 |
153 event_handler_->OnBufferReady(id_, buffer_id, timestamp); | 283 BrowserThread::PostTask(BrowserThread::IO, |
284 FROM_HERE, | |
285 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, | |
286 this, buffer_id, timestamp)); | |
154 } | 287 } |
155 | 288 |
156 void VideoCaptureController::OnError() { | 289 void VideoCaptureController::OnError() { |
157 event_handler_->OnError(id_); | 290 video_capture_manager_->Error(current_params_.session_id); |
158 video_capture_manager_->Error(params_.session_id); | 291 BrowserThread::PostTask(BrowserThread::IO, |
292 FROM_HERE, | |
293 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); | |
159 } | 294 } |
160 | 295 |
161 void VideoCaptureController::OnFrameInfo( | 296 void VideoCaptureController::OnFrameInfo( |
162 const media::VideoCaptureDevice::Capability& info) { | 297 const media::VideoCaptureDevice::Capability& info) { |
298 BrowserThread::PostTask(BrowserThread::IO, | |
299 FROM_HERE, | |
300 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, | |
301 this, info)); | |
302 } | |
303 | |
304 void VideoCaptureController::OnDeviceState(bool in_use) { | |
305 BrowserThread::PostTask(BrowserThread::IO, | |
306 FROM_HERE, | |
307 base::Bind(&VideoCaptureController::DoDeviceStateOnIOThread, this, | |
308 in_use)); | |
309 } | |
310 | |
311 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( | |
312 int buffer_id, base::Time timestamp) { | |
perkj_chrome
2011/10/21 14:54:00
You say that this is of type int here but in OnBuf
wjia(left Chromium)
2011/10/21 23:54:16
I guess you are confused with OnBufferReady and On
| |
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
314 | |
315 if (state_ != media::VideoCapture::kStarted) { | |
316 base::AutoLock lock(lock_); | |
317 free_dibs_.push_back(buffer_id); | |
318 return; | |
319 } | |
320 | |
321 int count = 0; | |
322 for (ControllerClients::iterator cit = controller_clients_.begin(); | |
323 cit != controller_clients_.end(); cit++) { | |
324 if ((*cit)->report_ready_to_delete) | |
325 continue; | |
326 | |
327 (*cit)->event_handler->OnBufferReady((*cit)->controller_id, | |
328 buffer_id, timestamp); | |
329 (*cit)->buffers.push_back(buffer_id); | |
330 count++; | |
331 } | |
332 if (count > 0) { | |
333 client_side_dib_count_[buffer_id] = count; | |
334 } else { | |
335 base::AutoLock lock(lock_); | |
336 free_dibs_.push_back(buffer_id); | |
337 } | |
338 } | |
339 | |
340 void VideoCaptureController::DoErrorOnIOThread() { | |
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
342 state_ = media::VideoCapture::kError; | |
343 ControllerClients::iterator cit; | |
344 for (cit = controller_clients_.begin(); | |
345 cit != controller_clients_.end(); cit++) { | |
346 (*cit)->event_handler->OnError((*cit)->controller_id); | |
347 } | |
348 for (cit = pending_clients_.begin(); | |
349 cit != pending_clients_.end(); cit++) { | |
350 (*cit)->event_handler->OnError((*cit)->controller_id); | |
351 } | |
352 } | |
353 | |
354 void VideoCaptureController::DoDeviceStateOnIOThread(bool device_in_use) { | |
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
356 device_in_use_ = device_in_use; | |
357 video_capture_manager_->DeviceStatusFromController(this, device_in_use); | |
358 if (!device_in_use && state_ == media::VideoCapture::kStopping) { | |
359 PostStopping(); | |
360 } | |
361 } | |
362 | |
363 void VideoCaptureController::DoFrameInfoOnIOThread( | |
364 const media::VideoCaptureDevice::Capability info) { | |
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
163 DCHECK(owned_dibs_.empty()); | 366 DCHECK(owned_dibs_.empty()); |
367 | |
368 // Check if pending clients request higher resolution. | |
369 current_params_.width = info.width; | |
370 current_params_.height = info.height; | |
371 current_params_.frame_per_second = info.frame_rate; | |
372 ControllerClients::iterator cit; | |
373 for (cit = pending_clients_.begin(); | |
374 cit != pending_clients_.end(); ) { | |
375 if (current_params_.width < (*cit)->parameters.width) | |
376 current_params_.width = (*cit)->parameters.width; | |
377 if (current_params_.height < (*cit)->parameters.height) | |
378 current_params_.height = (*cit)->parameters.height; | |
379 controller_clients_.push_back((*cit)); | |
380 pending_clients_.erase(cit++); | |
381 } | |
382 if (current_params_.width > info.width || | |
383 current_params_.height > info.height) { | |
384 video_capture_manager_->Stop(current_params_.session_id, base::Closure()); | |
385 frame_info_available_ = false; | |
386 state_ = media::VideoCapture::kStopping; | |
387 return; | |
388 } | |
389 | |
164 bool frames_created = true; | 390 bool frames_created = true; |
165 const size_t needed_size = (info.width * info.height * 3) / 2; | 391 const size_t needed_size = (info.width * info.height * 3) / 2; |
392 base::AutoLock lock(lock_); | |
166 for (size_t i = 1; i <= kNoOfDIBS; ++i) { | 393 for (size_t i = 1; i <= kNoOfDIBS; ++i) { |
167 base::SharedMemory* shared_memory = new base::SharedMemory(); | 394 base::SharedMemory* shared_memory = new base::SharedMemory(); |
168 if (!shared_memory->CreateAndMapAnonymous(needed_size)) { | 395 if (!shared_memory->CreateAndMapAnonymous(needed_size)) { |
169 frames_created = false; | 396 frames_created = false; |
170 break; | 397 break; |
171 } | 398 } |
172 base::SharedMemoryHandle remote_handle; | |
173 shared_memory->ShareToProcess(render_handle_, &remote_handle); | |
174 | |
175 base::AutoLock lock(lock_); | |
176 owned_dibs_.insert(std::make_pair(i, shared_memory)); | 399 owned_dibs_.insert(std::make_pair(i, shared_memory)); |
177 free_dibs_.push_back(i); | 400 free_dibs_.push_back(i); |
178 event_handler_->OnBufferCreated(id_, remote_handle, | 401 } |
179 static_cast<int>(needed_size), | 402 // Check whether all DIBs were created successfully. |
180 static_cast<int>(i)); | 403 if (!frames_created) { |
404 state_ = media::VideoCapture::kError; | |
405 for (ControllerClients::iterator it = controller_clients_.begin(); | |
406 it != controller_clients_.end(); it++) { | |
407 (*it)->event_handler->OnError((*it)->controller_id); | |
408 } | |
409 return; | |
181 } | 410 } |
182 frame_info_= info; | 411 frame_info_= info; |
183 | 412 frame_info_available_ = true; |
184 // Check that all DIBs where created successfully. | 413 |
185 if (!frames_created) { | 414 for (cit = controller_clients_.begin(); |
perkj_chrome
2011/10/21 14:54:00
Use SendFrameInfoAndBuffers - avoid duplicate code
wjia(left Chromium)
2011/10/21 23:54:16
Done.
| |
186 event_handler_->OnError(id_); | 415 cit != controller_clients_.end(); cit++) { |
187 } | 416 (*cit)->event_handler->OnFrameInfo((*cit)->controller_id, |
188 event_handler_->OnFrameInfo(id_, info.width, info.height, info.frame_rate); | 417 info.width, info.height, |
189 } | 418 info.frame_rate); |
190 | 419 for (DIBMap::iterator dit = owned_dibs_.begin(); |
191 /////////////////////////////////////////////////////////////////////////////// | 420 dit != owned_dibs_.end(); dit++) { |
192 // Called by VideoCaptureManager when a device have been stopped. | 421 int index = dit->first; |
193 // This will report to the event handler that this object is ready to be deleted | 422 base::SharedMemory* shared_memory = dit->second; |
194 // if all DIBS have been returned. | 423 base::SharedMemoryHandle remote_handle; |
195 void VideoCaptureController::OnDeviceStopped(base::Closure stopped_cb) { | 424 shared_memory->ShareToProcess((*cit)->render_process_handle, |
196 bool ready_to_delete_now; | 425 &remote_handle); |
197 | 426 (*cit)->event_handler->OnBufferCreated((*cit)->controller_id, |
198 { | 427 remote_handle, |
199 base::AutoLock lock(lock_); | 428 static_cast<int>(needed_size), |
200 // Set flag to indicate we need to report when all DIBs have been returned. | 429 index); |
201 report_ready_to_delete_ = true; | 430 } |
202 ready_to_delete_now = (free_dibs_.size() == owned_dibs_.size()); | 431 } |
203 } | 432 } |
204 | 433 |
205 if (ready_to_delete_now) { | 434 void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) { |
206 event_handler_->OnReadyToDelete(id_); | 435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
207 } | 436 DCHECK(frame_info_available_); |
208 | 437 const size_t needed_size = (frame_info_.width * frame_info_.height * 3) / 2; |
perkj_chrome
2011/10/21 14:54:00
not used
wjia(left Chromium)
2011/10/21 23:54:16
It's used in OnBufferCreated.
| |
209 if (!stopped_cb.is_null()) | 438 client->event_handler->OnFrameInfo(client->controller_id, |
210 stopped_cb.Run(); | 439 frame_info_.width, frame_info_.height, |
211 } | 440 frame_info_.frame_rate); |
441 base::AutoLock lock(lock_); | |
442 for (DIBMap::iterator dit = owned_dibs_.begin(); | |
443 dit != owned_dibs_.end(); dit++) { | |
444 base::SharedMemory* shared_memory = dit->second; | |
445 int index = dit->first; | |
446 base::SharedMemoryHandle remote_handle; | |
447 shared_memory->ShareToProcess(client->render_process_handle, | |
448 &remote_handle); | |
449 client->event_handler->OnBufferCreated(client->controller_id, | |
450 remote_handle, | |
451 static_cast<int>(needed_size), | |
452 index); | |
453 } | |
454 } | |
455 | |
456 void VideoCaptureController::PostStopping() { | |
457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
458 DCHECK_EQ(state_, media::VideoCapture::kStopping); | |
459 | |
460 if (ClientHasDIB() || device_in_use_) | |
461 return; | |
462 | |
463 // It's safe to free all DIB's on IO thread since device won't send | |
464 // buffer over. | |
465 free_dibs_.clear(); | |
466 STLDeleteValues(&owned_dibs_); | |
467 | |
468 if (controller_clients_.size() + pending_clients_.size() == 0) { | |
469 state_ = media::VideoCapture::kStopped; | |
470 return; | |
471 } | |
472 | |
473 // Restart the device. | |
474 current_params_.width = 0; | |
475 current_params_.height = 0; | |
476 ControllerClients::iterator cit; | |
477 for (cit = controller_clients_.begin(); | |
478 cit != controller_clients_.end(); cit++) { | |
479 if (current_params_.width < (*cit)->parameters.width) | |
480 current_params_.width = (*cit)->parameters.width; | |
481 if (current_params_.height < (*cit)->parameters.height) | |
482 current_params_.height = (*cit)->parameters.height; | |
483 } | |
484 for (cit = pending_clients_.begin(); | |
485 cit != pending_clients_.end(); ) { | |
486 if (current_params_.width < (*cit)->parameters.width) | |
487 current_params_.width = (*cit)->parameters.width; | |
488 if (current_params_.height < (*cit)->parameters.height) | |
489 current_params_.height = (*cit)->parameters.height; | |
490 controller_clients_.push_back((*cit)); | |
491 pending_clients_.erase(cit++); | |
492 } | |
493 // Request the manager to start the actual capture. | |
494 video_capture_manager_->Start(current_params_, this); | |
495 state_ = media::VideoCapture::kStarted; | |
496 } | |
497 | |
498 bool VideoCaptureController::ClientHasDIB() { | |
499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
500 for (ClientSideDIBCount::iterator dit = client_side_dib_count_.begin(); | |
501 dit != client_side_dib_count_.end(); dit++) { | |
502 if (dit->second > 0) | |
503 return true; | |
504 } | |
505 return false; | |
506 } | |
507 | |
508 VideoCaptureController::ControllerClients::iterator | |
509 VideoCaptureController::FindClient( | |
510 const VideoCaptureControllerID& id, | |
511 VideoCaptureControllerEventHandler* handler, | |
512 ControllerClients& clients) { | |
513 for (ControllerClients::iterator cit = clients.begin(); | |
514 cit != clients.end(); cit++) { | |
515 if ((*cit)->controller_id == id && (*cit)->event_handler == handler) { | |
516 return cit; | |
517 } | |
518 } | |
519 return clients.end(); | |
520 } | |
521 | |
OLD | NEW |