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 == |
336 LogMessage("Using AVFoundation for device: " + device_name_.name()); | 317 VideoCaptureApiType::MACOSX_AVFOUNDATION) |
| 318 LogMessage("Using AVFoundation for device: " + |
| 319 device_descriptor_.friendly_name); |
337 | 320 |
338 NSString* deviceId = | 321 NSString* deviceId = |
339 [NSString stringWithUTF8String:device_name_.id().c_str()]; | 322 [NSString stringWithUTF8String:device_descriptor_.device_id.c_str()]; |
340 | 323 |
341 [capture_device_ setFrameReceiver:this]; | 324 [capture_device_ setFrameReceiver:this]; |
342 | 325 |
343 if (![capture_device_ setCaptureDevice:deviceId]) { | 326 if (![capture_device_ setCaptureDevice:deviceId]) { |
344 SetErrorState(FROM_HERE, "Could not open capture device."); | 327 SetErrorState(FROM_HERE, "Could not open capture device."); |
345 return; | 328 return; |
346 } | 329 } |
347 | 330 |
348 capture_format_.frame_size = params.requested_format.frame_size; | 331 capture_format_.frame_size = params.requested_format.frame_size; |
349 capture_format_.frame_rate = | 332 capture_format_.frame_rate = |
350 std::max(kMinFrameRate, | 333 std::max(kMinFrameRate, |
351 std::min(params.requested_format.frame_rate, kMaxFrameRate)); | 334 std::min(params.requested_format.frame_rate, kMaxFrameRate)); |
352 // Leave the pixel format selection to AVFoundation. The pixel format | 335 // Leave the pixel format selection to AVFoundation. The pixel format |
353 // will be passed to |ReceiveFrame|. | 336 // will be passed to |ReceiveFrame|. |
354 capture_format_.pixel_format = PIXEL_FORMAT_UNKNOWN; | 337 capture_format_.pixel_format = PIXEL_FORMAT_UNKNOWN; |
355 | 338 |
356 if (!UpdateCaptureResolution()) | 339 if (!UpdateCaptureResolution()) |
357 return; | 340 return; |
358 | 341 |
359 // Try setting the power line frequency removal (anti-flicker). The built-in | 342 // Try setting the power line frequency removal (anti-flicker). The built-in |
360 // cameras are normally suspended so the configuration must happen right | 343 // cameras are normally suspended so the configuration must happen right |
361 // before starting capture and during configuration. | 344 // before starting capture and during configuration. |
362 const std::string& device_model = device_name_.GetModel(); | 345 std::string device_model = GetDeviceModelId(device_descriptor_); |
363 if (device_model.length() > 2 * kVidPidSize) { | 346 if (device_model.length() > 2 * kVidPidSize) { |
364 std::string vendor_id = device_model.substr(0, kVidPidSize); | 347 std::string vendor_id = device_model.substr(0, kVidPidSize); |
365 std::string model_id = device_model.substr(kVidPidSize + 1); | 348 std::string model_id = device_model.substr(kVidPidSize + 1); |
366 int vendor_id_as_int, model_id_as_int; | 349 int vendor_id_as_int, model_id_as_int; |
367 if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) && | 350 if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) && |
368 base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) { | 351 base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) { |
369 SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int, | 352 SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int, |
370 GetPowerLineFrequency(params)); | 353 GetPowerLineFrequency(params)); |
371 } | 354 } |
372 } | 355 } |
(...skipping 20 matching lines...) Expand all Loading... |
393 DCHECK(task_runner_->BelongsToCurrentThread()); | 376 DCHECK(task_runner_->BelongsToCurrentThread()); |
394 DCHECK(state_ == kCapturing) << state_; | 377 DCHECK(state_ == kCapturing) << state_; |
395 | 378 |
396 if (photo_callback_) // Only one picture can be in flight at a time. | 379 if (photo_callback_) // Only one picture can be in flight at a time. |
397 return; | 380 return; |
398 | 381 |
399 photo_callback_.reset(new TakePhotoCallback(std::move(callback))); | 382 photo_callback_.reset(new TakePhotoCallback(std::move(callback))); |
400 [capture_device_ takePhoto]; | 383 [capture_device_ takePhoto]; |
401 } | 384 } |
402 | 385 |
403 bool VideoCaptureDeviceMac::Init( | 386 bool VideoCaptureDeviceMac::Init(VideoCaptureApiType capture_api_type) { |
404 VideoCaptureDevice::Name::CaptureApiType capture_api_type) { | |
405 DCHECK(task_runner_->BelongsToCurrentThread()); | 387 DCHECK(task_runner_->BelongsToCurrentThread()); |
406 DCHECK_EQ(state_, kNotInitialized); | 388 DCHECK_EQ(state_, kNotInitialized); |
407 | 389 |
408 if (capture_api_type != Name::AVFOUNDATION) | 390 if (capture_api_type != VideoCaptureApiType::MACOSX_AVFOUNDATION) |
409 return false; | 391 return false; |
410 | 392 |
411 capture_device_.reset( | 393 capture_device_.reset( |
412 [[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this]); | 394 [[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this]); |
413 | 395 |
414 if (!capture_device_) | 396 if (!capture_device_) |
415 return false; | 397 return false; |
416 | 398 |
417 state_ = kIdle; | 399 state_ = kIdle; |
418 return true; | 400 return true; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 bool VideoCaptureDeviceMac::UpdateCaptureResolution() { | 463 bool VideoCaptureDeviceMac::UpdateCaptureResolution() { |
482 if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() | 464 if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() |
483 width:capture_format_.frame_size.width() | 465 width:capture_format_.frame_size.width() |
484 frameRate:capture_format_.frame_rate]) { | 466 frameRate:capture_format_.frame_rate]) { |
485 ReceiveError(FROM_HERE, "Could not configure capture device."); | 467 ReceiveError(FROM_HERE, "Could not configure capture device."); |
486 return false; | 468 return false; |
487 } | 469 } |
488 return true; | 470 return true; |
489 } | 471 } |
490 | 472 |
| 473 // static |
| 474 std::string VideoCaptureDeviceMac::GetDeviceModelId( |
| 475 const VideoCaptureDeviceDescriptor& device_descriptor) { |
| 476 // Skip the AVFoundation's not USB nor built-in devices. |
| 477 if (device_descriptor.capture_api == |
| 478 VideoCaptureApiType::MACOSX_AVFOUNDATION && |
| 479 device_descriptor.transport_type != |
| 480 VideoCaptureTransportType::MACOSX_USB_OR_BUILT_IN) |
| 481 return ""; |
| 482 if (device_descriptor.capture_api == VideoCaptureApiType::MACOSX_DECKLINK) |
| 483 return ""; |
| 484 // Both PID and VID are 4 characters. |
| 485 if (device_descriptor.device_id.size() < 2 * kVidPidSize) |
| 486 return ""; |
| 487 |
| 488 // The last characters of device id is a concatenation of VID and then PID. |
| 489 const size_t vid_location = |
| 490 device_descriptor.device_id.size() - 2 * kVidPidSize; |
| 491 std::string id_vendor = |
| 492 device_descriptor.device_id.substr(vid_location, kVidPidSize); |
| 493 const size_t pid_location = device_descriptor.device_id.size() - kVidPidSize; |
| 494 std::string id_product = |
| 495 device_descriptor.device_id.substr(pid_location, kVidPidSize); |
| 496 |
| 497 return id_vendor + ":" + id_product; |
| 498 } |
| 499 |
491 } // namespace media | 500 } // namespace media |
OLD | NEW |