qtkitvideosrc: implement zero-copy by using buffer-factory
authorOle André Vadla Ravnås <oravnas@cisco.com>
Thu, 4 Nov 2010 16:47:25 +0000 (17:47 +0100)
committerOle André Vadla Ravnås <oravnas@cisco.com>
Thu, 4 Nov 2010 16:52:05 +0000 (17:52 +0100)
This means we'll wrap each CoreVideo buffer inside a GstBuffer instead of
making a copy.

sys/applemedia/qtkitvideosrc.m

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