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

klchxbec klchxbec
Wed Dec 9 08:58:08 CET 2009


Luca,

Thanks for pointing that out. Do you mean the patch in :
http://archives.free.net.ph/message/20091205.101729.457f5f76.en.html

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.

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

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;
+}
+
 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);
 
             return -1;
         }
@@ -368,16 +378,15 @@
         return -1;
     }
     assert (buf.index < s->buffers);
-    if (buf.bytesused != s->frame_size) {
+    if (v4l2_format_is_fixed(s->frame_format) && buf.bytesused != s->frame_size) {
         av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
-
         return -1;
     }
 
     /* 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;
     pkt->destruct = mmap_release_buffer;
     buf_descriptor = av_malloc(sizeof(struct buff_data));
     if (buf_descriptor == NULL) {
@@ -506,6 +515,20 @@
     return 0;
 }
 
+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;
+      }
+   }
+
+   return desired_format;
+}
+
 static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
 {
     struct video_data *s = s1->priv_data;
@@ -541,7 +564,11 @@
     }
     av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);
 
-    desired_format = fmt_ff2v4l(ap->pix_fmt);
+    if (ap->video_codec_id == CODEC_ID_MJPEG) {
+       desired_format = device_init_mjpeg(s1, &width, &height);
+    } else {
+       desired_format = fmt_ff2v4l(ap->pix_fmt);
+    }
     if (desired_format == 0 || (device_init(s1, &width, &height, desired_format) < 0)) {
         int i, done;
 
@@ -558,6 +585,10 @@
                done = 1;
             }
         }
+        /* Fallback to mjpeg if none of the yuv formats are supported */
+        if (ap->video_codec_id != CODEC_ID_MJPEG && desired_format == 0) {
+           desired_format = device_init_mjpeg(s1, &width, &height);
+        }
     }
     if (desired_format == 0) {
         av_log(s1, AV_LOG_ERROR, "Cannot find a proper format.\n");
@@ -590,7 +621,12 @@
     s->top_field_first = first_field(s->fd);
 
     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;
+    }
     st->codec->width = width;
     st->codec->height = height;
     st->codec->time_base.den = ap->time_base.den;
@@ -625,7 +661,7 @@
         s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
     }
 
-    return s->frame_size;
+    return pkt->size;
 }
 
 static int v4l2_read_close(AVFormatContext *s1)


----- Original Message ----
From: Luca Abeni <lucabe72 at email.it>
To: FFmpeg development discussions and patches <ffmpeg-devel at mplayerhq.hu>
Sent: Wed, 9 December, 2009 12:14:05 PM
Subject: Re: [FFmpeg-devel] [PATCH] allow v4l2 to capture mjpeg streams

A similar patch has been sent for testing some time ago (Ramiro Polla
just re-sent it few days ago). Can you test it? I was plannin to apply
Ramiro's version in few days...
If you think your patch has some more features or some advantages
respect to the version posted by Ramiro, let me know.


            Thanks,
                Luca

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel at mplayerhq.hu
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel


      The INTERNET now has a personality. YOURS! See your Yahoo! Homepage. http://in.yahoo.com/



More information about the ffmpeg-devel mailing list