#include "media/video/capture/mac/video_capture_device_mac.h"
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/usb/USBSpec.h>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/mac/scoped_ioobject.h"
+#include "base/mac/scoped_ioplugininterface.h"
+#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
-#import "media/video/capture/mac/avfoundation_glue.h"
+#import "media/base/mac/avfoundation_glue.h"
#import "media/video/capture/mac/platform_video_capturing_mac.h"
#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h"
#import "media/video/capture/mac/video_capture_device_qtkit_mac.h"
-namespace media {
+@implementation DeviceNameAndTransportType
-const int kMinFrameRate = 1;
-const int kMaxFrameRate = 30;
+- (id)initWithName:(NSString*)deviceName transportType:(int32_t)transportType {
+ if (self = [super init]) {
+ deviceName_.reset([deviceName copy]);
+ transportType_ = transportType;
+ }
+ return self;
+}
-// In QT device identifiers, the USB VID and PID are stored in 4 bytes each.
-const size_t kVidPidSize = 4;
+- (NSString*)deviceName {
+ return deviceName_;
+}
-struct Resolution {
- int width;
- int height;
-};
+- (int32_t)transportType {
+ return transportType_;
+}
-const Resolution kQVGA = { 320, 240 },
- kVGA = { 640, 480 },
- kHD = { 1280, 720 };
+@end // @implementation DeviceNameAndTransportType
+
+namespace media {
-const Resolution* const kWellSupportedResolutions[] = {
- &kQVGA,
- &kVGA,
- &kHD,
+// Mac specific limits for minimum and maximum frame rate.
+const float kMinFrameRate = 1.0f;
+const float kMaxFrameRate = 30.0f;
+
+// In device identifiers, the USB VID and PID are stored in 4 bytes each.
+const size_t kVidPidSize = 4;
+
+const struct Resolution {
+ const int width;
+ const int height;
+} kQVGA = { 320, 240 },
+ kVGA = { 640, 480 },
+ kHD = { 1280, 720 };
+
+const struct Resolution* const kWellSupportedResolutions[] = {
+ &kQVGA,
+ &kVGA,
+ &kHD,
};
// Rescaling the image to fix the pixel aspect ratio runs the risk of making
// the aspect ratio worse, if QTKit selects a new source mode with a different
-// shape. This constant ensures that we don't take this risk if the current
+// shape. This constant ensures that we don't take this risk if the current
// aspect ratio is tolerable.
const float kMaxPixelAspectRatio = 1.15;
+// The following constants are extracted from the specification "Universal
+// Serial Bus Device Class Definition for Video Devices", Rev. 1.1 June 1, 2005.
+// http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
+// CS_INTERFACE: Sec. A.4 "Video Class-Specific Descriptor Types".
+const int kVcCsInterface = 0x24;
+// VC_PROCESSING_UNIT: Sec. A.5 "Video Class-Specific VC Interface Descriptor
+// Subtypes".
+const int kVcProcessingUnit = 0x5;
+// SET_CUR: Sec. A.8 "Video Class-Specific Request Codes".
+const int kVcRequestCodeSetCur = 0x1;
+// PU_POWER_LINE_FREQUENCY_CONTROL: Sec. A.9.5 "Processing Unit Control
+// Selectors".
+const int kPuPowerLineFrequencyControl = 0x5;
+// Sec. 4.2.2.3.5 Power Line Frequency Control.
+const int k50Hz = 1;
+const int k60Hz = 2;
+const int kPuPowerLineFrequencyControlCommandSize = 1;
+
+// Addition to the IOUSB family of structures, with subtype and unit ID.
+typedef struct IOUSBInterfaceDescriptor {
+ IOUSBDescriptorHeader header;
+ UInt8 bDescriptorSubType;
+ UInt8 bUnitID;
+} IOUSBInterfaceDescriptor;
+
// TODO(ronghuawu): Replace this with CapabilityList::GetBestMatchedCapability.
void GetBestMatchSupportedResolution(int* width, int* height) {
int min_diff = kint32max;
*height = matched_height;
}
-void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
- // Loop through all available devices and add to |device_names|.
- device_names->clear();
+// Tries to create a user-side device interface for a given USB device. Returns
+// true if interface was found and passes it back in |device_interface|. The
+// caller should release |device_interface|.
+static bool FindDeviceInterfaceInUsbDevice(
+ const int vendor_id,
+ const int product_id,
+ const io_service_t usb_device,
+ IOUSBDeviceInterface*** device_interface) {
+ // Create a plug-in, i.e. a user-side controller to manipulate USB device.
+ IOCFPlugInInterface** plugin;
+ SInt32 score; // Unused, but required for IOCreatePlugInInterfaceForService.
+ kern_return_t kr =
+ IOCreatePlugInInterfaceForService(usb_device,
+ kIOUSBDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugin,
+ &score);
+ if (kr != kIOReturnSuccess || !plugin) {
+ DLOG(ERROR) << "IOCreatePlugInInterfaceForService";
+ return false;
+ }
+ base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_ref(plugin);
+
+ // Fetch the Device Interface from the plug-in.
+ HRESULT res =
+ (*plugin)->QueryInterface(plugin,
+ CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
+ reinterpret_cast<LPVOID*>(device_interface));
+ if (!SUCCEEDED(res) || !*device_interface) {
+ DLOG(ERROR) << "QueryInterface, couldn't create interface to USB";
+ return false;
+ }
+ return true;
+}
- NSDictionary* capture_devices;
- if (AVFoundationGlue::IsAVFoundationSupported()) {
- DVLOG(1) << "Enumerating video capture devices using AVFoundation";
- capture_devices = [VideoCaptureDeviceAVFoundation deviceNames];
- } else {
- DVLOG(1) << "Enumerating video capture devices using QTKit";
- capture_devices = [VideoCaptureDeviceQTKit deviceNames];
+// Tries to find a Video Control type interface inside a general USB device
+// interface |device_interface|, and returns it in |video_control_interface| if
+// found. The returned interface must be released in the caller.
+static bool FindVideoControlInterfaceInDeviceInterface(
+ IOUSBDeviceInterface** device_interface,
+ IOCFPlugInInterface*** video_control_interface) {
+ // Create an iterator to the list of Video-AVControl interfaces of the device,
+ // then get the first interface in the list.
+ io_iterator_t interface_iterator;
+ IOUSBFindInterfaceRequest interface_request = {
+ .bInterfaceClass = kUSBVideoInterfaceClass,
+ .bInterfaceSubClass = kUSBVideoControlSubClass,
+ .bInterfaceProtocol = kIOUSBFindInterfaceDontCare,
+ .bAlternateSetting = kIOUSBFindInterfaceDontCare
+ };
+ kern_return_t kr =
+ (*device_interface)->CreateInterfaceIterator(device_interface,
+ &interface_request,
+ &interface_iterator);
+ if (kr != kIOReturnSuccess) {
+ DLOG(ERROR) << "Could not create an iterator to the device's interfaces.";
+ return false;
+ }
+ base::mac::ScopedIOObject<io_iterator_t> iterator_ref(interface_iterator);
+
+ // There should be just one interface matching the class-subclass desired.
+ io_service_t found_interface;
+ found_interface = IOIteratorNext(interface_iterator);
+ if (!found_interface) {
+ DLOG(ERROR) << "Could not find a Video-AVControl interface in the device.";
+ return false;
+ }
+ base::mac::ScopedIOObject<io_service_t> found_interface_ref(found_interface);
+
+ // Create a user side controller (i.e. a "plug-in") for the found interface.
+ SInt32 score;
+ kr = IOCreatePlugInInterfaceForService(found_interface,
+ kIOUSBInterfaceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ video_control_interface,
+ &score);
+ if (kr != kIOReturnSuccess || !*video_control_interface) {
+ DLOG(ERROR) << "IOCreatePlugInInterfaceForService";
+ return false;
+ }
+ return true;
+}
+
+// Creates a control interface for |plugin_interface| and produces a command to
+// set the appropriate Power Line frequency for flicker removal.
+static void SetAntiFlickerInVideoControlInterface(
+ IOCFPlugInInterface** plugin_interface,
+ const int frequency) {
+ // Create, the control interface for the found plug-in, and release
+ // the intermediate plug-in.
+ IOUSBInterfaceInterface** control_interface = NULL;
+ HRESULT res = (*plugin_interface)->QueryInterface(
+ plugin_interface,
+ CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
+ reinterpret_cast<LPVOID*>(&control_interface));
+ if (!SUCCEEDED(res) || !control_interface ) {
+ DLOG(ERROR) << "Couldn’t create control interface";
+ return;
}
- for (NSString* key in capture_devices) {
- Name name([[capture_devices valueForKey:key] UTF8String],
- [key UTF8String]);
- device_names->push_back(name);
+ base::mac::ScopedIOPluginInterface<IOUSBInterfaceInterface>
+ control_interface_ref(control_interface);
+
+ // Find the device's unit ID presenting type 0x24 (kVcCsInterface) and
+ // subtype 0x5 (kVcProcessingUnit). Inside this unit is where we find the
+ // power line frequency removal setting, and this id is device dependent.
+ int real_unit_id = -1;
+ IOUSBDescriptorHeader* descriptor = NULL;
+ IOUSBInterfaceDescriptor* cs_descriptor = NULL;
+ IOUSBInterfaceInterface220** interface =
+ reinterpret_cast<IOUSBInterfaceInterface220**>(control_interface);
+ while ((descriptor = (*interface)->FindNextAssociatedDescriptor(
+ interface, descriptor, kUSBAnyDesc))) {
+ cs_descriptor =
+ reinterpret_cast<IOUSBInterfaceDescriptor*>(descriptor);
+ if ((descriptor->bDescriptorType == kVcCsInterface) &&
+ (cs_descriptor->bDescriptorSubType == kVcProcessingUnit)) {
+ real_unit_id = cs_descriptor->bUnitID;
+ break;
+ }
+ }
+ DVLOG_IF(1, real_unit_id == -1) << "This USB device doesn't seem to have a "
+ << " VC_PROCESSING_UNIT, anti-flicker not available";
+ if (real_unit_id == -1)
+ return;
+
+ if ((*control_interface)->USBInterfaceOpen(control_interface) !=
+ kIOReturnSuccess) {
+ DLOG(ERROR) << "Unable to open control interface";
+ return;
}
+
+ // Create the control request and launch it to the device's control interface.
+ // Note how the wIndex needs the interface number OR'ed in the lowest bits.
+ IOUSBDevRequest command;
+ command.bmRequestType = USBmakebmRequestType(kUSBOut,
+ kUSBClass,
+ kUSBInterface);
+ command.bRequest = kVcRequestCodeSetCur;
+ UInt8 interface_number;
+ (*control_interface)->GetInterfaceNumber(control_interface,
+ &interface_number);
+ command.wIndex = (real_unit_id << 8) | interface_number;
+ const int selector = kPuPowerLineFrequencyControl;
+ command.wValue = (selector << 8);
+ command.wLength = kPuPowerLineFrequencyControlCommandSize;
+ command.wLenDone = 0;
+ int power_line_flag_value = (frequency == 50) ? k50Hz : k60Hz;
+ command.pData = &power_line_flag_value;
+
+ IOReturn ret = (*control_interface)->ControlRequest(control_interface,
+ 0, &command);
+ DLOG_IF(ERROR, ret != kIOReturnSuccess) << "Anti-flicker control request"
+ << " failed (0x" << std::hex << ret << "), unit id: " << real_unit_id;
+ DVLOG_IF(1, ret == kIOReturnSuccess) << "Anti-flicker set to " << frequency
+ << "Hz";
+
+ (*control_interface)->USBInterfaceClose(control_interface);
}
-// static
-void VideoCaptureDevice::GetDeviceSupportedFormats(const Name& device,
- VideoCaptureFormats* formats) {
- NOTIMPLEMENTED();
+// Sets the flicker removal in a USB webcam identified by |vendor_id| and
+// |product_id|, if available. The process includes first finding all USB
+// devices matching the specified |vendor_id| and |product_id|; for each
+// matching device, a device interface, and inside it a video control interface
+// are created. The latter is used to a send a power frequency setting command.
+static void SetAntiFlickerInUsbDevice(const int vendor_id,
+ const int product_id,
+ const int frequency) {
+ if (frequency == 0)
+ return;
+ DVLOG(1) << "Setting Power Line Frequency to " << frequency << " Hz, device "
+ << std::hex << vendor_id << "-" << product_id;
+
+ // Compose a search dictionary with vendor and product ID.
+ CFMutableDictionaryRef query_dictionary =
+ IOServiceMatching(kIOUSBDeviceClassName);
+ CFDictionarySetValue(query_dictionary, CFSTR(kUSBVendorName),
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor_id));
+ CFDictionarySetValue(query_dictionary, CFSTR(kUSBProductName),
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product_id));
+
+ io_iterator_t usb_iterator;
+ kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault,
+ query_dictionary,
+ &usb_iterator);
+ if (kr != kIOReturnSuccess) {
+ DLOG(ERROR) << "No devices found with specified Vendor and Product ID.";
+ return;
+ }
+ base::mac::ScopedIOObject<io_iterator_t> usb_iterator_ref(usb_iterator);
+
+ while (io_service_t usb_device = IOIteratorNext(usb_iterator)) {
+ base::mac::ScopedIOObject<io_service_t> usb_device_ref(usb_device);
+
+ IOUSBDeviceInterface** device_interface = NULL;
+ if (!FindDeviceInterfaceInUsbDevice(vendor_id, product_id,
+ usb_device, &device_interface)) {
+ return;
+ }
+ base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface>
+ device_interface_ref(device_interface);
+
+ IOCFPlugInInterface** video_control_interface = NULL;
+ if (!FindVideoControlInterfaceInDeviceInterface(device_interface,
+ &video_control_interface)) {
+ return;
+ }
+ base::mac::ScopedIOPluginInterface<IOCFPlugInInterface>
+ plugin_interface_ref(video_control_interface);
+
+ SetAntiFlickerInVideoControlInterface(video_control_interface, frequency);
+ }
}
const std::string VideoCaptureDevice::Name::GetModel() const {
+ // Skip the AVFoundation's not USB nor built-in devices.
+ if (capture_api_type() == AVFOUNDATION && transport_type() != USB_OR_BUILT_IN)
+ return "";
+ if (capture_api_type() == DECKLINK)
+ return "";
// Both PID and VID are 4 characters.
- if (unique_id_.size() < 2 * kVidPidSize) {
+ if (unique_id_.size() < 2 * kVidPidSize)
return "";
- }
// The last characters of device id is a concatenation of VID and then PID.
const size_t vid_location = unique_id_.size() - 2 * kVidPidSize;
return id_vendor + ":" + id_product;
}
-VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
- VideoCaptureDeviceMac* capture_device =
- new VideoCaptureDeviceMac(device_name);
- if (!capture_device->Init()) {
- LOG(ERROR) << "Could not initialize VideoCaptureDevice.";
- delete capture_device;
- capture_device = NULL;
- }
- return capture_device;
-}
-
VideoCaptureDeviceMac::VideoCaptureDeviceMac(const Name& device_name)
: device_name_(device_name),
- sent_frame_info_(false),
tried_to_square_pixels_(false),
task_runner_(base::MessageLoopProxy::current()),
state_(kNotInitialized),
- weak_factory_(this),
- weak_this_(weak_factory_.GetWeakPtr()),
- capture_device_(nil) {
+ capture_device_(nil),
+ weak_factory_(this) {
+ // Avoid reconfiguring AVFoundation or blacklisted devices.
+ final_resolution_selected_ = AVFoundationGlue::IsAVFoundationSupported() ||
+ device_name.is_blacklisted();
}
VideoCaptureDeviceMac::~VideoCaptureDeviceMac() {
}
int width = params.requested_format.frame_size.width();
int height = params.requested_format.frame_size.height();
- int frame_rate = params.requested_format.frame_rate;
+ float frame_rate = params.requested_format.frame_rate;
- // The OS API can scale captured frame to any size requested, which would lead
- // to undesired aspect ratio change. Try to open the camera with a natively
+ // QTKit API can scale captured frame to any size requested, which would lead
+ // to undesired aspect ratio changes. Try to open the camera with a known
// supported format and let the client crop/pad the captured frames.
- GetBestMatchSupportedResolution(&width, &height);
+ if (!AVFoundationGlue::IsAVFoundationSupported())
+ GetBestMatchSupportedResolution(&width, &height);
client_ = client.Pass();
+ if (device_name_.capture_api_type() == Name::AVFOUNDATION)
+ LogMessage("Using AVFoundation for device: " + device_name_.name());
+ else
+ LogMessage("Using QTKit for device: " + device_name_.name());
NSString* deviceId =
[NSString stringWithUTF8String:device_name_.id().c_str()];
capture_format_.frame_rate = frame_rate;
capture_format_.pixel_format = PIXEL_FORMAT_UYVY;
- if (width <= kVGA.width || height <= kVGA.height) {
- // If the resolution is VGA or QVGA, set the capture resolution to the
- // target size. Essentially all supported cameras offer at least VGA.
+ // QTKit: Set the capture resolution only if this is VGA or smaller, otherwise
+ // leave it unconfigured and start capturing: QTKit will produce frames at the
+ // native resolution, allowing us to identify cameras whose native resolution
+ // is too low for HD. This additional information comes at a cost in startup
+ // latency, because the webcam will need to be reopened if its default
+ // resolution is not HD or VGA.
+ // AVfoundation is configured for all resolutions.
+ if (AVFoundationGlue::IsAVFoundationSupported() || width <= kVGA.width ||
+ height <= kVGA.height) {
if (!UpdateCaptureResolution())
return;
}
- // For higher resolutions, we first open at the default resolution to find
- // out if the request is larger than the camera's native resolution.
- // If the resolution is HD, start capturing without setting a resolution.
- // QTKit will produce frames at the native resolution, allowing us to
- // identify cameras whose native resolution is too low for HD. This
- // additional information comes at a cost in startup latency, because the
- // webcam will need to be reopened if its default resolution is not HD or VGA.
+ // Try setting the power line frequency removal (anti-flicker). The built-in
+ // cameras are normally suspended so the configuration must happen right
+ // before starting capture and during configuration.
+ const std::string& device_model = device_name_.GetModel();
+ if (device_model.length() > 2 * kVidPidSize) {
+ std::string vendor_id = device_model.substr(0, kVidPidSize);
+ std::string model_id = device_model.substr(kVidPidSize + 1);
+ int vendor_id_as_int, model_id_as_int;
+ if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) &&
+ base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) {
+ SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int,
+ GetPowerLineFrequencyForLocation());
+ }
+ }
if (![capture_device_ startCapture]) {
SetErrorState("Could not start capture device.");
void VideoCaptureDeviceMac::StopAndDeAllocate() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ == kCapturing || state_ == kError) << state_;
- [capture_device_ stopCapture];
[capture_device_ setCaptureDevice:nil];
[capture_device_ setFrameReceiver:nil];
tried_to_square_pixels_ = false;
}
-bool VideoCaptureDeviceMac::Init() {
+bool VideoCaptureDeviceMac::Init(
+ VideoCaptureDevice::Name::CaptureApiType capture_api_type) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kNotInitialized);
- // TODO(mcasas): The following check might not be necessary; if the device has
- // disappeared after enumeration and before coming here, opening would just
- // fail but not necessarily produce a crash.
- Names device_names;
- GetDeviceNames(&device_names);
- Names::iterator it = device_names.begin();
- for (; it != device_names.end(); ++it) {
- if (it->id() == device_name_.id())
- break;
- }
- if (it == device_names.end())
- return false;
-
- if (AVFoundationGlue::IsAVFoundationSupported()) {
+ if (capture_api_type == Name::AVFOUNDATION) {
capture_device_ =
[[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this];
} else {
const VideoCaptureFormat& frame_format,
int aspect_numerator,
int aspect_denominator) {
- // This method is safe to call from a device capture thread,
- // i.e. any thread controlled by QTKit.
-
- if (!sent_frame_info_) {
- // Final resolution has not yet been selected.
+ // This method is safe to call from a device capture thread, i.e. any thread
+ // controlled by QTKit/AVFoundation.
+ if (!final_resolution_selected_) {
+ DCHECK(!AVFoundationGlue::IsAVFoundationSupported());
if (capture_format_.frame_size.width() > kVGA.width ||
capture_format_.frame_size.height() > kVGA.height) {
// We are requesting HD. Make sure that the picture is good, otherwise
change_to_vga = true;
}
- if (change_to_vga) {
+ if (change_to_vga)
capture_format_.frame_size.SetSize(kVGA.width, kVGA.height);
- }
}
if (capture_format_.frame_size == frame_format.frame_size &&
!tried_to_square_pixels_ &&
(aspect_numerator > kMaxPixelAspectRatio * aspect_denominator ||
aspect_denominator > kMaxPixelAspectRatio * aspect_numerator)) {
- // The requested size results in non-square PAR.
- // Shrink the frame to 1:1 PAR (assuming QTKit selects the same input
- // mode, which is not guaranteed).
+ // The requested size results in non-square PAR. Shrink the frame to 1:1
+ // PAR (assuming QTKit selects the same input mode, which is not
+ // guaranteed).
int new_width = capture_format_.frame_size.width();
int new_height = capture_format_.frame_size.height();
- if (aspect_numerator < aspect_denominator) {
+ if (aspect_numerator < aspect_denominator)
new_width = (new_width * aspect_numerator) / aspect_denominator;
- } else {
+ else
new_height = (new_height * aspect_denominator) / aspect_numerator;
- }
capture_format_.frame_size.SetSize(new_width, new_height);
tried_to_square_pixels_ = true;
}
if (capture_format_.frame_size == frame_format.frame_size) {
- sent_frame_info_ = true;
+ final_resolution_selected_ = true;
} else {
UpdateCaptureResolution();
- // OnFrameInfo has not yet been called. OnIncomingCapturedFrame must
- // not be called until after OnFrameInfo, so we return early.
+ // Let the resolution update sink through QTKit and wait for next frame.
return;
}
}
- DCHECK_EQ(capture_format_.frame_size.width(),
- frame_format.frame_size.width());
- DCHECK_EQ(capture_format_.frame_size.height(),
- frame_format.frame_size.height());
+ // QTKit capture source can change resolution if someone else reconfigures the
+ // camera, and that is fine: http://crbug.com/353620. In AVFoundation, this
+ // should not happen, it should resize internally.
+ if (!AVFoundationGlue::IsAVFoundationSupported()) {
+ capture_format_.frame_size = frame_format.frame_size;
+ } else if (capture_format_.frame_size != frame_format.frame_size) {
+ ReceiveError("Captured resolution " + frame_format.frame_size.ToString() +
+ ", and expected " + capture_format_.frame_size.ToString());
+ return;
+ }
- client_->OnIncomingCapturedFrame(video_frame,
- video_frame_length,
- base::TimeTicks::Now(),
- 0,
- capture_format_);
+ client_->OnIncomingCapturedData(video_frame,
+ video_frame_length,
+ capture_format_,
+ 0,
+ base::TimeTicks::Now());
}
void VideoCaptureDeviceMac::ReceiveError(const std::string& reason) {
task_runner_->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureDeviceMac::SetErrorState, weak_this_,
- reason));
+ base::Bind(&VideoCaptureDeviceMac::SetErrorState,
+ weak_factory_.GetWeakPtr(),
+ reason));
}
void VideoCaptureDeviceMac::SetErrorState(const std::string& reason) {
DCHECK(task_runner_->BelongsToCurrentThread());
- DLOG(ERROR) << reason;
state_ = kError;
client_->OnError(reason);
}
+void VideoCaptureDeviceMac::LogMessage(const std::string& message) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (client_)
+ client_->OnLog(message);
+}
+
bool VideoCaptureDeviceMac::UpdateCaptureResolution() {
- if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height()
- width:capture_format_.frame_size.width()
- frameRate:capture_format_.frame_rate]) {
- ReceiveError("Could not configure capture device.");
- return false;
- }
- return true;
+ if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height()
+ width:capture_format_.frame_size.width()
+ frameRate:capture_format_.frame_rate]) {
+ ReceiveError("Could not configure capture device.");
+ return false;
+ }
+ return true;
}
} // namespace media