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

2015-04-23 Thread 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.

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.

2015-04-23 Thread 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. 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.

2015-04-23 Thread Daniel Ly
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.

2015-04-28 Thread Daniel Ly
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.

2015-04-28 Thread Daniel Ly
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