Chromium Code Reviews| Index: media/video/capture/mac/video_capture_device_mac_qtkit.mm |
| diff --git a/media/video/capture/mac/video_capture_device_mac_qtkit.mm b/media/video/capture/mac/video_capture_device_mac_qtkit.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7ddccc1dbfe5ea199f339d0ef13a3c78856fe99b |
| --- /dev/null |
| +++ b/media/video/capture/mac/video_capture_device_mac_qtkit.mm |
| @@ -0,0 +1,198 @@ |
| +// Copyright (c) 2011 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. |
| + |
| +#import "media/video/capture/mac/video_capture_device_mac_qtkit.h" |
| + |
| +#import <QTKit/QTKit.h> |
| + |
| +@implementation VideoCaptureDeviceMacQTKit |
| + |
| +- (id)init { |
| + if (self = [super init]) { |
| + pool_ = [[NSAutoreleasePool alloc]init]; |
|
dmac
2011/10/06 23:36:22
space between ] and init
dmac
2011/10/06 23:36:22
do you really need an autoreleasepool? please expl
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
mflodman_chromium_OOO
2011/10/07 13:03:51
Removed. One of my object-c misunderstandings.
|
| + frameRate_ = 0; |
| + frameWidth_ = 0; |
|
dmac
2011/10/06 23:36:22
no need to set things to zero/nil. This happens au
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + frameHeight_ = 0; |
| + captureSession_ = nil; |
| + captureDecompressedOutput_ = nil; |
| + captureDeviceInput_ = nil; |
| + } |
| + return self; |
| +} |
| + |
| +- (void)dealloc { |
| + if(captureSession_) { |
|
dmac
2011/10/06 23:36:22
no need to check if these are nil
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + [captureSession_ release]; |
| + captureSession_ = nil; |
| + } |
| + if (captureDecompressedOutput_) { |
| + [captureDecompressedOutput_ release]; |
| + captureDecompressedOutput_ = nil; |
| + } |
| + if (captureDeviceInput_) { |
| + [captureDeviceInput_ release]; |
| + captureDeviceInput_ = nil; |
| + } |
| + [pool_ drain]; |
| + [super dealloc]; |
| +} |
| + |
| +#pragma mark Class methods |
| + |
| ++ (void) deviceNames:(NSArray *) deviceList { |
|
dmac
2011/10/06 23:36:22
no space between ) and device (in both cases)
mflodman_chromium_OOO
2011/10/07 13:03:51
Modified.
|
| + [deviceList initWithArray:[QTCaptureDevice |
|
dmac
2011/10/06 23:36:22
This does not do what you think it does. My guess
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + inputDevicesWithMediaType:QTMediaTypeVideo]]; |
| +} |
| + |
| +#pragma mark Public methods |
| + |
| +- (void)registerReceiver:(media::VideoCaptureDeviceMac *)frameReceiver { |
|
dmac
2011/10/06 23:36:22
should this be "setFrameReceiver" since you can on
mflodman_chromium_OOO
2011/10/07 13:03:51
Good point, changed.
|
| + frameReceiver_ = frameReceiver; |
| +} |
| + |
| +- (BOOL)setCaptureDevice:(const char *)name { |
|
dmac
2011/10/06 23:36:22
so on one side of the interface you take an NSStri
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + if (captureDeviceInput_) { |
| + // A device is already set. |
| + return NO; |
| + } |
| + |
| + // Find the requested device, open it and set as input. |
| + NSArray* captureDevices; |
| + captureDevices = [[[NSArray alloc] initWithArray: |
|
dmac
2011/10/06 23:36:22
There's a couple of bugs here, but can I suggest a
mflodman_chromium_OOO
2011/10/07 13:03:51
Changed to the suggested code, almost... I changed
|
| + [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]] |
| + autorelease]; |
| + |
| + if ([captureDevices count] == 0) { |
| + return NO; |
| + } |
| + |
| + for(NSUInteger index = 0; index < captureDevices.count; ++index) { |
| + NSError* error; |
| + QTCaptureDevice* captureDevice = |
| + (QTCaptureDevice*)[captureDevices objectAtIndex:index]; |
| + |
| + char captureDeviceName[1024]; |
| + [[captureDevice localizedDisplayName] getCString:captureDeviceName |
| + maxLength:1024 |
| + encoding:NSUTF8StringEncoding]; |
| + if (!strcmp(captureDeviceName, name)) { |
| + if (![captureDevice open:&error]) { |
| + return NO; |
| + } |
| + captureDeviceInput_ = [QTCaptureDeviceInput alloc]; |
| + [captureDeviceInput_ initWithDevice:captureDevice]; |
| + captureSession_ = [[QTCaptureSession alloc] init]; |
| + captureDecompressedOutput_ = |
| + [[QTCaptureDecompressedVideoOutput alloc] init]; |
| + [captureDecompressedOutput_ setDelegate:self]; |
| + return YES; |
| + } |
| + } |
| + return NO; |
| +} |
| + |
| +- (void)removeCaptureDevice { |
| + if ([[captureSession_ inputs] count] > 0) { |
| + // The device is still running. |
| + [self stopCapture]; |
| + } |
| + if (captureDecompressedOutput_) { |
|
dmac
2011/10/06 23:36:22
no need to check. Just call release on it.
Same w
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + [captureDecompressedOutput_ release]; |
| + captureDecompressedOutput_ = nil; |
| + } |
| + if(captureSession_) { |
| + [captureSession_ release]; |
| + captureSession_ = nil; |
| + } |
| + if (captureDeviceInput_) { |
| + [captureDeviceInput_ release]; |
| + captureDeviceInput_ = nil; |
| + } |
| +} |
| + |
| +- (BOOL)setCaptureHeight:(int)height |
| + AndWidth:(int)width |
| + AndFrameRate:(int)frameRate { |
| + // Verify an input device has been set. |
| + if (!captureDeviceInput_) { |
| + return NO; |
| + } |
| + |
| + frameWidth_ = width; |
| + frameHeight_ = height; |
| + frameRate_ = frameRate; |
| + |
| + // Set up desired output properties. |
| + NSDictionary* captureDictionary = |
| + [NSDictionary dictionaryWithObjectsAndKeys: |
| + [NSNumber numberWithDouble:frameWidth_], |
| + (id)kCVPixelBufferWidthKey, |
| + [NSNumber numberWithDouble:frameHeight_], |
| + (id)kCVPixelBufferHeightKey, |
| + [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], |
| + (id)kCVPixelBufferPixelFormatTypeKey, |
| + nil]; |
| + [captureDecompressedOutput_ setPixelBufferAttributes:captureDictionary]; |
| + |
| + // Connect the output with the session. |
| + NSError* error; |
| + if (![captureSession_ addOutput:captureDecompressedOutput_ error:&error]) { |
| + return NO; |
|
dmac
2011/10/06 23:36:22
log the error?
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + } |
| + return YES; |
| +} |
| + |
| +- (BOOL)startCapture { |
| + if ([[captureSession_ outputs] count] == 0) { |
| + // Capture properties not set. |
| + return NO; |
| + } |
| + if ([[captureSession_ inputs] count] == 0) { |
| + NSError* error; |
| + if (![captureSession_ addInput:captureDeviceInput_ error:&error]) { |
| + return NO; |
|
dmac
2011/10/06 23:36:22
log the error?
mflodman_chromium_OOO
2011/10/07 13:03:51
Done.
|
| + } |
| + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]]; |
|
dmac
2011/10/06 23:36:22
what breaks out of this runloop?
mflodman_chromium_OOO
2011/10/07 13:03:51
The runloop was originally from sample, which I pr
|
| + [captureSession_ startRunning]; |
| + } |
| + return YES; |
| +} |
| + |
| +- (void)stopCapture { |
| + if ([[captureSession_ inputs] count] > 0) { |
| + [captureSession_ removeInput:captureDeviceInput_]; |
| + [captureSession_ stopRunning]; |
| + } |
| +} |
| + |
| +// |captureOutput| is called by the capture device to deliver a new frame. |
| +- (void)captureOutput:(QTCaptureOutput *)captureOutput |
| + didOutputVideoFrame:(CVImageBufferRef)videoFrame |
| + withSampleBuffer:(QTSampleBuffer *)sampleBuffer |
| + fromConnection:(QTCaptureConnection *)connection { |
| + |
| + // Lock the frame and calculate frame size. |
| + const int LOCK_FLAGS = 0; |
| + CVPixelBufferLockBaseAddress(videoFrame, LOCK_FLAGS); |
| + void* baseAddress = CVPixelBufferGetBaseAddress(videoFrame); |
| + size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoFrame); |
| + int frameHeight = CVPixelBufferGetHeight(videoFrame); |
| + |
| + if(frameReceiver_) { |
|
dmac
2011/10/06 23:36:22
do you want to check frameReceiver_ before doing a
mflodman_chromium_OOO
2011/10/07 13:03:51
Good point, changed.
|
| + int frameSize = bytesPerRow * frameHeight; |
| + CVBufferRetain(videoFrame); |
|
dmac
2011/10/06 23:36:22
why do feel you need to retain and release the vid
mflodman_chromium_OOO
2011/10/07 13:03:51
It was to make sure videoFrame was valid during th
|
| + media::VideoCaptureDevice::Capability captureCapability; |
| + captureCapability.width = frameWidth_; |
| + captureCapability.height = frameHeight_; |
| + captureCapability.frame_rate = frameRate_; |
| + captureCapability.color = media::VideoCaptureDevice::kARGB; |
| + |
| + frameReceiver_->IncomingFrame(baseAddress, frameSize, captureCapability); |
| + |
| + CVBufferRelease(videoFrame); |
| + } |
| + CVPixelBufferUnlockBaseAddress(videoFrame, LOCK_FLAGS); |
| +} |
| + |
| +@end |