[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