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

klchxbec at freenet.de klchxbec
Wed Dec 9 05:55:09 CET 2009


Hi,

This patch allows v4l2 to capture mjpeg streams using -vcodec mjpeg option. The default is still yuv streams.
I tested with a webcam that supports both mjpeg+yuv, and one that supports mjpeg only and one that supports
yuv only.

Index: v4l2.c
===================================================================
--- v4l2.c (revision 20738)
+++ v4l2.c (working copy)
@@ -241,6 +241,15 @@
 return PIX_FMT_NONE;
}

+static int v4l2_format_is_fixed(int frame_format)
+{
+ switch (frame_format) {
+ case V4L2_PIX_FMT_MJPEG:
+ return 0;
+ }
+ return 1;
+}
+
static int mmap_init(AVFormatContext *ctx)
{
 struct video_data *s = ctx->priv_data;
@@ -297,8 +306,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 +377,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) {
@@ -542,6 +550,9 @@
 av_log(s1, AV_LOG_INFO, \"[%d]Capabilities: %x\\n\", s->fd, capabilities);

 desired_format = fmt_ff2v4l(ap->pix_fmt);
+ if (desired_format == 0 && ap->video_codec_id == CODEC_ID_MJPEG) {
+ desired_format = V4L2_PIX_FMT_MJPEG;
+ }
 if (desired_format == 0 || (device_init(s1, &width, &height, desired_format) < 0)) {
 int i, done;

@@ -558,6 +569,13 @@
 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 = V4L2_PIX_FMT_MJPEG;
+ if (device_init(s1, &width, &height, desired_format) < 0) {
+ desired_format = 0;
+ }
+ }
 }
 if (desired_format == 0) {
 av_log(s1, AV_LOG_ERROR, \"Cannot find a proper format.\\n\");
@@ -590,7 +608,11 @@
 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) {
+ 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 +647,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)

-K Chowksey



Gesendet von freenetMail-
Mehr als nur eine E-Mail-Adresse
http://email.freenet.de/dienste/emailoffice/produktuebersicht/basic/mail/index.html?pid=6828





More information about the ffmpeg-devel mailing list