1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define DEFAULT_CAPTURE_DEVICE_INDEX    1
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define DEFAULT_FRAME_RATE              30
131fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org#define DEFAULT_FRAME_WIDTH             352
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define DEFAULT_FRAME_HEIGHT            288
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define ROTATE_CAPTURED_FRAME           1
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define LOW_QUALITY                     1
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
181fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org#import "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.h"
191fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
201fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing namespace webrtc;
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing namespace videocapturemodule;
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@implementation VideoCaptureMacQTKitObjC
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
271fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org-(id)init {
281fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  self = [super init];
291fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (self) {
301fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [self initializeVariables];
311fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
321fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  return self;
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org- (void)dealloc {
361fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (_captureSession)
371fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [_captureSession stopRunning];
380dae366146cb5c6871db85c48cfefe97c8262e5cmflodman@webrtc.org
391fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (_captureVideoDeviceInput) {
401fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    if ([[_captureVideoDeviceInput device] isOpen])
411fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [[_captureVideoDeviceInput device] close];
420dae366146cb5c6871db85c48cfefe97c8262e5cmflodman@webrtc.org
431fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [_captureVideoDeviceInput release];
441fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
450dae366146cb5c6871db85c48cfefe97c8262e5cmflodman@webrtc.org
461fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDecompressedVideoOutput release];
471fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureSession release];
481fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDevices release];
490dae366146cb5c6871db85c48cfefe97c8262e5cmflodman@webrtc.org
501fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [super dealloc];
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
531fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org#pragma mark Public methods
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
551fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (void)registerOwner:(VideoCaptureMacQTKit*)owner {
561fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [lock_ lock];
571fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _owner = owner;
581fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [lock_ unlock];
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
611fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (BOOL)setCaptureDeviceById:(char*)uniqueId {
621fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (uniqueId == nil || !strcmp("", uniqueId)) {
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVideoCapture, 0,
641fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                 "Incorrect capture id argument");
651fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
661fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
671fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
681fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (!strcmp(uniqueId, _captureDeviceNameUniqueID))
691fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return YES;
701fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
711fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  QTCaptureDevice* captureDevice;
721fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  for(int index = 0; index < _captureDeviceCount; index++) {
731fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    captureDevice = (QTCaptureDevice*)[_captureDevices objectAtIndex:index];
741fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    char captureDeviceId[1024] = "";
751fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [[captureDevice uniqueID] getCString:captureDeviceId
761fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                               maxLength:1024
771fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                                encoding:NSUTF8StringEncoding];
781fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    if (strcmp(uniqueId, captureDeviceId) == 0) {
791fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      WEBRTC_TRACE(kTraceInfo, kTraceVideoCapture, 0,
801fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                   "%s:%d Found capture device id %s as index %d",
811fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                   __FUNCTION__, __LINE__, captureDeviceId, index);
821fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [[captureDevice localizedDisplayName] getCString:_captureDeviceNameUTF8
831fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                                             maxLength:1024
841fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                                              encoding:NSUTF8StringEncoding];
851fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [[captureDevice uniqueID] getCString:_captureDeviceNameUniqueID
861fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                                 maxLength:1024
871fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                                  encoding:NSUTF8StringEncoding];
881fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      break;
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
901fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    captureDevice = nil;
911fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
921fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
931fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (!captureDevice)
941fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
951fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
961fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  NSError* error;
971fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (![captureDevice open:&error]) {
981fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceVideoCapture, 0,
991fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                 "Failed to open capture device: %s", _captureDeviceNameUTF8);
1001fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
1011fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
1021fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1031fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (_captureVideoDeviceInput) {
1041fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [_captureVideoDeviceInput release];
1051fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
1061fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureVideoDeviceInput =
1071fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [[QTCaptureDeviceInput alloc] initWithDevice:captureDevice];
1081fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1091fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (![_captureSession addInput:_captureVideoDeviceInput error:&error]) {
1101fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    WEBRTC_TRACE(kTraceError, kTraceVideoCapture, 0,
1111fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                 "Failed to add input from %s to the capture session",
1121fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                 _captureDeviceNameUTF8);
1131fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
1141fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
1151fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1161fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVideoCapture, 0,
1171fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org               "%s:%d successfully added capture device: %s", __FUNCTION__,
1181fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org               __LINE__, _captureDeviceNameUTF8);
1191fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  return YES;
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1221fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (void)setCaptureHeight:(int)height width:(int)width frameRate:(int)frameRate {
1231fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _frameWidth = width;
1241fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _frameHeight = height;
1251fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _frameRate = frameRate;
1261fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1271fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  NSDictionary* captureDictionary =
1281fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [NSDictionary dictionaryWithObjectsAndKeys:
1291fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          [NSNumber numberWithDouble:_frameWidth],
1301fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          (id)kCVPixelBufferWidthKey,
1311fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          [NSNumber numberWithDouble:_frameHeight],
1321fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          (id)kCVPixelBufferHeightKey,
1331fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB],
1341fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          (id)kCVPixelBufferPixelFormatTypeKey,
1351fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          nil];
1361fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDecompressedVideoOutput
1371fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      performSelectorOnMainThread:@selector(setPixelBufferAttributes:)
1381fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                       withObject:captureDictionary
1391fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                    waitUntilDone:YES];
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1421fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (void)startCapture {
1431fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (_capturing)
1441fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return;
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1461fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureSession startRunning];
1471fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _capturing = YES;
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1501fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (void)stopCapture {
1511fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (!_capturing)
1521fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return;
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1541fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureSession stopRunning];
1551fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _capturing = NO;
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1581fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org#pragma mark Private methods
1591fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1601fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (BOOL)initializeVariables {
1611fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (NSClassFromString(@"QTCaptureSession") == nil)
1621fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
1631fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1641fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  memset(_captureDeviceNameUTF8, 0, 1024);
1651fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _framesDelivered = 0;
1661fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _framesRendered = 0;
1671fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureDeviceCount = 0;
1681fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _capturing = NO;
1691fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureInitialized = NO;
1701fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _frameRate = DEFAULT_FRAME_RATE;
1711fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _frameWidth = DEFAULT_FRAME_WIDTH;
1721fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _frameHeight = DEFAULT_FRAME_HEIGHT;
1731fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  lock_ = [[NSLock alloc] init];
1741fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureSession = [[QTCaptureSession alloc] init];
1751fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureDecompressedVideoOutput =
1761fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [[QTCaptureDecompressedVideoOutput alloc] init];
1771fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDecompressedVideoOutput setDelegate:self];
1781fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1791fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [self getCaptureDevices];
1801fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (![self initializeVideoCapture])
1811fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
1821fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
1831fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  return NO;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1861fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (void)getCaptureDevices {
1871fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (_captureDevices)
1881fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [_captureDevices release];
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1901fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureDevices = [[NSArray alloc] initWithArray:
1911fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]];
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1931fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _captureDeviceCount = _captureDevices.count;
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1961fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (BOOL)initializeVideoCapture{
1971fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  NSDictionary *captureDictionary =
1981fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      [NSDictionary dictionaryWithObjectsAndKeys:
1991fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          [NSNumber numberWithDouble:_frameWidth],
2001fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          (id)kCVPixelBufferWidthKey,
2011fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          [NSNumber numberWithDouble:_frameHeight],
2021fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          (id)kCVPixelBufferHeightKey,
2031fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB],
2041fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          (id)kCVPixelBufferPixelFormatTypeKey,
2051fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org          nil];
2061fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
2071fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDecompressedVideoOutput setPixelBufferAttributes:captureDictionary];
2081fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDecompressedVideoOutput setAutomaticallyDropsLateVideoFrames:YES];
2091fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [_captureDecompressedVideoOutput
2101fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org      setMinimumVideoFrameInterval:(NSTimeInterval)1/(float)_frameRate];
2111fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
2121fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  NSError *error;
2131fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (![_captureSession addOutput:_captureDecompressedVideoOutput error:&error])
2141fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return NO;
2151fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
2161fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  return YES;
2171fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org}
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2191fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org- (void)captureOutput:(QTCaptureOutput *)captureOutput
2201fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    didDropVideoFrameWithSampleBuffer:(QTSampleBuffer *)sampleBuffer
2211fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                       fromConnection:(QTCaptureConnection *)connection {
2221fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  // TODO(mflodman) Experiment more when this happens.
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org- (void)captureOutput:(QTCaptureOutput *)captureOutput
2261fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  didOutputVideoFrame:(CVImageBufferRef)videoFrame
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     withSampleBuffer:(QTSampleBuffer *)sampleBuffer
2281fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org       fromConnection:(QTCaptureConnection *)connection {
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2301fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [lock_ lock];
2311fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (!_owner) {
2321fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    [lock_ unlock];
2331fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    return;
2341fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2361fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  const int kFlags = 0;
2371fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  if (CVPixelBufferLockBaseAddress(videoFrame, kFlags) == kCVReturnSuccess) {
2381fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    void *baseAddress = CVPixelBufferGetBaseAddress(videoFrame);
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoFrame);
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int frameHeight = CVPixelBufferGetHeight(videoFrame);
2411fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    int frameSize = bytesPerRow * frameHeight;
2421fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
2431fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    VideoCaptureCapability tempCaptureCapability;
2441fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    tempCaptureCapability.width = _frameWidth;
2451fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    tempCaptureCapability.height = _frameHeight;
2461fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    tempCaptureCapability.maxFPS = _frameRate;
2471fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    // TODO(wu) : Update actual type and not hard-coded value.
2481fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    tempCaptureCapability.rawType = kVideoBGRA;
2491fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org
2501fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    _owner->IncomingFrame((unsigned char*)baseAddress, frameSize,
2511fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org                          tempCaptureCapability, 0);
2521fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org    CVPixelBufferUnlockBaseAddress(videoFrame, kFlags);
2531fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  }
2541fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  [lock_ unlock];
2551fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _framesDelivered++;
2561fc08d3ea04de5616b9070115f0b66f5827de7f3mflodman@webrtc.org  _framesRendered++;
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@end
260