mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
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 <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,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user