lavd/avfoundation: Split adding a device and getting the device configuration into...
authorThilo Borgmann <thilo.borgmann@mail.de>
Wed, 24 Sep 2014 10:16:31 +0000 (12:16 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 26 Sep 2014 02:18:24 +0000 (04:18 +0200)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavdevice/avfoundation.m

index 4ac50a0..895bd29 100644 (file)
@@ -172,99 +172,23 @@ static void destroy_context(AVFContext* ctx)
     }
 }
 
-static int avf_read_header(AVFormatContext *s)
+static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    AVFContext *ctx         = (AVFContext*)s->priv_data;
-    ctx->first_pts          = av_gettime();
-
-    pthread_mutex_init(&ctx->frame_lock, NULL);
-    pthread_cond_init(&ctx->frame_wait_cond, NULL);
-
-    // List devices if requested
-    if (ctx->list_devices) {
-        av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n");
-        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
-        for (AVCaptureDevice *device in devices) {
-            const char *name = [[device localizedName] UTF8String];
-            int index  = [devices indexOfObject:device];
-            av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
-        }
-        goto fail;
-    }
-
-    // Find capture device
-    AVCaptureDevice *video_device = nil;
-
-    // check for device index given in filename
-    if (ctx->video_device_index == -1) {
-        sscanf(s->filename, "%d", &ctx->video_device_index);
-    }
-
-    if (ctx->video_device_index >= 0) {
-        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
-
-        if (ctx->video_device_index >= [devices count]) {
-            av_log(ctx, AV_LOG_ERROR, "Invalid device index\n");
-            goto fail;
-        }
-
-        video_device = [devices objectAtIndex:ctx->video_device_index];
-    } else if (strncmp(s->filename, "",        1) &&
-               strncmp(s->filename, "default", 7)) {
-        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
-
-        for (AVCaptureDevice *device in devices) {
-            if (!strncmp(s->filename, [[device localizedName] UTF8String], strlen(s->filename))) {
-                video_device = device;
-                break;
-            }
-        }
-
-        if (!video_device) {
-            av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
-            goto fail;
-        }
-    } else {
-        video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeMuxed];
-    }
-
-    // Video capture device not found, looking for AVMediaTypeVideo
-    if (!video_device) {
-        video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
-
-        if (!video_device) {
-            av_log(s, AV_LOG_ERROR, "No AV capture device found\n");
-            goto fail;
-        }
-    }
-
-    NSString* dev_display_name = [video_device localizedName];
-    av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [dev_display_name UTF8String]);
-
-    // Initialize capture session
-    ctx->capture_session = [[AVCaptureSession alloc] init];
-
-    NSError *error = nil;
+    AVFContext *ctx = (AVFContext*)s->priv_data;
+    NSError *error  = nil;
     AVCaptureDeviceInput* capture_dev_input = [[[AVCaptureDeviceInput alloc] initWithDevice:video_device error:&error] autorelease];
 
     if (!capture_dev_input) {
         av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
                [[error localizedDescription] UTF8String]);
-        goto fail;
-    }
-
-    if (!capture_dev_input) {
-        av_log(s, AV_LOG_ERROR, "Failed to add AV capture input device to session: %s\n",
-               [[error localizedDescription] UTF8String]);
-        goto fail;
+        return 1;
     }
 
     if ([ctx->capture_session canAddInput:capture_dev_input]) {
         [ctx->capture_session addInput:capture_dev_input];
     } else {
         av_log(s, AV_LOG_ERROR, "can't add video input to capture session\n");
-        goto fail;
+        return 1;
     }
 
     // Attaching output
@@ -272,7 +196,7 @@ static int avf_read_header(AVFormatContext *s)
 
     if (!ctx->video_output) {
         av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
-        goto fail;
+        return 1;
     }
 
     // select pixel format
@@ -290,7 +214,7 @@ static int avf_read_header(AVFormatContext *s)
     if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
         av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by AVFoundation.\n",
                av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
-        goto fail;
+        return 1;
     }
 
     // check if the pixel format is available for this device
@@ -323,14 +247,14 @@ static int avf_read_header(AVFormatContext *s)
 
         // fail if there is no appropriate pixel format or print a warning about overriding the pixel format
         if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
