blob: 53e9db7770b0fd96aac6682af96e892de45285e6 [file] [log] [blame]
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#define DEFAULT_CAPTURE_DEVICE_INDEX 1
#define DEFAULT_FRAME_RATE 30
#define DEFAULT_FRAME_WIDTH 352
#define DEFAULT_FRAME_HEIGHT 288
#define ROTATE_CAPTURED_FRAME 1
#define LOW_QUALITY 1
#import "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.h"
#include "webrtc/system_wrappers/include/trace.h"
using namespace webrtc;
using namespace videocapturemodule;
@implementation VideoCaptureMacQTKitObjC
-(id)init {
self = [super init];
if (self) {
[self initializeVariables];
}
return self;
}
- (void)dealloc {
if (_captureSession)
[_captureSession stopRunning];
if (_captureVideoDeviceInput) {
if ([[_captureVideoDeviceInput device] isOpen])
[[_captureVideoDeviceInput device] close];
[_captureVideoDeviceInput release];
}
[_captureDecompressedVideoOutput release];
[_captureSession release];
[_captureDevices release];
[_lock release];
[super dealloc];
}
#pragma mark Public methods
- (void)registerOwner:(VideoCaptureMacQTKit*)owner {
[_lock lock];
_owner = owner;
[_lock unlock];
}
- (BOOL)setCaptureDeviceById:(char*)uniqueId {
if (uniqueId == nil || !strcmp("", uniqueId)) {
WEBRTC_TRACE(kTraceInfo, kTraceVideoCapture, 0,
"Incorrect capture id argument");
return NO;
}
if (!strcmp(uniqueId, _captureDeviceNameUniqueID))
return YES;
QTCaptureDevice* captureDevice;
for(int index = 0; index < _captureDeviceCount; index++) {
captureDevice = (QTCaptureDevice*)[_captureDevices objectAtIndex:index];
char captureDeviceId[1024] = "";
[[captureDevice uniqueID] getCString:captureDeviceId
maxLength:1024
encoding:NSUTF8StringEncoding];
if (strcmp(uniqueId, captureDeviceId) == 0) {
WEBRTC_TRACE(kTraceInfo, kTraceVideoCapture, 0,
"%s:%d Found capture device id %s as index %d",
__FUNCTION__, __LINE__, captureDeviceId, index);
[[captureDevice localizedDisplayName] getCString:_captureDeviceNameUTF8
maxLength:1024
encoding:NSUTF8StringEncoding];
[[captureDevice uniqueID] getCString:_captureDeviceNameUniqueID
maxLength:1024
encoding:NSUTF8StringEncoding];
break;
}
captureDevice = nil;
}
if (!captureDevice)
return NO;
NSError* error;
if (![captureDevice open:&error]) {
WEBRTC_TRACE(kTraceError, kTraceVideoCapture, 0,
"Failed to open capture device: %s", _captureDeviceNameUTF8);
return NO;
}
if (_captureVideoDeviceInput) {
[_captureVideoDeviceInput release];
}
_captureVideoDeviceInput =
[[QTCaptureDeviceInput alloc] initWithDevice:captureDevice];
if (![_captureSession addInput:_captureVideoDeviceInput error:&error]) {
WEBRTC_TRACE(kTraceError, kTraceVideoCapture, 0,
"Failed to add input from %s to the capture session",
_captureDeviceNameUTF8);
return NO;
}
WEBRTC_TRACE(kTraceInfo, kTraceVideoCapture, 0,
"%s:%d successfully added capture device: %s", __FUNCTION__,
__LINE__, _captureDeviceNameUTF8);
return YES;
}
- (void)setCaptureHeight:(int)height width:(int)width frameRate:(int)frameRate {
_frameWidth = width;
_frameHeight = height;
_frameRate = frameRate;
NSDictionary* captureDictionary =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:_frameWidth],
(id)kCVPixelBufferWidthKey,
[NSNumber numberWithDouble:_frameHeight],
(id)kCVPixelBufferHeightKey,
[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB],
(id)kCVPixelBufferPixelFormatTypeKey,
nil];
[_captureDecompressedVideoOutput
performSelectorOnMainThread:@selector(setPixelBufferAttributes:)
withObject:captureDictionary
waitUntilDone:YES];
}
- (void)startCapture {
if (_capturing)
return;
[_captureSession startRunning];
_capturing = YES;
}
- (void)stopCapture {
if (!_capturing)
return;
[_captureSession stopRunning];
_capturing = NO;
}
#pragma mark Private methods
- (BOOL)initializeVariables {
if (NSClassFromString(@"QTCaptureSession") == nil)
return NO;
memset(_captureDeviceNameUTF8, 0, 1024);
_framesDelivered = 0;
_framesRendered = 0;
_captureDeviceCount = 0;
_capturing = NO;
_captureInitialized = NO;
_frameRate = DEFAULT_FRAME_RATE;
_frameWidth = DEFAULT_FRAME_WIDTH;
_frameHeight = DEFAULT_FRAME_HEIGHT;
_lock = [[NSLock alloc] init];
_captureSession = [[QTCaptureSession alloc] init];
_captureDecompressedVideoOutput =
[[QTCaptureDecompressedVideoOutput alloc] init];
[_captureDecompressedVideoOutput setDelegate:self];
[self getCaptureDevices];
if (![self initializeVideoCapture])
return NO;
return NO;
}
- (void)getCaptureDevices {
if (_captureDevices)
[_captureDevices release];
_captureDevices = [[NSArray alloc] initWithArray:
[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]];
_captureDeviceCount = _captureDevices.count;
}
- (BOOL)initializeVideoCapture{
NSDictionary *captureDictionary =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:_frameWidth],
(id)kCVPixelBufferWidthKey,
[NSNumber numberWithDouble:_frameHeight],
(id)kCVPixelBufferHeightKey,
[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB],
(id)kCVPixelBufferPixelFormatTypeKey,
nil];
[_captureDecompressedVideoOutput setPixelBufferAttributes:captureDictionary];
[_captureDecompressedVideoOutput setAutomaticallyDropsLateVideoFrames:YES];
[_captureDecompressedVideoOutput
setMinimumVideoFrameInterval:(NSTimeInterval)1/(float)_frameRate];
NSError *error;
if (![_captureSession addOutput:_captureDecompressedVideoOutput error:&error])
return NO;
return YES;
}
- (void)captureOutput:(QTCaptureOutput *)captureOutput
didDropVideoFrameWithSampleBuffer:(QTSampleBuffer *)sampleBuffer
fromConnection:(QTCaptureConnection *)connection {
}
- (void)captureOutput:(QTCaptureOutput *)captureOutput
didOutputVideoFrame:(CVImageBufferRef)videoFrame
withSampleBuffer:(QTSampleBuffer *)sampleBuffer
fromConnection:(QTCaptureConnection *)connection {
[_lock lock];
if (!_owner) {
[_lock unlock];
return;
}
const int kFlags = 0;
if (CVPixelBufferLockBaseAddress(videoFrame, kFlags) == kCVReturnSuccess) {
void *baseAddress = CVPixelBufferGetBaseAddress(videoFrame);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoFrame);
size_t frameHeight = CVPixelBufferGetHeight(videoFrame);
size_t frameSize = bytesPerRow * frameHeight;
VideoCaptureCapability tempCaptureCapability;
tempCaptureCapability.width = _frameWidth;
tempCaptureCapability.height = _frameHeight;
tempCaptureCapability.maxFPS = _frameRate;
// TODO(wu) : Update actual type and not hard-coded value.
tempCaptureCapability.rawType = kVideoBGRA;
_owner->IncomingFrame((unsigned char*)baseAddress, frameSize,
tempCaptureCapability, 0);
CVPixelBufferUnlockBaseAddress(videoFrame, kFlags);
}
[_lock unlock];
_framesDelivered++;
_framesRendered++;
}
@end