qtkitvideosrc: implement zero-copy by using buffer-factory

This means we'll wrap each CoreVideo buffer inside a GstBuffer instead of
making a copy.
This commit is contained in:
Ole André Vadla Ravnås 2010-11-04 17:47:25 +01:00
parent 835b2988b6
commit 86e2539816

View file

@ -19,6 +19,8 @@
#include "qtkitvideosrc.h" #include "qtkitvideosrc.h"
#import "bufferfactory.h"
#import <QTKit/QTKit.h> #import <QTKit/QTKit.h>
#define DEFAULT_DEVICE_INDEX -1 #define DEFAULT_DEVICE_INDEX -1
@ -100,6 +102,7 @@ static GstPushSrcClass * parent_class;
int deviceIndex; int deviceIndex;
GstAMBufferFactory *bufferFactory;
QTCaptureSession *session; QTCaptureSession *session;
QTCaptureDeviceInput *input; QTCaptureDeviceInput *input;
QTCaptureDecompressedVideoOutput *output; QTCaptureDecompressedVideoOutput *output;
@ -166,24 +169,31 @@ static GstPushSrcClass * parent_class;
- (BOOL)openDevice - (BOOL)openDevice
{ {
NSString *mediaType; GError *gerror;
NSString *mediaType = QTMediaTypeVideo;
NSError *error = nil; NSError *error = nil;
mediaType = QTMediaTypeVideo; bufferFactory = [[GstAMBufferFactory alloc] initWithError:&gerror];
if (bufferFactory == nil) {
GST_ELEMENT_ERROR (element, RESOURCE, FAILED, ("API error"),
("%s", gerror->message));
g_clear_error (&gerror);
goto openFailed;
}
if (deviceIndex == -1) { if (deviceIndex == -1) {
device = [QTCaptureDevice defaultInputDeviceWithMediaType:mediaType]; device = [QTCaptureDevice defaultInputDeviceWithMediaType:mediaType];
if (device == nil) { if (device == nil) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND,
("No video capture devices found"), (NULL)); ("No video capture devices found"), (NULL));
return NO; goto openFailed;
} }
} else { } else {
NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:mediaType]; NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:mediaType];
if (deviceIndex >= [devices count]) { if (deviceIndex >= [devices count]) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND,
("Invalid video capture device index"), (NULL)); ("Invalid video capture device index"), (NULL));
return NO; goto openFailed;
} }
device = [devices objectAtIndex:deviceIndex]; device = [devices objectAtIndex:deviceIndex];
} }
@ -195,12 +205,22 @@ static GstPushSrcClass * parent_class;
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND,
("Failed to open device '%s'", ("Failed to open device '%s'",
[[device localizedDisplayName] UTF8String]), (NULL)); [[device localizedDisplayName] UTF8String]), (NULL));
[device release]; goto openFailed;
device = nil;
return NO;
} }
return YES; return YES;
/* ERRORS */
openFailed:
{
[device release];
device = nil;
[bufferFactory release];
bufferFactory = nil;
return NO;
}
} }
- (void)closeDevice - (void)closeDevice
@ -218,6 +238,9 @@ static GstPushSrcClass * parent_class;
[device release]; [device release];
device = nil; device = nil;
[bufferFactory release];
bufferFactory = nil;
} }
- (BOOL)setCaps:(GstCaps *)caps - (BOOL)setCaps:(GstCaps *)caps
@ -383,12 +406,7 @@ static GstPushSrcClass * parent_class;
[queueLock unlockWithCondition: [queueLock unlockWithCondition:
([queue count] == 0) ? NO_FRAMES : HAS_FRAME_OR_STOP_REQUEST]; ([queue count] == 0) ? NO_FRAMES : HAS_FRAME_OR_STOP_REQUEST];
*buf = gst_buffer_new_and_alloc ( *buf = [bufferFactory createGstBufferForCoreVideoBuffer:frame];
CVPixelBufferGetBytesPerRow (frame) * CVPixelBufferGetHeight (frame));
CVPixelBufferLockBaseAddress (frame, 0);
memcpy (GST_BUFFER_DATA (*buf), CVPixelBufferGetBaseAddress (frame),
GST_BUFFER_SIZE (*buf));
CVPixelBufferUnlockBaseAddress (frame, 0);
CVBufferRelease (frame); CVBufferRelease (frame);
[self timestampBuffer:*buf]; [self timestampBuffer:*buf];