[FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.
Daniel Ly
nalply at gmail.com
Thu Apr 23 11:07:43 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. I will post the follow-up patch in the same
thread.
Signed-off-by: Daniel Ly <nalply at gmail.com>
---
libavdevice/avfoundation.m | 98 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 90 insertions(+), 8 deletions(-)
diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 763e675..19ce2a0 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,86 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
return 0;
}
+static int avf_add_device_info(AVDeviceInfoList *list, AVFormatContext *s,
+ 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_log(s->priv_data, AV_LOG_INFO, "%s\n", info->device_name);
+ 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)
+{
+ int result = 0, index;
+ const char *localizedName, *modelID;
+
+ av_log(s->priv_data, AV_LOG_INFO, "AVFoundation video devices:\n");
+ NSArray *video_devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+ for (AVCaptureDevice *device in video_devices) {
+ @autoreleasepool {
+ index = [video_devices indexOfObject:device];
+ localizedName = [[device localizedName] UTF8String];
+ modelID = [[device modelID] UTF8String];
+
+ result = avf_add_device_info(list, s, index, localizedName, modelID);
+ if (result < 0) break;
+ }
+ }
+ [video_devices release];
+
+
+#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+ uint32_t num_screens = 0;
+ CGGetActiveDisplayList(0, NULL, &num_screens);
+
+ if (num_screens > 0) {
+ CGDirectDisplayID screens[num_screens];
+ CGGetActiveDisplayList(num_screens, screens, &num_screens);
+ int i;
+ for (i = 0; i < num_screens; i++) {
+ char buf[30];
+ snprintf(buf, 30, "Capture screen %d", i);
+
+ // No screen name available (as model). Implementation is arcane
+ // and uses deprecated API. See stackoverflow.com/q/24348142/220060
+ result = avf_add_device_info(list, s, index + i + 1, buf, "-");
+ if (result < 0) break;
+ }
+ }
+#endif
+
+ av_log(s->priv_data, AV_LOG_INFO, "AVFoundation audio devices:\n");
+ NSArray *audio_devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+ for (AVCaptureDevice *device in audio_devices) {
+ @autoreleasepool {
+ index = [audio_devices indexOfObject:device];
+ localizedName = [[device localizedName] UTF8String];
+ modelID = [[device modelID] UTF8String];
+
+ result = avf_add_device_info(list, s, index, localizedName, modelID);
+ if (result < 0) break;
+ }
+ }
+ [audio_devices release];
+
+ // Make the first device default if it exists.
+ list->default_device = list->nb_devices > 0 ? 0 : -1;
+
+ return result;
+}
+
static int avf_close(AVFormatContext *s)
{
AVFContext* ctx = (AVFContext*)s->priv_data;
@@ -1038,12 +1119,13 @@ static const AVClass avf_class = {
};
AVInputFormat ff_avfoundation_demuxer = {
- .name = "avfoundation",
- .long_name = NULL_IF_CONFIG_SMALL("AVFoundation input device"),
- .priv_data_size = sizeof(AVFContext),
- .read_header = avf_read_header,
- .read_packet = avf_read_packet,
- .read_close = avf_close,
- .flags = AVFMT_NOFILE,
- .priv_class = &avf_class,
+ .name = "avfoundation",
+ .long_name = NULL_IF_CONFIG_SMALL("AVFoundation input device"),
+ .priv_data_size = sizeof(AVFContext),
+ .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