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 |