Chromium Code Reviews| 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/capture/video/mac/video_capture_device_mac.h" | 5 #include "media/capture/video/mac/video_capture_device_mac.h" |
| 6 | 6 |
| 7 #include <IOKit/IOCFPlugIn.h> | 7 #include <IOKit/IOCFPlugIn.h> |
| 8 #include <IOKit/usb/IOUSBLib.h> | 8 #include <IOKit/usb/IOUSBLib.h> |
| 9 #include <IOKit/usb/USBSpec.h> | 9 #include <IOKit/usb/USBSpec.h> |
| 10 #include <stddef.h> | 10 #include <stddef.h> |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 &video_control_interface)) { | 285 &video_control_interface)) { |
| 286 return; | 286 return; |
| 287 } | 287 } |
| 288 base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> | 288 base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> |
| 289 plugin_interface_ref(video_control_interface); | 289 plugin_interface_ref(video_control_interface); |
| 290 | 290 |
| 291 SetAntiFlickerInVideoControlInterface(video_control_interface, frequency); | 291 SetAntiFlickerInVideoControlInterface(video_control_interface, frequency); |
| 292 } | 292 } |
| 293 } | 293 } |
| 294 | 294 |
| 295 const std::string VideoCaptureDevice::Name::GetModel() const { | 295 VideoCaptureDeviceMac::VideoCaptureDeviceMac( |
| 296 // Skip the AVFoundation's not USB nor built-in devices. | 296 const VideoCaptureDeviceDescriptor& device_descriptor) |
| 297 if (capture_api_type() == AVFOUNDATION && transport_type() != USB_OR_BUILT_IN) | 297 : device_descriptor_(device_descriptor), |
| 298 return ""; | |
| 299 if (capture_api_type() == DECKLINK) | |
| 300 return ""; | |
| 301 // Both PID and VID are 4 characters. | |
| 302 if (unique_id_.size() < 2 * kVidPidSize) | |
| 303 return ""; | |
| 304 | |
| 305 // The last characters of device id is a concatenation of VID and then PID. | |
| 306 const size_t vid_location = unique_id_.size() - 2 * kVidPidSize; | |
| 307 std::string id_vendor = unique_id_.substr(vid_location, kVidPidSize); | |
| 308 const size_t pid_location = unique_id_.size() - kVidPidSize; | |
| 309 std::string id_product = unique_id_.substr(pid_location, kVidPidSize); | |
| 310 | |
| 311 return id_vendor + ":" + id_product; | |
| 312 } | |
| 313 | |
| 314 VideoCaptureDeviceMac::VideoCaptureDeviceMac(const Name& device_name) | |
| 315 : device_name_(device_name), | |
| 316 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 298 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 317 state_(kNotInitialized), | 299 state_(kNotInitialized), |
| 318 capture_device_(nil), | 300 capture_device_(nil), |
| 319 weak_factory_(this) { | 301 weak_factory_(this) {} |
| 320 } | |
| 321 | 302 |
| 322 VideoCaptureDeviceMac::~VideoCaptureDeviceMac() { | 303 VideoCaptureDeviceMac::~VideoCaptureDeviceMac() { |
| 323 DCHECK(task_runner_->BelongsToCurrentThread()); | 304 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 324 } | 305 } |
| 325 | 306 |
| 326 void VideoCaptureDeviceMac::AllocateAndStart( | 307 void VideoCaptureDeviceMac::AllocateAndStart( |
| 327 const VideoCaptureParams& params, | 308 const VideoCaptureParams& params, |
| 328 std::unique_ptr<VideoCaptureDevice::Client> client) { | 309 std::unique_ptr<VideoCaptureDevice::Client> client) { |
| 329 DCHECK(task_runner_->BelongsToCurrentThread()); | 310 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 330 if (state_ != kIdle) { | 311 if (state_ != kIdle) { |
| 331 return; | 312 return; |
| 332 } | 313 } |
| 333 | 314 |
| 334 client_ = std::move(client); | 315 client_ = std::move(client); |
| 335 if (device_name_.capture_api_type() == Name::AVFOUNDATION) | 316 if (device_descriptor_.capture_api == VideoCaptureApi::MACOSX_AVFOUNDATION) |
| 336 LogMessage("Using AVFoundation for device: " + device_name_.name()); | 317 LogMessage("Using AVFoundation for device: " + |
| 318 device_descriptor_.friendly_name); | |
| 337 | 319 |
| 338 NSString* deviceId = | 320 NSString* deviceId = |
| 339 [NSString stringWithUTF8String:device_name_.id().c_str()]; | 321 [NSString stringWithUTF8String:device_descriptor_.device_id.c_str()]; |
| 340 | 322 |
| 341 [capture_device_ setFrameReceiver:this]; | 323 [capture_device_ setFrameReceiver:this]; |
| 342 | 324 |
| 343 if (![capture_device_ setCaptureDevice:deviceId]) { | 325 if (![capture_device_ setCaptureDevice:deviceId]) { |
| 344 SetErrorState(FROM_HERE, "Could not open capture device."); | 326 SetErrorState(FROM_HERE, "Could not open capture device."); |
| 345 return; | 327 return; |
| 346 } | 328 } |
| 347 | 329 |
| 348 capture_format_.frame_size = params.requested_format.frame_size; | 330 capture_format_.frame_size = params.requested_format.frame_size; |
| 349 capture_format_.frame_rate = | 331 capture_format_.frame_rate = |
| 350 std::max(kMinFrameRate, | 332 std::max(kMinFrameRate, |
| 351 std::min(params.requested_format.frame_rate, kMaxFrameRate)); | 333 std::min(params.requested_format.frame_rate, kMaxFrameRate)); |
| 352 // Leave the pixel format selection to AVFoundation. The pixel format | 334 // Leave the pixel format selection to AVFoundation. The pixel format |
| 353 // will be passed to |ReceiveFrame|. | 335 // will be passed to |ReceiveFrame|. |
| 354 capture_format_.pixel_format = PIXEL_FORMAT_UNKNOWN; | 336 capture_format_.pixel_format = PIXEL_FORMAT_UNKNOWN; |
| 355 | 337 |
| 356 if (!UpdateCaptureResolution()) | 338 if (!UpdateCaptureResolution()) |
| 357 return; | 339 return; |
| 358 | 340 |
| 359 // Try setting the power line frequency removal (anti-flicker). The built-in | 341 // Try setting the power line frequency removal (anti-flicker). The built-in |
| 360 // cameras are normally suspended so the configuration must happen right | 342 // cameras are normally suspended so the configuration must happen right |
| 361 // before starting capture and during configuration. | 343 // before starting capture and during configuration. |
| 362 const std::string& device_model = device_name_.GetModel(); | 344 std::string device_model = GetDeviceModelId( |
|
emircan
2016/07/28 21:23:02
const std::string& device_model?
chfremer
2016/07/29 18:09:51
I will add const, but const reference is not possi
| |
| 345 device_descriptor_.device_id, device_descriptor_.capture_api, | |
| 346 device_descriptor_.transport_type); | |
| 363 if (device_model.length() > 2 * kVidPidSize) { | 347 if (device_model.length() > 2 * kVidPidSize) { |
| 364 std::string vendor_id = device_model.substr(0, kVidPidSize); | 348 std::string vendor_id = device_model.substr(0, kVidPidSize); |
| 365 std::string model_id = device_model.substr(kVidPidSize + 1); | 349 std::string model_id = device_model.substr(kVidPidSize + 1); |
| 366 int vendor_id_as_int, model_id_as_int; | 350 int vendor_id_as_int, model_id_as_int; |
| 367 if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) && | 351 if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) && |
| 368 base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) { | 352 base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) { |
| 369 SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int, | 353 SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int, |
| 370 GetPowerLineFrequency(params)); | 354 GetPowerLineFrequency(params)); |
| 371 } | 355 } |
| 372 } | 356 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 393 DCHECK(task_runner_->BelongsToCurrentThread()); | 377 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 394 DCHECK(state_ == kCapturing) << state_; | 378 DCHECK(state_ == kCapturing) << state_; |
| 395 | 379 |
| 396 if (photo_callback_) // Only one picture can be in flight at a time. | 380 if (photo_callback_) // Only one picture can be in flight at a time. |
| 397 return; | 381 return; |
| 398 | 382 |
| 399 photo_callback_.reset(new TakePhotoCallback(std::move(callback))); | 383 photo_callback_.reset(new TakePhotoCallback(std::move(callback))); |
| 400 [capture_device_ takePhoto]; | 384 [capture_device_ takePhoto]; |
| 401 } | 385 } |
| 402 | 386 |
| 403 bool VideoCaptureDeviceMac::Init( | 387 bool VideoCaptureDeviceMac::Init(VideoCaptureApi capture_api_type) { |
| 404 VideoCaptureDevice::Name::CaptureApiType capture_api_type) { | |
| 405 DCHECK(task_runner_->BelongsToCurrentThread()); | 388 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 406 DCHECK_EQ(state_, kNotInitialized); | 389 DCHECK_EQ(state_, kNotInitialized); |
| 407 | 390 |
| 408 if (capture_api_type != Name::AVFOUNDATION) | 391 if (capture_api_type != VideoCaptureApi::MACOSX_AVFOUNDATION) |
| 409 return false; | 392 return false; |
| 410 | 393 |
| 411 capture_device_.reset( | 394 capture_device_.reset( |
| 412 [[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this]); | 395 [[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this]); |
| 413 | 396 |
| 414 if (!capture_device_) | 397 if (!capture_device_) |
| 415 return false; | 398 return false; |
| 416 | 399 |
| 417 state_ = kIdle; | 400 state_ = kIdle; |
| 418 return true; | 401 return true; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 } | 440 } |
| 458 | 441 |
| 459 void VideoCaptureDeviceMac::ReceiveError( | 442 void VideoCaptureDeviceMac::ReceiveError( |
| 460 const tracked_objects::Location& from_here, | 443 const tracked_objects::Location& from_here, |
| 461 const std::string& reason) { | 444 const std::string& reason) { |
| 462 task_runner_->PostTask( | 445 task_runner_->PostTask( |
| 463 FROM_HERE, base::Bind(&VideoCaptureDeviceMac::SetErrorState, | 446 FROM_HERE, base::Bind(&VideoCaptureDeviceMac::SetErrorState, |
| 464 weak_factory_.GetWeakPtr(), from_here, reason)); | 447 weak_factory_.GetWeakPtr(), from_here, reason)); |
| 465 } | 448 } |
| 466 | 449 |
| 450 void VideoCaptureDeviceMac::LogMessage(const std::string& message) { | |
| 451 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 452 if (client_) | |
| 453 client_->OnLog(message); | |
| 454 } | |
| 455 | |
| 456 // static | |
| 457 std::string VideoCaptureDeviceMac::GetDeviceModelId( | |
| 458 const std::string& device_id, | |
| 459 VideoCaptureApi capture_api, | |
| 460 VideoCaptureTransportType transport_type) { | |
| 461 // Skip the AVFoundation's not USB nor built-in devices. | |
| 462 if (capture_api == VideoCaptureApi::MACOSX_AVFOUNDATION && | |
| 463 transport_type != VideoCaptureTransportType::MACOSX_USB_OR_BUILT_IN) | |
| 464 return ""; | |
| 465 if (capture_api == VideoCaptureApi::MACOSX_DECKLINK) | |
| 466 return ""; | |
| 467 // Both PID and VID are 4 characters. | |
| 468 if (device_id.size() < 2 * kVidPidSize) | |
| 469 return ""; | |
| 470 | |
| 471 // The last characters of device id is a concatenation of VID and then PID. | |
| 472 const size_t vid_location = device_id.size() - 2 * kVidPidSize; | |
| 473 std::string id_vendor = device_id.substr(vid_location, kVidPidSize); | |
| 474 const size_t pid_location = device_id.size() - kVidPidSize; | |
| 475 std::string id_product = device_id.substr(pid_location, kVidPidSize); | |
| 476 | |
| 477 return id_vendor + ":" + id_product; | |
| 478 } | |
| 479 | |
| 467 void VideoCaptureDeviceMac::SetErrorState( | 480 void VideoCaptureDeviceMac::SetErrorState( |
| 468 const tracked_objects::Location& from_here, | 481 const tracked_objects::Location& from_here, |
| 469 const std::string& reason) { | 482 const std::string& reason) { |
| 470 DCHECK(task_runner_->BelongsToCurrentThread()); | 483 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 471 state_ = kError; | 484 state_ = kError; |
| 472 client_->OnError(from_here, reason); | 485 client_->OnError(from_here, reason); |
| 473 } | 486 } |
| 474 | 487 |
| 475 void VideoCaptureDeviceMac::LogMessage(const std::string& message) { | |
| 476 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 477 if (client_) | |
| 478 client_->OnLog(message); | |
| 479 } | |
| 480 | |
| 481 bool VideoCaptureDeviceMac::UpdateCaptureResolution() { | 488 bool VideoCaptureDeviceMac::UpdateCaptureResolution() { |
| 482 if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() | 489 if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() |
| 483 width:capture_format_.frame_size.width() | 490 width:capture_format_.frame_size.width() |
| 484 frameRate:capture_format_.frame_rate]) { | 491 frameRate:capture_format_.frame_rate]) { |
| 485 ReceiveError(FROM_HERE, "Could not configure capture device."); | 492 ReceiveError(FROM_HERE, "Could not configure capture device."); |
| 486 return false; | 493 return false; |
| 487 } | 494 } |
| 488 return true; | 495 return true; |
| 489 } | 496 } |
| 490 | 497 |
| 491 } // namespace media | 498 } // namespace media |
| OLD | NEW |