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