---
doc/indevs.texi | 2 +-
libavdevice/v4l2.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 4405a5b..e1b4ddd 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -267,7 +267,7 @@ the device.
Video4Linux and Video4Linux2 devices only support a limited set of
@var{width}x@var{height} sizes and framerates. You can check which are
supported for example with the command @file{dov4l} for Video4Linux
-devices and the command @file{v4l-info} for Video4Linux2 devices.
+devices and using @command{-list_formats all} for Video4Linux2 devices.
If the size for the device is set to 0x0, the input device will
try to autodetect the size to use.
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index b3c3c1d..13d0e6a 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -51,6 +51,10 @@
static const int desired_video_buffers = 256;
+#define V4L_ALLFORMATS 3
+#define V4L_RAWFORMATS 1
+#define V4L_COMPFORMATS 2
+
struct video_data {
AVClass *class;
int fd;
@@ -67,6 +71,7 @@ struct video_data {
int channel;
char *video_size; /**< String describing video size, set by a private
option. */
char *pixel_format; /**< Set by a private option. */
+ int list_format; /**< Set by a private option. */
char *framerate; /**< Set by a private option. */
};
@@ -254,6 +259,52 @@ static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt)
return CODEC_ID_NONE;
}
+static void list_formats(AVFormatContext *ctx, int type, int fd)
+{
+ struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
+ struct v4l2_frmsizeenum vfse = { 0 };
+
+ while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) {
+ enum CodecID codec_id = fmt_v4l2codec(vfd.pixelformat);
+ enum PixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id);
+
+ vfd.index++;
+
+ if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) &&
+ type & V4L_RAWFORMATS) {
+ const char *fmt_name = av_get_pix_fmt_name(pix_fmt);
+ av_log(ctx, AV_LOG_INFO, "R : %9s : %20s :",
+ fmt_name ? fmt_name : "Unsupported",
+ vfd.description);
+ } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED &&
+ type & V4L_COMPFORMATS) {
+ AVCodec *codec = avcodec_find_encoder(codec_id);
+ av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :",
+ codec ? codec->name : "Unsupported",
+ vfd.description);
+ } else {
+ continue;
+ }
+
+ if (vfd.flags & V4L2_FMT_FLAG_EMULATED) {
+ av_log(ctx, AV_LOG_WARNING, "%s", "Emulated");
+ continue;
+ }
+
+ vfse.pixel_format = vfd.pixelformat;
+
+ while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
+ av_log(ctx, AV_LOG_INFO,
+ " %ux%u",
+ vfse.discrete.width, vfse.discrete.height);
+ vfse.index++;
+ }
+
+ vfse.index = 0;
+ av_log(ctx, AV_LOG_INFO, "\n");
+ }
+}
+
static int mmap_init(AVFormatContext *ctx)
{
struct video_data *s = ctx->priv_data;
@@ -617,6 +668,12 @@ static int v4l2_read_header(AVFormatContext *s1,
AVFormatParameters *ap)
goto out;
}
+ if (s->list_format) {
+ list_formats(s1, s->list_format, s->fd);
+ res = AVERROR_EXIT;
+ goto out;
+ }
+
avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
if (s->video_size &&
@@ -625,12 +682,18 @@ static int v4l2_read_header(AVFormatContext *s1,
AVFormatParameters *ap)
s->video_size);
goto out;
}
- if (s->pixel_format &&
- (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) {
- av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n",
- s->pixel_format);
- res = AVERROR(EINVAL);
- goto out;
+
+ if (s->pixel_format) {
+
+ pix_fmt = av_get_pix_fmt(s->pixel_format);
+
+ if (pix_fmt == PIX_FMT_NONE) {
+ av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n",
+ s->pixel_format);
+
+ res = AVERROR(EINVAL);
+ goto out;
+ }
}
if (!s->width && !s->height) {
@@ -730,6 +793,10 @@ static const AVOption options[] = {
{ "video_size", "A string describing frame size, such as 640x480 or
hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0,
DEC },
{ "pixel_format", "",
OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "framerate", "",
OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "list_formats", "List available formats and exit",
OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC,
"list_formats" },
+ { "all", "Show all available formats",
OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0,
INT_MAX, DEC, "list_formats" },
+ { "raw", "Show only non-compressed formats",
OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_RAWFORMATS }, 0,
INT_MAX, DEC, "list_formats" },
+ { "compressed", "Show only compressed formats",
OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_COMPFORMATS }, 0,
INT_MAX, DEC, "list_formats" },
{ NULL },
};
--
1.7.8.rc1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel