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

Thilo Borgmann thilo.borgmann at mail.de
Thu Apr 23 09:58:39 CEST 2015


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)


> 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
> +)

Paranthesis looks awkward.


> +{
> +    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 ':'.


> +    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?


> +}
> +
> +
> +static int avf_get_device_list(
> +    struct AVFormatContext *s, struct AVDeviceInfoList *list
> +) 

See above...


> +{
> +    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.


> +
> +#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);

Vertical alignment.


> +        if (result < 0) goto fail;
> +        av_log(ctx, AV_LOG_INFO, "%s\n", list->devices[result - 1]->device_name);

Segfault if result == 0?

> +    }
> +#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,
>  };
> 

-Thilo


More information about the ffmpeg-devel mailing list