[FFmpeg-devel] [PATCH] allow v4l2 to capture mjpeg streams

Luca Abeni lucabe72
Wed Dec 9 10:01:52 CET 2009


Hi,

On Tue, 2009-12-08 at 23:58 -0800, klchxbec wrote:
> Thanks for pointing that out. Do you mean the patch in :
> http://archives.free.net.ph/message/20091205.101729.457f5f76.en.html

Yes, that's it

> That patch handles only V4L2_PIX_FMT_JPEG, not V4L2_PIX_FMT_MJPEG that my webcam
> supports.
> 
> That patch falls back to jpeg only if none of the yuv modes can be found or activated. AFAICT,
> it does not offer the user a way to select jpeg over yuv if the webcam supports both.

Ah, ok... Thanks for explaining. I still don't understand why v4l2 has
both V4L2_PIX_FMT_JPEG and V4L2_PIX_FMT_MJPEG, but I guess we cannot do
anything about this :)


> I integrated Ramiro Polla's patch to handle V4L2_PIX_FMT_JPEG into mine:

Ok; after your explanation, I think the patch can be made even more
generic, by introducing an array (similar to fmt_conversion_table[]) for
converting between codec IDs and v4l2 formats.
This would simplify support for other compressed formats.

See some comments below.

> Index: v4l2.c
> ===================================================================
> --- v4l2.c    (revision 20738)
> +++ v4l2.c    (working copy)
> @@ -241,6 +241,16 @@
>      return PIX_FMT_NONE;
>  }
>  
> +static int v4l2_format_is_fixed(int frame_format)
> +{
> +    switch (frame_format) {
> +    case V4L2_PIX_FMT_MJPEG:
> +    case V4L2_PIX_FMT_JPEG:
> +        return 0;
> +    }
> +    return 1;
> +}

I think this check can be based on the codec ID, can can be
(codec_id == CODEC_ID_RAWVIDEO).


>  static int mmap_init(AVFormatContext *ctx)
>  {
>      struct video_data *s = ctx->priv_data;
> @@ -297,8 +307,8 @@
>          }
>  
>          s->buf_len[i] = buf.length;
> -        if (s->buf_len[i] < s->frame_size) {
> -            av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
> +        if (v4l2_format_is_fixed(s->frame_format) && s->buf_len[i] > s->frame_size) {
> +            av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d > %d\n", i, s->buf_len[i], s->frame_size);

Here, you seem to be reverting the check; "s->buf_len[i] >
s->frame_size" instead of "s->buf_len[i] < s->frame_size" (actually, a
buffer larger than the frame size can be ok...).

[...] 
>      /* Image is at s->buff_start[buf.index] */
>      pkt->data= s->buf_start[buf.index];
>      pkt->size = buf.bytesused;
> -    pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
> +    pkt->pts = buf.timestamp.tv_sec * UINT64_C(1000000) + buf.timestamp.tv_usec;

Why this? pkt->pts is int64_t, so the original code should be correct...
No?

 
> +static int device_init_mjpeg(AVFormatContext *s1, int *width, int *height)
> +{
> +   int desired_format = V4L2_PIX_FMT_MJPEG;
> +
> +   if (device_init(s1, width, height, desired_format) < 0) {
> +      desired_format = V4L2_PIX_FMT_JPEG;
> +      if (device_init(s1, width, height, desired_format) < 0) {
> +         desired_format = 0;
> +      }
> +   }

Maybe this function can get a codec_id as a parameter, and use the table
mentioned above for converting between codec_id and v4l2 format?


[...] 
>      st->codec->codec_type = CODEC_TYPE_VIDEO;
> -    st->codec->codec_id = CODEC_ID_RAWVIDEO;
> +    if (s->frame_format == V4L2_PIX_FMT_MJPEG ||
> +        s->frame_format == V4L2_PIX_FMT_JPEG) {
> +        st->codec->codec_id = CODEC_ID_MJPEG;
> +    } else {
> +        st->codec->codec_id = CODEC_ID_RAWVIDEO;
> +    }

Maybe having a codec_id variable which you previously set in this
function can help to simplify the code?

>      st->codec->width = width;
>      st->codec->height = height;
>      st->codec->time_base.den = ap->time_base.den;

I think the code following these lines will end up by setting a wrong
st->codec->bit_rate in case of compressed formats.


			Thanks,
				Luca




More information about the ffmpeg-devel mailing list