[FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.

Daniel Ly nalply at gmail.com
Thu Apr 23 09:35:53 CEST 2015


This makes avdevice_list_input_sources() available for
device_name = "avfoundation".

I didn't yet retrofit avf_read_header() to use the new function to
keep this patch small.

Signed-off-by: Daniel Ly <nalply at gmail.com>
---
 libavdevice/avfoundation.m | 85 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 763e675..523dc12 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -34,6 +34,7 @@
 #include "libavformat/internal.h"
 #include "libavutil/internal.h"
 #include "libavutil/parseutils.h"
+#include "libavutil/avstring.h"
 #include "libavutil/time.h"
 #include "avdevice.h"
 
@@ -1007,6 +1008,89 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
     return 0;
 }
 
+static int avf_add_device_info(
+    AVDeviceInfoList *list, int index, const char *description, const char *model
+)
+{
+    AVDeviceInfo *info = av_mallocz(sizeof(AVDeviceInfo));
+    if (!info) return AVERROR(ENOMEM);
+
+    info->device_name = av_asprintf("[%d] %s; %s", index, description, model);
+    info->device_description = strdup(description);
+    if (!info->device_name || !info->device_description) {
+        av_free(info);
+        return AVERROR(ENOMEM);
+    }
+
+    av_dynarray_add(&list->devices, &list->nb_devices, info);
+    return list ? list->nb_devices : AVERROR(ENOMEM);
+}
+
+
+static int avf_get_device_list(
+    struct AVFormatContext *s, struct AVDeviceInfoList *list
+) 
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    uint32_t num_screens    = 0;
+    AVFContext *ctx         = (AVFContext*)s->priv_data;
+    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+
+#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+    CGGetActiveDisplayList(0, NULL, &num_screens);
+#endif
+
+    int result = 0;
+    int index;
+    const char *localizedName, *modelID;
+
+    av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n");
+    for (AVCaptureDevice *device in devices) {
+        index = [devices indexOfObject:device];
+        localizedName = [[device localizedName] UTF8String];
+        modelID = [[device modelID] UTF8String];
+        result = avf_add_device_info(list, index, localizedName, modelID);
+        if (result < 0) goto fail;
+        av_log(ctx, AV_LOG_INFO, "%s\n", list->devices[result - 1]->device_name);
+    }
+#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+    if (num_screens > 0) {
+        CGDirectDisplayID screens[num_screens];
+        CGGetActiveDisplayList(num_screens, screens, &num_screens);
+        for (int i = 0; i < num_screens; i++) {
+            char buf[30];
+            snprintf(buf, 30, "Capture screen %d", i);
+        
+            // No screen name available. Implementation is arcane and uses
+            // deprecated API, see http://stackoverflow.com/q/24348142/220060.
+            // Perhaps the current screen resolution would be more interesting.
+            result = avf_add_device_info(list, index + i + 1, buf, "-"); 
+            if (result < 0) goto fail;
+            av_log(ctx, AV_LOG_INFO, "%s\n", list->devices[result - 1]->device_name);
+        }
+    }
+#endif
+
+    av_log(ctx, AV_LOG_INFO, "AVFoundation audio devices:\n");
+    devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
+    for (AVCaptureDevice *device in devices) {
+        index = [devices indexOfObject:device];
+        localizedName = [[device localizedName] UTF8String];
+        modelID = [[device modelID] UTF8String];
+        result = avf_add_device_info(list, index, localizedName, modelID);
+        if (result < 0) goto fail;
+        av_log(ctx, AV_LOG_INFO, "%s\n", list->devices[result - 1]->device_name);
+    }
+
+    list->default_device = 0;
+
+fail:
+    [pool release];
+    destroy_context(ctx);
+
+    return result;
+}
+
 static int avf_close(AVFormatContext *s)
 {
     AVFContext* ctx = (AVFContext*)s->priv_data;
@@ -1044,6 +1128,7 @@ AVInputFormat ff_avfoundation_demuxer = {
     .read_header    = avf_read_header,
     .read_packet    = avf_read_packet,
     .read_close     = avf_close,
+    .get_device_list= avf_get_device_list,
     .flags          = AVFMT_NOFILE,
     .priv_class     = &avf_class,
 };
-- 
1.8.1.4



More information about the ffmpeg-devel mailing list