From: Luca Barbato <[email protected]>

- renaming
- refactor
---
 configure                      |   2 +-
 libavdevice/avfoundation_dec.m | 221 ++++++++++++++++++++++-------------------
 2 files changed, 119 insertions(+), 104 deletions(-)

diff --git a/configure b/configure
index 7bdc523..e371e54 100755
--- a/configure
+++ b/configure
@@ -4561,7 +4561,7 @@ check_struct linux/videodev2.h "struct v4l2_frmivalenum" 
discrete
 
 check_header AVFoundation/AVFoundation.h &&
     check_objcflags -fobjc-arc &&
-    add_extralibs -framework Foundation -framework AVFoundation || \
+    add_extralibs -framework Foundation -framework AVFoundation -framework 
CoreMedia || \
     disable AVFoundation_AVFoundation_h
 
 check_header sys/videoio.h
diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m
index 7bac610..c5ec320 100644
--- a/libavdevice/avfoundation_dec.m
+++ b/libavdevice/avfoundation_dec.m
@@ -33,12 +33,12 @@
 
 #include "avdevice.h"
 
-struct AVFPixelFormatSpec {
-    enum AVPixelFormat ff_id;
-    OSType avf_id;
+struct AVPixelFormatMap {
+    enum AVPixelFormat pix_fmt;
+    OSType core_video_fmt;
 };
 
-static const struct AVFPixelFormatSpec avf_pixel_formats[] = {
+static const struct AVPixelFormatMap pixel_format_map[] = {
     { AV_PIX_FMT_MONOBLACK,    kCVPixelFormatType_1Monochrome },
     { AV_PIX_FMT_RGB555BE,     kCVPixelFormatType_16BE555 },
     { AV_PIX_FMT_RGB555LE,     kCVPixelFormatType_16LE555 },
@@ -67,24 +67,44 @@ static const struct AVFPixelFormatSpec avf_pixel_formats[] 
= {
     { AV_PIX_FMT_NONE, 0 }
 };
 
-typedef struct AVFoundationCaptureContext {
-    AVClass         *class;
-    int             list_devices;
+static enum AVPixelFormat core_video_to_pix_fmt(OSType core_video_fmt)
+{
+    int i;
+    for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
+         if (core_video_fmt == pixel_format_map[i].core_video_fmt)
+             return pixel_format_map[i].pix_fmt;
+    }
+    return AV_PIX_FMT_NONE;
+}
 
+static OSType pix_fmt_to_core_video(enum AVPixelFormat pix_fmt)
+{
+    int i;
+    for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
+         if (pix_fmt == pixel_format_map[i].pix_fmt)
+             return pixel_format_map[i].core_video_fmt;
+    }
+    return 0;
+}
+
+typedef struct AVFoundationCaptureContext {
+    AVClass *class;
+    /* AVOptions */
+    int list_devices;
     enum AVPixelFormat pixel_format;
 
-    int             video_stream_index;
+    int video_stream_index;
 
-    int64_t         first_pts;
-    int             frames_captured;
+    int64_t first_pts;
+    int frames_captured;
     pthread_mutex_t frame_lock;
-    pthread_cond_t  frame_wait_cond;
-
-    CFTypeRef           session;         /** AVCaptureSession*/
-    CFTypeRef           video_delegate;  /** AVFFrameReceiver */
-    CFTypeRef           video_output;    /** AVCaptureVideoDataOutput */
-    CVImageBufferRef    current_frame;   /** CVImageBufferRef */
+    pthread_cond_t frame_wait_cond;
 
+    /* ARC-compatible pointers to ObjC objects */
+    CFTypeRef session;                  /* AVCaptureSession */
+    CFTypeRef video_output;
+    CFTypeRef video_delegate;
+    CVImageBufferRef current_frame;
 } AVFoundationCaptureContext;
 
 #define AUDIO_DEVICES 1
@@ -142,9 +162,7 @@ static void unlock_frames(AVFoundationCaptureContext* ctx)
     pthread_mutex_unlock(&ctx->frame_lock);
 }
 
-/** FrameReceiver class - delegate for AVCaptureSession
- */
-@interface AVFFrameReceiver : NSObject 
<AVCaptureVideoDataOutputSampleBufferDelegate>
+@interface VideoCapture : NSObject 
<AVCaptureVideoDataOutputSampleBufferDelegate>
 {
     AVFoundationCaptureContext* _context;
 }
@@ -157,7 +175,7 @@ static void unlock_frames(AVFoundationCaptureContext* ctx)
 
 @end
 
-@implementation AVFFrameReceiver
+@implementation VideoCapture
 
 - (id)initWithContext:(AVFoundationCaptureContext*)context
 {
@@ -188,12 +206,9 @@ static void unlock_frames(AVFoundationCaptureContext* ctx)
 
 @end
 
-// Remove '[]' from the device name
-NSString *pat = @"(?<=\\[).*?(?=\\])";
-
 static int setup_stream(AVFormatContext *s, AVCaptureDevice *device)
 {
-    NSLog(@"setting up stream for device %@ ID\n", [device uniqueID]);
+    av_log(s, AV_LOG_INFO, "Setting up stream for device %s\n", [[device 
uniqueID] UTF8String]);
 
     AVFoundationCaptureContext *ctx = s->priv_data;
     NSError *__autoreleasing error = nil;
@@ -217,8 +232,9 @@ static int setup_stream(AVFormatContext *s, AVCaptureDevice 
*device)
 
     // add the output devices
     if ([device hasMediaType:AVMediaTypeVideo]) {
-
         AVCaptureVideoDataOutput* out = [[AVCaptureVideoDataOutput alloc] 
init];
+        NSNumber *core_video_fmt = nil;
+        enum AVPixelFormat pixel_format;
         if (!out) {
             av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
             return -1;
@@ -226,61 +242,45 @@ static int setup_stream(AVFormatContext *s, 
AVCaptureDevice *device)
 
         [out setAlwaysDiscardsLateVideoFrames:YES];
 
-
-        // select pixel format
-        struct AVFPixelFormatSpec pxl_fmt_spec;
-        pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
-
-        av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
-        for (NSNumber *pxl_fmt in [out availableVideoCVPixelFormatTypes]) {
-            struct AVFPixelFormatSpec pxl_fmt_dummy;
-            pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
-            for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; 
i++) {
-                if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) {
-                    pxl_fmt_dummy = avf_pixel_formats[i];
-                    break;
-                }
-            }
-
-            if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
-                av_log(s, AV_LOG_ERROR, "  %s: %d \n", 
av_get_pix_fmt_name(pxl_fmt_dummy.ff_id),
-                                                    pxl_fmt_dummy.avf_id);
-
-                // select first supported pixel format instead of user 
selected (or default) pixel format
-                if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
-                    pxl_fmt_spec = pxl_fmt_dummy;
-                }
+        // Map the first supported pixel format
+        av_log(s, AV_LOG_VERBOSE, "Supported pixel formats:\n");
+        for (NSNumber *cv_pixel_format in [out 
availableVideoCVPixelFormatTypes]) {
+            OSType cv_fmt = [cv_pixel_format intValue];
+            enum AVPixelFormat pix_fmt = core_video_to_pix_fmt(cv_fmt);
+            if (pix_fmt != AV_PIX_FMT_NONE) {
+                av_log(s, AV_LOG_VERBOSE, "  %s: %d\n",
+                       av_get_pix_fmt_name(pix_fmt),
+                       cv_fmt);
+                core_video_fmt = cv_pixel_format;
+                pixel_format   = pix_fmt;
             }
         }
 
         // 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) {
+        if (!core_video_fmt) {
             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));
+            av_log(s, AV_LOG_INFO, "Using %s.\n",
+                   av_get_pix_fmt_name(pixel_format));
         }
-        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];
+        ctx->pixel_format          = pixel_format;
+        NSDictionary *capture_dict = [NSDictionary 
dictionaryWithObject:core_video_fmt
+                                                                 
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
         [out setVideoSettings:capture_dict];
 
-        AVFFrameReceiver* delegate = [[AVFFrameReceiver alloc] 
initWithContext:ctx];
+        VideoCapture *delegate = [[VideoCapture alloc] initWithContext:ctx];
 
         dispatch_queue_t queue = dispatch_queue_create("avf_queue", NULL);
         [out setSampleBufferDelegate:delegate queue:queue];
 
-        ctx->video_delegate = (__bridge_retained CFTypeRef) delegate;
-
         if ([session canAddOutput:out]) {
             [session addOutput:out];
-            ctx->video_output = (__bridge_retained CFTypeRef) out;
+            ctx->video_output   = (__bridge_retained CFTypeRef) out;
+            ctx->video_delegate = (__bridge_retained CFTypeRef) delegate;
         } else {
             av_log(s, AV_LOG_ERROR, "can't add video output to capture 
session\n");
             return -1;
         }
-        NSLog(@"%@", device);
     }
 
     return 0;
@@ -329,8 +329,6 @@ static int get_video_config(AVFormatContext *s)
 
 static void destroy_context(AVFoundationCaptureContext* ctx)
 {
-    NSLog(@"Destroying context");
-
     AVCaptureSession *session = (__bridge AVCaptureSession*)ctx->session;
     [session stopRunning];
 
@@ -349,65 +347,82 @@ static int setup_default_stream(AVFormatContext *s)
     AVCaptureDevice *device;
     for (NSString *type in @[AVMediaTypeVideo]) {
         device = [AVCaptureDevice defaultDeviceWithMediaType:type];
-        if (device)
+        if (device) {
+            av_log(s, AV_LOG_INFO, "Using default device %s\n",
+                 [[device uniqueID] UTF8String]);
             return setup_stream(s, device);
+        }
     }
 
     return -1;
 }
 
+static AVCaptureDevice* create_device(AVFormatContext *s)
+{
+    NSString* filename;
+    NSError* __autoreleasing error = nil;
+    NSRegularExpression *exp;
+    NSArray* matches;
+    AVCaptureDevice* device;
+
+    filename = [NSString stringWithFormat:@"%s", s->filename];
+
+    if ((device = [AVCaptureDevice deviceWithUniqueID:filename])) {
+        av_log(s, AV_LOG_INFO, "Device with name %s found\n",[filename 
UTF8String]);
+        return device;
+    }
+
+    // Remove '[]' from the device name
+    NSString *pat = @"(?<=\\[).*?(?=\\])";
+    exp = [NSRegularExpression regularExpressionWithPattern:pat
+                                                    options:0
+                                                      error:&error];
+    if (!exp) {
+        av_log(s, AV_LOG_ERROR, "%s\n",
+               [[error localizedDescription] UTF8String]);
+        return NULL;
+    }
+
+    av_log(s, AV_LOG_INFO, "device name: %s\n",[filename UTF8String]);
+
+    matches = [exp matchesInString:filename options:0
+                             range:NSMakeRange(0, [filename length])];
+
+    if (matches.count > 0) {
+        for (NSTextCheckingResult *match in matches) {
+            NSRange range = [match rangeAtIndex:0];
+            NSString *uniqueID = [filename 
substringWithRange:NSMakeRange(range.location, range.length)];
+            av_log(s, AV_LOG_INFO, "opening device with ID: %s\n", [uniqueID 
UTF8String]);
+            if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) {
+                // report error
+                av_log(s, AV_LOG_ERROR, "Device with name %s not 
found",[filename UTF8String]);
+                return NULL;
+            }
+            return device;
+        }
+    }
+    return NULL;
+}
+
 static int setup_streams(AVFormatContext *s)
 {
-    NSLog(@"setting streams");
     AVFoundationCaptureContext *ctx = s->priv_data;
     int ret;
-    NSError *__autoreleasing error = nil;
-    NSArray *matches;
-    NSString *filename;
     AVCaptureDevice *device;
-    NSRegularExpression *exp;
 
     pthread_mutex_init(&ctx->frame_lock, NULL);
     pthread_cond_init(&ctx->frame_wait_cond, NULL);
 
     ctx->session = (__bridge_retained CFTypeRef)[[AVCaptureSession alloc] 
init];
 
-    if (s->filename[0] != '[') {
+    if (!strncmp(s->filename, "default", 7)) {
         ret = setup_default_stream(s);
     } else {
-        exp = [NSRegularExpression regularExpressionWithPattern:pat
-                                                        options:0
-                                                          error:&error];
-        if (!exp) {
-            av_log(s, AV_LOG_ERROR, "%s\n",
-                   [[error localizedDescription] UTF8String]);
-            return AVERROR(ENOMEM);
-        }
-
-        filename = [NSString stringWithFormat:@"%s", s->filename];
-        av_log(s, AV_LOG_INFO, "device name: %s\n",[filename UTF8String]);
-
-        matches = [exp matchesInString:filename options:0
-                                 range:NSMakeRange(0, [filename length])];
-
-        if (matches.count > 0) {
-            for (NSTextCheckingResult *match in matches) {
-                NSRange range = [match rangeAtIndex:0];
-                NSString *uniqueID = [filename substringWithRange:range];
-                av_log(s, AV_LOG_INFO, "opening device with ID: 
%s\n",[uniqueID UTF8String]);
-                if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) 
{
-                    // report error
-                    av_log(s, AV_LOG_ERROR, "Device with name %s not 
found",[filename UTF8String]);
-                    return AVERROR(EINVAL);
-                }
-                ret = setup_stream(s, device);
-                if (ret < 0) {
-                    // avfoundation_close
-                    return ret;
-                }
-            }
+        device = create_device(s);
+        if (device) {
+            ret = setup_stream(s, device);
         } else {
-            av_log(s, AV_LOG_ERROR, "No matches for %s",[filename UTF8String]);
+            av_log(s, AV_LOG_ERROR, "No matches for %s\n", s->filename);
             ret = setup_default_stream(s);
         }
     }
@@ -479,7 +494,7 @@ static int avfoundation_read_packet(AVFormatContext *s, 
AVPacket *pkt)
 
 static int avfoundation_read_close(AVFormatContext *s)
 {
-    NSLog(@"Closing session...");
+    av_log(s, AV_LOG_INFO, "Closing session...\n");
     AVFoundationCaptureContext *ctx = s->priv_data;
     destroy_context(ctx);
     return 0;
-- 
2.6.2

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to