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