| Index: webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.mm
|
| diff --git a/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.mm b/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..53e9db7770b0fd96aac6682af96e892de45285e6
|
| --- /dev/null
|
| +++ b/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.mm
|
| @@ -0,0 +1,259 @@
|
| +/*
|
| + * 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
|
|
|