blob: 0bb14a79b70ba670803f09c115108d4a6200db1b [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/video/capture/mac/video_capture_device_mac.h"
#import <QTKit/QTKit.h>
#include "base/logging.h"
#include "base/time.h"
#include "media/video/capture/mac/video_capture_device_qtkit_mac.h"
namespace {
const int kMinFrameRate = 1;
const int kMaxFrameRate = 30;
}
namespace media {
void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
// Loop through all available devices and add to |device_names|.
device_names->clear();
NSDictionary* capture_devices = [VideoCaptureDeviceQTKit deviceNames];
for (NSString* key in capture_devices) {
Name name;
name.device_name = [[capture_devices valueForKey:key] UTF8String];
name.unique_id = [key UTF8String];
device_names->push_back(name);
}
}
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),
observer_(NULL),
state_(kNotInitialized),
capture_device_(nil) {
}
VideoCaptureDeviceMac::~VideoCaptureDeviceMac() {
[capture_device_ release];
}
void VideoCaptureDeviceMac::Allocate(int width, int height, int frame_rate,
EventHandler* observer) {
if (state_ != kIdle) {
return;
}
observer_ = observer;
NSString* deviceId =
[NSString stringWithUTF8String:device_name_.unique_id.c_str()];
[capture_device_ setFrameReceiver:this];
if (![capture_device_ setCaptureDevice:deviceId]) {
SetErrorState("Could not open capture device.");
return;
}
if (frame_rate < kMinFrameRate)
frame_rate = kMinFrameRate;
else if (frame_rate > kMaxFrameRate)
frame_rate = kMaxFrameRate;
if (![capture_device_ setCaptureHeight:height
width:width
frameRate:frame_rate]) {
SetErrorState("Could not configure capture device.");
return;
}
state_ = kAllocated;
VideoCaptureCapability current_settings;
current_settings.color = VideoCaptureCapability::kARGB;
current_settings.width = width;
current_settings.height = height;
current_settings.frame_rate = frame_rate;
current_settings.expected_capture_delay = 0;
current_settings.interlaced = false;
observer_->OnFrameInfo(current_settings);
}
void VideoCaptureDeviceMac::Start() {
DCHECK_EQ(state_, kAllocated);
if (![capture_device_ startCapture]) {
SetErrorState("Could not start capture device.");
return;
}
state_ = kCapturing;
}
void VideoCaptureDeviceMac::Stop() {
DCHECK_EQ(state_, kCapturing);
[capture_device_ stopCapture];
state_ = kAllocated;
}
void VideoCaptureDeviceMac::DeAllocate() {
if (state_ != kAllocated && state_ != kCapturing) {
return;
}
if (state_ == kCapturing) {
[capture_device_ stopCapture];
}
[capture_device_ setCaptureDevice:nil];
[capture_device_ setFrameReceiver:nil];
state_ = kIdle;
}
const VideoCaptureDevice::Name& VideoCaptureDeviceMac::device_name() {
return device_name_;
}
bool VideoCaptureDeviceMac::Init() {
DCHECK_EQ(state_, kNotInitialized);
Names device_names;
GetDeviceNames(&device_names);
for (Names::iterator it = device_names.begin();
it != device_names.end();
++it) {
if (device_name_.unique_id == it->unique_id) {
capture_device_ =
[[VideoCaptureDeviceQTKit alloc] initWithFrameReceiver:this];
if (!capture_device_) {
return false;
}
state_ = kIdle;
return true;
}
}
return false;
}
void VideoCaptureDeviceMac::ReceiveFrame(
const uint8* video_frame,
int video_frame_length,
const VideoCaptureCapability& frame_info) {
observer_->OnIncomingCapturedFrame(video_frame, video_frame_length,
base::Time::Now());
}
void VideoCaptureDeviceMac::SetErrorState(const std::string& reason) {
DLOG(ERROR) << reason;
state_ = kError;
observer_->OnError();
}
} // namespace media