[FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.
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 --- 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 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.
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 --- 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 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.
On Thu, Apr 23, 2015 at 9:58 AM, Thilo Borgmann wrote: > Am 23.04.15 um 09:35 schrieb Daniel Ly: > > 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. > > Please post a follow-up patch for that purpose, too. (In that thread) Ok. > > Signed-off-by: Daniel Ly > > --- > > 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 > > +) > > Paranthesis looks awkward. > I moved the parenthesis to the end of the previous line. > > +{ > > +AVDeviceInfo *info = av_mallocz(sizeof(AVDeviceInfo)); > > +if (!info) return AVERROR(ENOMEM); > > + > > > +info->device_name = av_asprintf("[%d] %s; %s", index, description, > model); > > Is this string format kind of standard in FFmpeg? Otherwise I would prefer > description behind model and no ';' but a ':'. > I replaced ; by :. ffmpeg -f avfoundation -list_devices true -i dummy produces this output: [AVFoundation input device @ 0x7fec68c01080] AVFoundation video devices: [AVFoundation input device @ 0x7fec68c01080] [0] Logitech Camera [AVFoundation input device @ 0x7fec68c01080] [1] Capture screen 0 [AVFoundation input device @ 0x7fec68c01080] [2] Capture screen 1 [AVFoundation input device @ 0x7fec68c01080] AVFoundation audio devices: [AVFoundation input device @ 0x7fec68c01080] [0] Logitech Camera [AVFoundation input device @ 0x7fec68c01080] [1] Built-in Input Now it looks like this: [AVFoundation input device @ 0x7fdcd9421830] AVFoundation video devices: [AVFoundation input device @ 0x7fdcd9421830] [0] Logitech Camera: UVC Camera VendorID_1133 ProductID_2050 [AVFoundation input device @ 0x7fdcd9421830] [1] Capture screen 0: - [AVFoundation input device @ 0x7fdcd9421830] [2] Capture screen 1: - [AVFoundation input device @ 0x7fdcd9421830] AVFoundation audio devices: [AVFoundation input device @ 0x7fdcd9421830] [0] Logitech Camera: UVC Camera VendorID_1133 ProductID_2050 Doxygen says about the struct AVDeviceInfo that device_name is device name, format depends on device; and that device_description is human friendly name. Therefore I set device_description to "Logitech Camera" and device_name to = "Logitech Camera: UVC Camera VendorID_1133 ProductID_2050". This is awkward but I don't know what else to put in. > +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); > > I'm not sure if "list" is null'd in case of an error in av_dynarray_add? > Doxygen says: In case of failure, the array is freed, *tab_ptr is set to NULL and *nb_ptr is set to 0. > > +} > > + > > + > > +static int avf_get_device_list( > > +struct AVFormatContext *s, struct AVDeviceInfoList *list > > +) > > See above... > Ok. > > +{ > > +NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; > > +uint32_t num_screens= 0; > > +AVFContext *ctx = (AVFContext*)s->priv_data; > > +NSArray *devices = [AVCaptureDevice > devicesWithMediaType:AVMediaTypeVideo]; > > Please align vertically even if one line gets too long by that. > Ok. > > + > > +#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; > > + > > +
[FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.
This makes avdevice_list_input_sources() available for device_name = "avfoundation". avf_read_header is retrofitted to use the new method. Signed-off-by: Daniel Ly --- libavdevice/avfoundation.m | 139 + 1 file changed, 104 insertions(+), 35 deletions(-) diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m index 763e675..a827248 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" @@ -659,6 +660,98 @@ static int get_audio_config(AVFormatContext *s) return 0; } +static int avf_add_device_info(AVDeviceInfoList *list, AVFormatContext *s, +int index, const char *description, const char *model, int do_log) +{ +if (do_log) av_log(s->priv_data, AV_LOG_INFO, "[%d] %s\n", index, description); +if (!list) return 0; + +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); +} + +/** + * List AVFoundation video and audio devices into AVDeviceInfoList. + * + * @param s format context. + * @param list device list or NULL (to log only). + * @param do_log log the devices if true. + */ +static int avf_get_device_list2(struct AVFormatContext *s, struct AVDeviceInfoList *list, int do_log) +{ +int result = 0, index; +const char *localizedName, *modelID; + +if (do_log) 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, do_log); +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, "-", do_log); +if (result < 0) break; +} +} +#endif + +if (do_log) av_log(s->priv_data, AV_LOG_INFO, "AVFoundation audio devices:\n"); +NSArray *audio_devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio]; +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, do_log); +if (result < 0) break; +} +} +[audio_devices release]; + +// Make the first device default if it exists. +if (list) list->default_device = list->nb_devices > 0 ? 0 : -1; + +return result; +} + +static int avf_get_device_list(struct AVFormatContext *s, struct AVDeviceInfoList *list) +{ + return avf_get_device_list2(s, list, FALSE); +} + static int avf_read_header(AVFormatContext *s) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -683,32 +776,8 @@ static int avf_read_header(AVFormatContext *s) // List devices if requested if (ctx->list_devices) { -int index = 0; -av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n"); -for (AVCaptureDevice *device in devices) { -const char *name = [[device localizedName] UTF8String]; -index= [devices indexOfObject:device]; -av_log(ct
Re: [FFmpeg-devel] [PATCH] Add get_device_list() to AVFoundation input device.
On Thu, Apr 23, 2015 at 11:41 AM, Thilo Borgmann wrote: > Am 23.04.15 um 11:07 schrieb Daniel Ly: > > +info->device_name = av_asprintf("[%d] %s: %s", index, description, > model); > > So I assume that this is not parsed later. > However, it changes current output format and should interfere with > parse_device_string(). Consider choosing the very same format string which > is > there already. > Yes. The new patch with the retrofitted method produces exactly the same output as before. > > +av_log(s->priv_data, AV_LOG_INFO, "%s\n", info->device_name); > > This always prints all devices, which is an unwanted behaviour. > Currently you have to cause an error (e.g. wrong index) or explicitly call > with > -list_devices to get that. > Yes. avdevice_list_input_sources() is silent now. Daniel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel