[FFmpeg-cvslog] lavd/v4l2: implement list device callback

Lukasz Marek git at videolan.org
Sun Jan 11 19:00:14 CET 2015


ffmpeg | branch: master | Lukasz Marek <lukasz.m.luki2 at gmail.com> | Sun Dec 21 22:37:18 2014 +0100| [ea0ac11f1bf1909f369a9d7d2a26709412fc55f5] | committer: Lukasz Marek

lavd/v4l2: implement list device callback

Signed-off-by: Lukasz Marek <lukasz.m.luki2 at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ea0ac11f1bf1909f369a9d7d2a26709412fc55f5
---

 libavdevice/v4l2.c |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 2969980..8337cf5 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -31,6 +31,7 @@
  */
 
 #include "v4l2-common.h"
+#include <dirent.h>
 
 #if CONFIG_LIBV4L2
 #include <libv4l2.h>
@@ -1006,6 +1007,81 @@ static int v4l2_read_close(AVFormatContext *ctx)
     return 0;
 }
 
+static int v4l2_is_v4l_dev(const char *name)
+{
+    return !strncmp(name, "video", 5) ||
+           !strncmp(name, "radio", 5) ||
+           !strncmp(name, "vbi", 3) ||
+           !strncmp(name, "v4l-subdev", 10);
+}
+
+static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_list)
+{
+    struct video_data *s = ctx->priv_data;
+    DIR *dir;
+    struct dirent *entry;
+    AVDeviceInfo *device = NULL;
+    struct v4l2_capability cap;
+    int ret = 0;
+
+    if (!device_list)
+        return AVERROR(EINVAL);
+
+    dir = opendir("/dev");
+    if (!dir) {
+        ret = AVERROR(errno);
+        av_log(ctx, AV_LOG_ERROR, "Couldn't open the directory: %s\n", av_err2str(ret));
+        return ret;
+    }
+    while ((entry = readdir(dir))) {
+        if (!v4l2_is_v4l_dev(entry->d_name))
+            continue;
+
+        snprintf(ctx->filename, sizeof(ctx->filename), "/dev/%s", entry->d_name);
+        if ((s->fd = device_open(ctx)) < 0)
+            continue;
+
+        if (v4l2_ioctl(s->fd, VIDIOC_QUERYCAP, &cap) < 0) {
+            ret = AVERROR(errno);
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", av_err2str(ret));
+            goto fail;
+        }
+
+        device = av_mallocz(sizeof(AVDeviceInfo));
+        if (!device) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        device->device_name = av_strdup(ctx->filename);
+        device->device_description = av_strdup(cap.card);
+        if (!device->device_name || !device->device_description) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        if ((ret = av_dynarray_add_nofree(&device_list->devices,
+                                          &device_list->nb_devices, device)) < 0)
+            goto fail;
+
+        v4l2_close(s->fd);
+        s->fd = -1;
+        continue;
+
+      fail:
+        if (device) {
+            av_freep(&device->device_name);
+            av_freep(&device->device_description);
+            av_freep(&device);
+        }
+        if (s->fd >= 0)
+            v4l2_close(s->fd);
+        s->fd = -1;
+        break;
+    }
+    closedir(dir);
+    return ret;
+}
+
 #define OFFSET(x) offsetof(struct video_data, x)
 #define DEC AV_OPT_FLAG_DECODING_PARAM
 
@@ -1050,6 +1126,7 @@ AVInputFormat ff_v4l2_demuxer = {
     .read_header    = v4l2_read_header,
     .read_packet    = v4l2_read_packet,
     .read_close     = v4l2_read_close,
+    .get_device_list = v4l2_get_device_list,
     .flags          = AVFMT_NOFILE,
     .priv_class     = &v4l2_class,
 };



More information about the ffmpeg-cvslog mailing list