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

Reply via email to