lavd/v4l2: implement list device callback
Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
This commit is contained in:
parent
44e6eeb30d
commit
ea0ac11f1b
@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "v4l2-common.h"
|
#include "v4l2-common.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#if CONFIG_LIBV4L2
|
#if CONFIG_LIBV4L2
|
||||||
#include <libv4l2.h>
|
#include <libv4l2.h>
|
||||||
@ -1006,6 +1007,81 @@ static int v4l2_read_close(AVFormatContext *ctx)
|
|||||||
return 0;
|
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 OFFSET(x) offsetof(struct video_data, x)
|
||||||
#define DEC AV_OPT_FLAG_DECODING_PARAM
|
#define DEC AV_OPT_FLAG_DECODING_PARAM
|
||||||
|
|
||||||
@ -1050,6 +1126,7 @@ AVInputFormat ff_v4l2_demuxer = {
|
|||||||
.read_header = v4l2_read_header,
|
.read_header = v4l2_read_header,
|
||||||
.read_packet = v4l2_read_packet,
|
.read_packet = v4l2_read_packet,
|
||||||
.read_close = v4l2_read_close,
|
.read_close = v4l2_read_close,
|
||||||
|
.get_device_list = v4l2_get_device_list,
|
||||||
.flags = AVFMT_NOFILE,
|
.flags = AVFMT_NOFILE,
|
||||||
.priv_class = &v4l2_class,
|
.priv_class = &v4l2_class,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user