[FFmpeg-devel] [PATCH] allow v4l2 to select a frame rate

klchxbec at freenet.de klchxbec
Thu Dec 17 09:29:19 CET 2009


Hello.
??
Attached patch fixes the problem with v4l2 where if the user does
not specify the frame rate using -r option, it would fail with:

Error while opening encoder for output stream #0.0 - maybe incorrect parameters such as bit_rate, rate, width or height

The patch tries to apply the user-specified frame rate. If that does
not work, it reads the frame rate from the driver. Tested with a
couple of Logitech webcams.
??
--
K. Chowksey
??



Ist Ihr wunschname at freenet.de noch frei?
Jetzt pr?fen und kostenlose E-Mail-Adresse sichern!
http://email.freenet.de/dienste/emailoffice/produktuebersicht/basic/mail/index.html?pid=6829

-------------- next part --------------
Index: libavdevice/v4l2.c
===================================================================
--- libavdevice/v4l2.c	(revision 20888)
+++ libavdevice/v4l2.c	(working copy)
@@ -543,9 +543,55 @@
         }
     }
 
+    if (ap->time_base.num != 0 && ap->time_base.den != 0) {
+       struct v4l2_streamparm parm = {
+          .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
+       };
+
+       if (ioctl(s->fd, VIDIOC_G_PARM, &parm) < 0) {
+          av_log(s1, AV_LOG_INFO, "The V4L2 driver ioctl get parm failed\n");
+       } else {
+          if (parm.parm.capture.timeperframe.numerator != ap->time_base.num ||
+              parm.parm.capture.timeperframe.denominator != ap->time_base.den) {
+             parm.parm.capture.timeperframe.numerator = ap->time_base.num;
+             parm.parm.capture.timeperframe.denominator = ap->time_base.den;
+             if (ioctl(s->fd, VIDIOC_S_PARM, &parm) < 0) {
+                av_log(s1, AV_LOG_INFO, "The V4L2 driver ioctl to set frame rate %lf"
+                       " failed\n", 1/av_q2d(ap->time_base));
+             }
+          }
+       }
+    }
     return 0;
 }
 
+static void v4l2_find_frame_rate(AVFormatContext *ctx, AVStream *st, AVFormatParameters *ap)
+{
+    struct video_data *s = ctx->priv_data;
+    struct v4l2_streamparm parm = {
+        .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
+    };
+
+    if (ioctl(s->fd, VIDIOC_G_PARM, &parm) < 0) {
+        if (ap->time_base.den != 0 && ap->time_base.num != 0) {
+            av_log(ctx, AV_LOG_INFO, "The V4L2 driver ioctl get parm failed, assuming "
+                   "user-specified rate %lf\n", 1/av_q2d(ap->time_base));
+        }
+        st->codec->time_base.den = ap->time_base.den;
+        st->codec->time_base.num = ap->time_base.num;
+    } else {
+        st->codec->time_base.num = parm.parm.capture.timeperframe.numerator;
+        st->codec->time_base.den = parm.parm.capture.timeperframe.denominator;
+        if (ap->time_base.den != 0 && ap->time_base.num != 0 &&
+            (st->codec->time_base.num != ap->time_base.num ||
+             st->codec->time_base.den != ap->time_base.den)) {
+            av_log(ctx, AV_LOG_INFO, "The V4L2 driver changed the frame rate from "
+                   "%lf to %lf\n", 1/av_q2d(ap->time_base),
+                   1/av_q2d(st->codec->time_base));
+        }
+    }
+}
+
 uint32_t device_try_init(AVFormatContext *s1,
                          const AVFormatParameters *ap,
                          int *width,
@@ -650,8 +696,7 @@
     st->codec->codec_id = codec_id;
     st->codec->width = width;
     st->codec->height = height;
-    st->codec->time_base.den = ap->time_base.den;
-    st->codec->time_base.num = ap->time_base.num;
+    v4l2_find_frame_rate(s1, st, ap);
     st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
 
     return 0;



More information about the ffmpeg-devel mailing list