-            goto fail;
+            return 1;
         } else {
             av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n",
                    av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
         }
     }
 
-
+    ctx->pixel_format          = pxl_fmt_spec.ff_id;
     NSNumber     *pixel_format = [NSNumber numberWithUnsignedInt:pxl_fmt_spec.avf_id];
     NSDictionary *capture_dict = [NSDictionary dictionaryWithObject:pixel_format
                                                forKey:(id)kCVPixelBufferPixelFormatTypeKey];
@@ -348,10 +272,15 @@ static int avf_read_header(AVFormatContext *s)
         [ctx->capture_session addOutput:ctx->video_output];
     } else {
         av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n");
-        goto fail;
+        return 1;
     }
 
-    [ctx->capture_session startRunning];
+    return 0;
+}
+
+static int get_video_config(AVFormatContext *s)
+{
+    AVFContext *ctx = (AVFContext*)s->priv_data;
 
     // Take stream info from the first frame.
     while (ctx->frames_captured < 1) {
@@ -363,7 +292,7 @@ static int avf_read_header(AVFormatContext *s)
     AVStream* stream = avformat_new_stream(s, NULL);
 
     if (!stream) {
-        goto fail;
+        return 1;
     }
 
     avpriv_set_pts_info(stream, 64, 1, avf_time_base);
@@ -375,12 +304,99 @@ static int avf_read_header(AVFormatContext *s)
     stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
     stream->codec->width      = (int)image_buffer_size.width;
     stream->codec->height     = (int)image_buffer_size.height;
-    stream->codec->pix_fmt    = pxl_fmt_spec.ff_id;
+    stream->codec->pix_fmt    = ctx->pixel_format;
 
     CFRelease(ctx->current_frame);
     ctx->current_frame = nil;
 
     unlock_frames(ctx);
+
+    return 0;
+}
+
+static int avf_read_header(AVFormatContext *s)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    AVFContext *ctx         = (AVFContext*)s->priv_data;
+    ctx->first_pts          = av_gettime();
+
+    pthread_mutex_init(&ctx->frame_lock, NULL);
+    pthread_cond_init(&ctx->frame_wait_cond, NULL);
+
+    // List devices if requested
+    if (ctx->list_devices) {
+        av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n");
+        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+        for (AVCaptureDevice *device in devices) {
+            const char *name = [[device localizedName] UTF8String];
+            int index  = [devices indexOfObject:device];
+            av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
+        }
+        goto fail;
+    }
+
+    // Find capture device
+    AVCaptureDevice *video_device = nil;
+
+    // check for device index given in filename
+    if (ctx->video_device_index == -1) {
+        sscanf(s->filename, "%d", &ctx->video_device_index);
+    }
+
+    if (ctx->video_device_index >= 0) {
+        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+
+        if (ctx->video_device_index >= [devices count]) {
+            av_log(ctx, AV_LOG_ERROR, "Invalid device index\n");
+            goto fail;
+        }
+
+        video_device = [devices objectAtIndex:ctx->video_device_index];
+    } else if (strncmp(s->filename, "",        1) &&
+               strncmp(s->filename, "default", 7)) {
+        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+
+        for (AVCaptureDevice *device in devices) {
+            if (!strncmp(s->filename, [[device localizedName] UTF8String], strlen(s->filename))) {
+                video_device = device;
+                break;
+            }
+        }
+
+        if (!video_device) {
+            av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
+            goto fail;
+        }
+    } else {
+        video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+    }
+
+    // Video capture device not found, looking for AVMediaTypeVideo
+    if (!video_device) {
+        video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+
+        if (!video_device) {
+            av_log(s, AV_LOG_ERROR, "No AV capture device found\n");
+            goto fail;
+        }
+    }
+
+    NSString* dev_display_name = [video_device localizedName];
+    av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [dev_display_name UTF8String]);
+
+    // Initialize capture session
+    ctx->capture_session = [[AVCaptureSession alloc] init];
+
+    if (add_video_device(s, video_device)) {
+        goto fail;
+    }
+
+    [ctx->capture_session startRunning];
+
+    if (get_video_config(s)) {
+        goto fail;
+    }
+
     [pool release];
     return 0;