Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: media/video/capture/mac/video_capture_device_mac.mm

Issue 558623002: Video capture: Refactor GetBestMatchedFormat from Win to OS independent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: sort pixel formats in order of preference Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/mac/video_capture_device_mac.h" 5 #include "media/video/capture/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 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop/message_loop_proxy.h" 14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/mac/scoped_ioobject.h" 15 #include "base/mac/scoped_ioobject.h"
16 #include "base/mac/scoped_ioplugininterface.h" 16 #include "base/mac/scoped_ioplugininterface.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/time/time.h" 18 #include "base/time/time.h"
19 #import "media/base/mac/avfoundation_glue.h" 19 #import "media/base/mac/avfoundation_glue.h"
20 #import "media/video/capture/mac/platform_video_capturing_mac.h" 20 #import "media/video/capture/mac/platform_video_capturing_mac.h"
21 #import "media/video/capture/mac/video_capture_device_avfoundation_mac.h" 21 #import "media/video/capture/mac/video_capture_device_avfoundation_mac.h"
22 #import "media/video/capture/mac/video_capture_device_qtkit_mac.h" 22 #import "media/video/capture/mac/video_capture_device_qtkit_mac.h"
23 #include "ui/gfx/size.h"
23 24
24 @implementation DeviceNameAndTransportType 25 @implementation DeviceNameAndTransportType
25 26
26 - (id)initWithName:(NSString*)deviceName transportType:(int32_t)transportType { 27 - (id)initWithName:(NSString*)deviceName transportType:(int32_t)transportType {
27 if (self = [super init]) { 28 if (self = [super init]) {
28 deviceName_.reset([deviceName copy]); 29 deviceName_.reset([deviceName copy]);
29 transportType_ = transportType; 30 transportType_ = transportType;
30 } 31 }
31 return self; 32 return self;
32 } 33 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 const int k60Hz = 2; 88 const int k60Hz = 2;
88 const int kPuPowerLineFrequencyControlCommandSize = 1; 89 const int kPuPowerLineFrequencyControlCommandSize = 1;
89 90
90 // Addition to the IOUSB family of structures, with subtype and unit ID. 91 // Addition to the IOUSB family of structures, with subtype and unit ID.
91 typedef struct IOUSBInterfaceDescriptor { 92 typedef struct IOUSBInterfaceDescriptor {
92 IOUSBDescriptorHeader header; 93 IOUSBDescriptorHeader header;
93 UInt8 bDescriptorSubType; 94 UInt8 bDescriptorSubType;
94 UInt8 bUnitID; 95 UInt8 bUnitID;
95 } IOUSBInterfaceDescriptor; 96 } IOUSBInterfaceDescriptor;
96 97
97 // TODO(ronghuawu): Replace this with CapabilityList::GetBestMatchedCapability. 98 static void GetBestMatchSupportedResolution(gfx::Size* resolution) {
98 void GetBestMatchSupportedResolution(int* width, int* height) {
99 int min_diff = kint32max; 99 int min_diff = kint32max;
100 int matched_width = *width; 100 const int desired_area = resolution->GetArea();
101 int matched_height = *height;
102 int desired_res_area = *width * *height;
103 for (size_t i = 0; i < arraysize(kWellSupportedResolutions); ++i) { 101 for (size_t i = 0; i < arraysize(kWellSupportedResolutions); ++i) {
mcasas 2014/10/13 08:18:45 nit: range-based for loop...? ;)
104 int area = kWellSupportedResolutions[i]->width * 102 const int area = kWellSupportedResolutions[i]->width *
105 kWellSupportedResolutions[i]->height; 103 kWellSupportedResolutions[i]->height;
106 int diff = std::abs(desired_res_area - area); 104 const int diff = std::abs(desired_area - area);
107 if (diff < min_diff) { 105 if (diff < min_diff) {
108 min_diff = diff; 106 min_diff = diff;
109 matched_width = kWellSupportedResolutions[i]->width; 107 resolution->SetSize(kWellSupportedResolutions[i]->width,
110 matched_height = kWellSupportedResolutions[i]->height; 108 kWellSupportedResolutions[i]->height);
111 } 109 }
112 } 110 }
113 *width = matched_width;
114 *height = matched_height;
115 } 111 }
116 112
117 // Tries to create a user-side device interface for a given USB device. Returns 113 // Tries to create a user-side device interface for a given USB device. Returns
118 // true if interface was found and passes it back in |device_interface|. The 114 // true if interface was found and passes it back in |device_interface|. The
119 // caller should release |device_interface|. 115 // caller should release |device_interface|.
120 static bool FindDeviceInterfaceInUsbDevice( 116 static bool FindDeviceInterfaceInUsbDevice(
121 const int vendor_id, 117 const int vendor_id,
122 const int product_id, 118 const int product_id,
123 const io_service_t usb_device, 119 const io_service_t usb_device,
124 IOUSBDeviceInterface*** device_interface) { 120 IOUSBDeviceInterface*** device_interface) {
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 [capture_device_ release]; 359 [capture_device_ release];
364 } 360 }
365 361
366 void VideoCaptureDeviceMac::AllocateAndStart( 362 void VideoCaptureDeviceMac::AllocateAndStart(
367 const VideoCaptureParams& params, 363 const VideoCaptureParams& params,
368 scoped_ptr<VideoCaptureDevice::Client> client) { 364 scoped_ptr<VideoCaptureDevice::Client> client) {
369 DCHECK(task_runner_->BelongsToCurrentThread()); 365 DCHECK(task_runner_->BelongsToCurrentThread());
370 if (state_ != kIdle) { 366 if (state_ != kIdle) {
371 return; 367 return;
372 } 368 }
373 int width = params.requested_format.frame_size.width();
374 int height = params.requested_format.frame_size.height();
375 float frame_rate = params.requested_format.frame_rate;
376 369
377 // QTKit API can scale captured frame to any size requested, which would lead 370 // QTKit API can scale captured frame to any size requested, which would lead
378 // to undesired aspect ratio changes. Try to open the camera with a known 371 // to undesired aspect ratio changes. Try to open the camera with a known
379 // supported format and let the client crop/pad the captured frames. 372 // supported format and let the client crop/pad the captured frames.
373 gfx::Size resolution = params.requested_format.frame_size;
380 if (!AVFoundationGlue::IsAVFoundationSupported()) 374 if (!AVFoundationGlue::IsAVFoundationSupported())
381 GetBestMatchSupportedResolution(&width, &height); 375 GetBestMatchSupportedResolution(&resolution);
382 376
383 client_ = client.Pass(); 377 client_ = client.Pass();
384 if (device_name_.capture_api_type() == Name::AVFOUNDATION) 378 if (device_name_.capture_api_type() == Name::AVFOUNDATION)
385 LogMessage("Using AVFoundation for device: " + device_name_.name()); 379 LogMessage("Using AVFoundation for device: " + device_name_.name());
386 else 380 else
387 LogMessage("Using QTKit for device: " + device_name_.name()); 381 LogMessage("Using QTKit for device: " + device_name_.name());
388 NSString* deviceId = 382 NSString* deviceId =
389 [NSString stringWithUTF8String:device_name_.id().c_str()]; 383 [NSString stringWithUTF8String:device_name_.id().c_str()];
390 384
391 [capture_device_ setFrameReceiver:this]; 385 [capture_device_ setFrameReceiver:this];
392 386
393 if (![capture_device_ setCaptureDevice:deviceId]) { 387 if (![capture_device_ setCaptureDevice:deviceId]) {
394 SetErrorState("Could not open capture device."); 388 SetErrorState("Could not open capture device.");
395 return; 389 return;
396 } 390 }
397 if (frame_rate < kMinFrameRate)
398 frame_rate = kMinFrameRate;
399 else if (frame_rate > kMaxFrameRate)
400 frame_rate = kMaxFrameRate;
401 391
402 capture_format_.frame_size.SetSize(width, height); 392 capture_format_.frame_size = resolution;
403 capture_format_.frame_rate = frame_rate; 393 capture_format_.frame_rate =
394 std::max(kMinFrameRate,
395 std::min(params.requested_format.frame_rate, kMaxFrameRate));
404 capture_format_.pixel_format = PIXEL_FORMAT_UYVY; 396 capture_format_.pixel_format = PIXEL_FORMAT_UYVY;
405 397
406 // QTKit: Set the capture resolution only if this is VGA or smaller, otherwise 398 // QTKit: Set the capture resolution only if this is VGA or smaller, otherwise
407 // leave it unconfigured and start capturing: QTKit will produce frames at the 399 // leave it unconfigured and start capturing: QTKit will produce frames at the
408 // native resolution, allowing us to identify cameras whose native resolution 400 // native resolution, allowing us to identify cameras whose native resolution
409 // is too low for HD. This additional information comes at a cost in startup 401 // is too low for HD. This additional information comes at a cost in startup
410 // latency, because the webcam will need to be reopened if its default 402 // latency, because the webcam will need to be reopened if its default
411 // resolution is not HD or VGA. 403 // resolution is not HD or VGA.
412 // AVfoundation is configured for all resolutions. 404 // AVfoundation is configured for all resolutions.
413 if (AVFoundationGlue::IsAVFoundationSupported() || width <= kVGA.width || 405 if (AVFoundationGlue::IsAVFoundationSupported() ||
414 height <= kVGA.height) { 406 resolution.width() <= kVGA.width || resolution.height() <= kVGA.height) {
415 if (!UpdateCaptureResolution()) 407 if (!UpdateCaptureResolution())
416 return; 408 return;
417 } 409 }
418 410
419 // Try setting the power line frequency removal (anti-flicker). The built-in 411 // Try setting the power line frequency removal (anti-flicker). The built-in
420 // cameras are normally suspended so the configuration must happen right 412 // cameras are normally suspended so the configuration must happen right
421 // before starting capture and during configuration. 413 // before starting capture and during configuration.
422 const std::string& device_model = device_name_.GetModel(); 414 const std::string& device_model = device_name_.GetModel();
423 if (device_model.length() > 2 * kVidPidSize) { 415 if (device_model.length() > 2 * kVidPidSize) {
424 std::string vendor_id = device_model.substr(0, kVidPidSize); 416 std::string vendor_id = device_model.substr(0, kVidPidSize);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() 567 if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height()
576 width:capture_format_.frame_size.width() 568 width:capture_format_.frame_size.width()
577 frameRate:capture_format_.frame_rate]) { 569 frameRate:capture_format_.frame_rate]) {
578 ReceiveError("Could not configure capture device."); 570 ReceiveError("Could not configure capture device.");
579 return false; 571 return false;
580 } 572 }
581 return true; 573 return true;
582 } 574 }
583 575
584 } // namespace media 576 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/video/capture/video_capture_device.h » ('j') | media/video/capture/video_capture_device.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698