On 2012-01-03 11:27:54 +0100, Luca Barbato wrote:
> Make use of the experimental framesize enumeration ioctl if available.
> ---
> configure | 3 ++
> doc/indevs.texi | 2 +-
> libavdevice/v4l2.c | 101
> ++++++++++++++++++++++++++++++++++++++++++++++++----
> 3 files changed, 98 insertions(+), 8 deletions(-)
>
> diff --git a/configure b/configure
> index b7f0acd..c683dc4 100755
> --- a/configure
> +++ b/configure
> @@ -1135,6 +1135,7 @@ HAVE_LIST="
> struct_sockaddr_in6
> struct_sockaddr_sa_len
> struct_sockaddr_storage
> + struct_v4l2_frmivalenum_discrete
> symver
> symver_asm_label
> symver_gnu_asm
> @@ -2993,6 +2994,8 @@ texi2html -version > /dev/null 2>&1 && enable texi2html
> || disable texi2html
> check_header linux/fb.h
> check_header linux/videodev.h
> check_header linux/videodev2.h
> +check_struct linux/videodev2.h "struct v4l2_frmivalenum" discrete
> +
does this check for a member in an anonymous union ever succeed with
gcc -std=c99 ? if not it is pointless and we should look how we can
make it available for gcc on linux.
> check_header sys/videoio.h
>
> check_func_headers "windows.h vfw.h" capCreateCaptureWindow
> "$vfwcap_indev_extralibs"
> 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 cde2f9f..e0cd97f 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;
> @@ -65,8 +69,10 @@ struct video_data {
> unsigned int *buf_len;
> char *standard;
> int channel;
> - char *video_size; /**< String describing video size, set by a private
> option. */
> + 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. */
> };
>
> @@ -258,6 +264,71 @@ static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt)
> return CODEC_ID_NONE;
> }
>
> +#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
> +static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t
> pixelformat)
> +{
> + struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat };
> +
> + while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
> + switch (vfse.type) {
> + case V4L2_FRMSIZE_TYPE_DISCRETE:
> + av_log(ctx, AV_LOG_INFO, " %ux%u",
> + vfse.discrete.width, vfse.discrete.height);
> + break;
> + case V4L2_FRMSIZE_TYPE_CONTINUOUS:
> + av_log(ctx, AV_LOG_INFO, " {Any}x{Any}");
the only driver using V4L2_FRMSIZE_TYPE_CONTINUOUS in 3.1 still sets
stepwise.* probably noting to rely on. Any sounds wrong since there
will be a min and max frame size. It's probably fine as is and
V4L2_FRMSIZE_TYPE_CONTINUOUS will be mostly ignored
> + break;
> + case V4L2_FRMSIZE_TYPE_STEPWISE:
> + av_log(ctx, AV_LOG_INFO, " {%u-%u, %u}x{%u-%u, %u}",
> + vfse.stepwise.min_width,
> + vfse.stepwise.max_width,
> + vfse.stepwise.step_width,
> + vfse.stepwise.min_height,
> + vfse.stepwise.max_height,
> + vfse.stepwise.step_height);
> + }
> + vfse.index++;
> + }
> +}
> +#endif
> +
> +static void list_formats(AVFormatContext *ctx, int fd, int type)
> +{
> + struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
> +
> + 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;
> + }
> +#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
> + list_framesizes(ctx, fd, vfd.pixelformat);
> +#endif
> + av_log(ctx, AV_LOG_INFO, "\n");
> + }
> +}
> +
> static int mmap_init(AVFormatContext *ctx)
> {
> struct video_data *s = ctx->priv_data;
> @@ -621,6 +692,12 @@ static int v4l2_read_header(AVFormatContext *s1,
> AVFormatParameters *ap)
> goto out;
> }
>
> + if (s->list_format) {
> + list_formats(s1, s->fd, s->list_format);
> + res = AVERROR_EXIT;
> + goto out;
> + }
> +
> avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
>
> if (s->video_size &&
> @@ -629,12 +706,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) {
> @@ -737,6 +820,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 },
> };
still ok otherwise
Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel