| 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 |