OLD | NEW |
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 "media/video/capture/win/video_capture_device_win.h" | 5 #include "media/video/capture/win/video_capture_device_win.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 | 9 |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 172 |
173 namespace media { | 173 namespace media { |
174 | 174 |
175 // Name of a fake DirectShow filter that exist on computers with | 175 // Name of a fake DirectShow filter that exist on computers with |
176 // GTalk installed. | 176 // GTalk installed. |
177 static const char kGoogleCameraAdapter[] = "google camera adapter"; | 177 static const char kGoogleCameraAdapter[] = "google camera adapter"; |
178 | 178 |
179 // Gets the names of all video capture devices connected to this computer. | 179 // Gets the names of all video capture devices connected to this computer. |
180 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { | 180 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { |
181 DCHECK(device_names); | 181 DCHECK(device_names); |
| 182 DCHECK(CalledOnValidThread()); |
182 | 183 |
183 base::win::ScopedCOMInitializer coinit; | |
184 ScopedComPtr<ICreateDevEnum> dev_enum; | 184 ScopedComPtr<ICreateDevEnum> dev_enum; |
185 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, | 185 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, |
186 CLSCTX_INPROC); | 186 CLSCTX_INPROC); |
187 if (FAILED(hr)) | 187 if (FAILED(hr)) |
188 return; | 188 return; |
189 | 189 |
190 ScopedComPtr<IEnumMoniker> enum_moniker; | 190 ScopedComPtr<IEnumMoniker> enum_moniker; |
191 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, | 191 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, |
192 enum_moniker.Receive(), 0); | 192 enum_moniker.Receive(), 0); |
193 // CreateClassEnumerator returns S_FALSE on some Windows OS | 193 // CreateClassEnumerator returns S_FALSE on some Windows OS |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 return self; | 248 return self; |
249 | 249 |
250 delete self; | 250 delete self; |
251 return NULL; | 251 return NULL; |
252 } | 252 } |
253 | 253 |
254 VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name) | 254 VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name) |
255 : device_name_(device_name), | 255 : device_name_(device_name), |
256 state_(kIdle), | 256 state_(kIdle), |
257 observer_(NULL) { | 257 observer_(NULL) { |
| 258 DetachFromThread(); |
258 } | 259 } |
259 | 260 |
260 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { | 261 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { |
| 262 DCHECK(CalledOnValidThread()); |
261 if (media_control_) | 263 if (media_control_) |
262 media_control_->Stop(); | 264 media_control_->Stop(); |
263 | 265 |
264 if (graph_builder_) { | 266 if (graph_builder_) { |
265 if (sink_filter_) { | 267 if (sink_filter_) { |
266 graph_builder_->RemoveFilter(sink_filter_); | 268 graph_builder_->RemoveFilter(sink_filter_); |
267 sink_filter_ = NULL; | 269 sink_filter_ = NULL; |
268 } | 270 } |
269 | 271 |
270 if (capture_filter_) | 272 if (capture_filter_) |
271 graph_builder_->RemoveFilter(capture_filter_); | 273 graph_builder_->RemoveFilter(capture_filter_); |
272 | 274 |
273 if (mjpg_filter_) | 275 if (mjpg_filter_) |
274 graph_builder_->RemoveFilter(mjpg_filter_); | 276 graph_builder_->RemoveFilter(mjpg_filter_); |
275 } | 277 } |
276 } | 278 } |
277 | 279 |
278 bool VideoCaptureDeviceWin::Init() { | 280 bool VideoCaptureDeviceWin::Init() { |
| 281 DCHECK(CalledOnValidThread()); |
279 HRESULT hr = GetDeviceFilter(device_name_, capture_filter_.Receive()); | 282 HRESULT hr = GetDeviceFilter(device_name_, capture_filter_.Receive()); |
280 if (!capture_filter_) { | 283 if (!capture_filter_) { |
281 DVLOG(2) << "Failed to create capture filter."; | 284 DVLOG(2) << "Failed to create capture filter."; |
282 return false; | 285 return false; |
283 } | 286 } |
284 | 287 |
285 hr = GetPin(capture_filter_, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, | 288 hr = GetPin(capture_filter_, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, |
286 output_capture_pin_.Receive()); | 289 output_capture_pin_.Receive()); |
287 if (!output_capture_pin_) { | 290 if (!output_capture_pin_) { |
288 DVLOG(2) << "Failed to get capture output pin"; | 291 DVLOG(2) << "Failed to get capture output pin"; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 } | 327 } |
325 | 328 |
326 return CreateCapabilityMap(); | 329 return CreateCapabilityMap(); |
327 } | 330 } |
328 | 331 |
329 void VideoCaptureDeviceWin::Allocate( | 332 void VideoCaptureDeviceWin::Allocate( |
330 int width, | 333 int width, |
331 int height, | 334 int height, |
332 int frame_rate, | 335 int frame_rate, |
333 VideoCaptureDevice::EventHandler* observer) { | 336 VideoCaptureDevice::EventHandler* observer) { |
| 337 DCHECK(CalledOnValidThread()); |
334 if (state_ != kIdle) | 338 if (state_ != kIdle) |
335 return; | 339 return; |
336 | 340 |
337 observer_ = observer; | 341 observer_ = observer; |
338 // Get the camera capability that best match the requested resolution. | 342 // Get the camera capability that best match the requested resolution. |
339 const int capability_index = GetBestMatchedCapability(width, height, | 343 const int capability_index = GetBestMatchedCapability(width, height, |
340 frame_rate); | 344 frame_rate); |
341 VideoCaptureCapability capability = capabilities_[capability_index]; | 345 VideoCaptureCapability capability = capabilities_[capability_index]; |
342 | 346 |
343 // Reduce the frame rate if the requested frame rate is lower | 347 // Reduce the frame rate if the requested frame rate is lower |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 // Get the capability back from the sink filter after the filter have been | 424 // Get the capability back from the sink filter after the filter have been |
421 // connected. | 425 // connected. |
422 const VideoCaptureCapability& used_capability | 426 const VideoCaptureCapability& used_capability |
423 = sink_filter_->ResultingCapability(); | 427 = sink_filter_->ResultingCapability(); |
424 observer_->OnFrameInfo(used_capability); | 428 observer_->OnFrameInfo(used_capability); |
425 | 429 |
426 state_ = kAllocated; | 430 state_ = kAllocated; |
427 } | 431 } |
428 | 432 |
429 void VideoCaptureDeviceWin::Start() { | 433 void VideoCaptureDeviceWin::Start() { |
| 434 DCHECK(CalledOnValidThread()); |
430 if (state_ != kAllocated) | 435 if (state_ != kAllocated) |
431 return; | 436 return; |
432 | 437 |
433 HRESULT hr = media_control_->Run(); | 438 HRESULT hr = media_control_->Run(); |
434 if (FAILED(hr)) { | 439 if (FAILED(hr)) { |
435 SetErrorState("Failed to start the Capture device."); | 440 SetErrorState("Failed to start the Capture device."); |
436 return; | 441 return; |
437 } | 442 } |
438 | 443 |
439 state_ = kCapturing; | 444 state_ = kCapturing; |
440 } | 445 } |
441 | 446 |
442 void VideoCaptureDeviceWin::Stop() { | 447 void VideoCaptureDeviceWin::Stop() { |
| 448 DCHECK(CalledOnValidThread()); |
443 if (state_ != kCapturing) | 449 if (state_ != kCapturing) |
444 return; | 450 return; |
445 | 451 |
446 HRESULT hr = media_control_->Stop(); | 452 HRESULT hr = media_control_->Stop(); |
447 if (FAILED(hr)) { | 453 if (FAILED(hr)) { |
448 SetErrorState("Failed to stop the capture graph."); | 454 SetErrorState("Failed to stop the capture graph."); |
449 return; | 455 return; |
450 } | 456 } |
451 | 457 |
452 state_ = kAllocated; | 458 state_ = kAllocated; |
453 } | 459 } |
454 | 460 |
455 void VideoCaptureDeviceWin::DeAllocate() { | 461 void VideoCaptureDeviceWin::DeAllocate() { |
| 462 DCHECK(CalledOnValidThread()); |
456 if (state_ == kIdle) | 463 if (state_ == kIdle) |
457 return; | 464 return; |
458 | 465 |
459 HRESULT hr = media_control_->Stop(); | 466 HRESULT hr = media_control_->Stop(); |
460 graph_builder_->Disconnect(output_capture_pin_); | 467 graph_builder_->Disconnect(output_capture_pin_); |
461 graph_builder_->Disconnect(input_sink_pin_); | 468 graph_builder_->Disconnect(input_sink_pin_); |
462 | 469 |
463 // If the _mjpg filter exist disconnect it even if it has not been used. | 470 // If the _mjpg filter exist disconnect it even if it has not been used. |
464 if (mjpg_filter_) { | 471 if (mjpg_filter_) { |
465 graph_builder_->Disconnect(input_mjpg_pin_); | 472 graph_builder_->Disconnect(input_mjpg_pin_); |
466 graph_builder_->Disconnect(output_mjpg_pin_); | 473 graph_builder_->Disconnect(output_mjpg_pin_); |
467 } | 474 } |
468 | 475 |
469 if (FAILED(hr)) { | 476 if (FAILED(hr)) { |
470 SetErrorState("Failed to Stop the Capture device"); | 477 SetErrorState("Failed to Stop the Capture device"); |
471 return; | 478 return; |
472 } | 479 } |
473 | 480 |
474 state_ = kIdle; | 481 state_ = kIdle; |
475 } | 482 } |
476 | 483 |
477 const VideoCaptureDevice::Name& VideoCaptureDeviceWin::device_name() { | 484 const VideoCaptureDevice::Name& VideoCaptureDeviceWin::device_name() { |
| 485 DCHECK(CalledOnValidThread()); |
478 return device_name_; | 486 return device_name_; |
479 } | 487 } |
480 | 488 |
481 // Implements SinkFilterObserver::SinkFilterObserver. | 489 // Implements SinkFilterObserver::SinkFilterObserver. |
482 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, | 490 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, |
483 int length) { | 491 int length) { |
484 observer_->OnIncomingCapturedFrame(buffer, length, base::Time::Now()); | 492 observer_->OnIncomingCapturedFrame(buffer, length, base::Time::Now()); |
485 } | 493 } |
486 | 494 |
487 bool VideoCaptureDeviceWin::CreateCapabilityMap() { | 495 bool VideoCaptureDeviceWin::CreateCapabilityMap() { |
| 496 DCHECK(CalledOnValidThread()); |
488 ScopedComPtr<IAMStreamConfig> stream_config; | 497 ScopedComPtr<IAMStreamConfig> stream_config; |
489 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); | 498 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); |
490 if (FAILED(hr)) { | 499 if (FAILED(hr)) { |
491 DVLOG(2) << "Failed to get IAMStreamConfig interface from " | 500 DVLOG(2) << "Failed to get IAMStreamConfig interface from " |
492 "capture device"; | 501 "capture device"; |
493 return false; | 502 return false; |
494 } | 503 } |
495 | 504 |
496 // Get interface used for getting the frame rate. | 505 // Get interface used for getting the frame rate. |
497 ScopedComPtr<IAMVideoControl> video_control; | 506 ScopedComPtr<IAMVideoControl> video_control; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 return capabilities_.size() > 0; | 596 return capabilities_.size() > 0; |
588 } | 597 } |
589 | 598 |
590 // Loops through the list of capabilities and returns an index of the best | 599 // Loops through the list of capabilities and returns an index of the best |
591 // matching capability. | 600 // matching capability. |
592 // The algorithm prioritize height, width, frame rate and color format in that | 601 // The algorithm prioritize height, width, frame rate and color format in that |
593 // order. | 602 // order. |
594 int VideoCaptureDeviceWin::GetBestMatchedCapability(int requested_width, | 603 int VideoCaptureDeviceWin::GetBestMatchedCapability(int requested_width, |
595 int requested_height, | 604 int requested_height, |
596 int requested_frame_rate) { | 605 int requested_frame_rate) { |
| 606 DCHECK(CalledOnValidThread()); |
597 std::list<ResolutionDiff> diff_list; | 607 std::list<ResolutionDiff> diff_list; |
598 | 608 |
599 // Loop through the candidates to create a list of differentials between the | 609 // Loop through the candidates to create a list of differentials between the |
600 // requested resolution and the camera capability. | 610 // requested resolution and the camera capability. |
601 for (CapabilityMap::iterator iterator = capabilities_.begin(); | 611 for (CapabilityMap::iterator iterator = capabilities_.begin(); |
602 iterator != capabilities_.end(); | 612 iterator != capabilities_.end(); |
603 ++iterator) { | 613 ++iterator) { |
604 VideoCaptureCapability capability = iterator->second; | 614 VideoCaptureCapability capability = iterator->second; |
605 | 615 |
606 ResolutionDiff diff; | 616 ResolutionDiff diff; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 break; | 656 break; |
647 } | 657 } |
648 } | 658 } |
649 | 659 |
650 // Decide the best color format. | 660 // Decide the best color format. |
651 diff_list.sort(&CompareColor); | 661 diff_list.sort(&CompareColor); |
652 return diff_list.front().capability_index; | 662 return diff_list.front().capability_index; |
653 } | 663 } |
654 | 664 |
655 void VideoCaptureDeviceWin::SetErrorState(const char* reason) { | 665 void VideoCaptureDeviceWin::SetErrorState(const char* reason) { |
| 666 DCHECK(CalledOnValidThread()); |
656 DVLOG(1) << reason; | 667 DVLOG(1) << reason; |
657 state_ = kError; | 668 state_ = kError; |
658 observer_->OnError(); | 669 observer_->OnError(); |
659 } | 670 } |
660 | 671 |
661 } // namespace media | 672 } // namespace media |
OLD | NEW |