On 2011-12-29 17:29:22 +0100, Luca Barbato wrote:
> ---
> 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. */
could use vertical alignment
> };
>
> @@ -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 },
> };
I was more thinking of a binary avconv option but I guess this is ok,
since even the avconv option needs a away to request the formats from
the v4l2 driver.
patch ok
Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel