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

Daniel Ly daniel.ly at lively5.ch
Thu Apr 23 11:07:40 CEST 2015


On Thu, Apr 23, 2015 at 9:58 AM, Thilo Borgmann <thilo.borgmann at mail.de>
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 <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.
>

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

Ok. Also aligned lines 1122-1130.


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

Does not matter. I switched to @autoreleasepool {} and removed the fail
label. valgrind and I are happier with the memory leaks.


> > +    }
> > +#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
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list