]> git.sesse.net Git - ffmpeg/blobdiff - libavdevice/v4l2.c
movenc: Force first sample as SYNC
[ffmpeg] / libavdevice / v4l2.c
index a3b8968fa04e75b1d587b302b0a75dc3d0011f7f..993e2adceceb23d63595e68473f846ee8c82b19f 100644 (file)
@@ -78,81 +78,22 @@ struct fmt_map {
 };
 
 static struct fmt_map fmt_conversion_table[] = {
-    {
-        .ff_fmt = PIX_FMT_YUV420P,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_YUV420,
-    },
-    {
-        .ff_fmt = PIX_FMT_YUV422P,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
-    },
-    {
-        .ff_fmt = PIX_FMT_YUYV422,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_YUYV,
-    },
-    {
-        .ff_fmt = PIX_FMT_UYVY422,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_UYVY,
-    },
-    {
-        .ff_fmt = PIX_FMT_YUV411P,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
-    },
-    {
-        .ff_fmt = PIX_FMT_YUV410P,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_YUV410,
-    },
-    {
-        .ff_fmt = PIX_FMT_RGB555,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_RGB555,
-    },
-    {
-        .ff_fmt = PIX_FMT_RGB565,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_RGB565,
-    },
-    {
-        .ff_fmt = PIX_FMT_BGR24,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_BGR24,
-    },
-    {
-        .ff_fmt = PIX_FMT_RGB24,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_RGB24,
-    },
-    {
-        .ff_fmt = PIX_FMT_BGRA,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_BGR32,
-    },
-    {
-        .ff_fmt = PIX_FMT_GRAY8,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_GREY,
-    },
-    {
-        .ff_fmt = PIX_FMT_NV12,
-        .codec_id = CODEC_ID_RAWVIDEO,
-        .v4l2_fmt = V4L2_PIX_FMT_NV12,
-    },
-    {
-        .ff_fmt = PIX_FMT_NONE,
-        .codec_id = CODEC_ID_MJPEG,
-        .v4l2_fmt = V4L2_PIX_FMT_MJPEG,
-    },
-    {
-        .ff_fmt = PIX_FMT_NONE,
-        .codec_id = CODEC_ID_MJPEG,
-        .v4l2_fmt = V4L2_PIX_FMT_JPEG,
-    },
+    //ff_fmt           codec_id           v4l2_fmt
+    { PIX_FMT_YUV420P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV420  },
+    { PIX_FMT_YUV422P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV422P },
+    { PIX_FMT_YUYV422, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUYV    },
+    { PIX_FMT_UYVY422, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_UYVY    },
+    { PIX_FMT_YUV411P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV411P },
+    { PIX_FMT_YUV410P, CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV410  },
+    { PIX_FMT_RGB555,  CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB555  },
+    { PIX_FMT_RGB565,  CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB565  },
+    { PIX_FMT_BGR24,   CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR24   },
+    { PIX_FMT_RGB24,   CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB24   },
+    { PIX_FMT_BGRA,    CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR32   },
+    { PIX_FMT_GRAY8,   CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_GREY    },
+    { PIX_FMT_NV12,    CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12    },
+    { PIX_FMT_NONE,    CODEC_ID_MJPEG,    V4L2_PIX_FMT_MJPEG   },
+    { PIX_FMT_NONE,    CODEC_ID_MJPEG,    V4L2_PIX_FMT_JPEG    },
 };
 
 static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
@@ -383,7 +324,7 @@ static void mmap_release_buffer(AVPacket *pkt)
 
     res = ioctl(fd, VIDIOC_QBUF, &buf);
     if (res < 0) {
-        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
+        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
     }
     pkt->data = NULL;
     pkt->size = 0;
@@ -501,8 +442,12 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
     struct video_data *s = s1->priv_data;
     struct v4l2_input input;
     struct v4l2_standard standard;
+    struct v4l2_streamparm streamparm = { 0 };
+    struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
     int i;
 
+    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
     if (ap->channel>=0) {
         /* set tv video input */
         memset (&input, 0, sizeof (input));
@@ -548,6 +493,35 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
         }
     }
 
+    if (ap->time_base.num && ap->time_base.den) {
+        av_log(s1, AV_LOG_DEBUG, "Setting time per frame to %d/%d\n",
+               ap->time_base.num, ap->time_base.den);
+        tpf->numerator = ap->time_base.num;
+        tpf->denominator = ap->time_base.den;
+        if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
+            av_log(s1, AV_LOG_ERROR,
+                   "ioctl set time per frame(%d/%d) failed\n",
+                   ap->time_base.num, ap->time_base.den);
+            return AVERROR(EIO);
+        }
+
+        if (ap->time_base.den != tpf->denominator ||
+            ap->time_base.num != tpf->numerator) {
+            av_log(s1, AV_LOG_INFO,
+                   "The driver changed the time per frame from %d/%d to %d/%d\n",
+                   ap->time_base.num, ap->time_base.den,
+                   tpf->numerator, tpf->denominator);
+        }
+    } else {
+        /* if timebase value is not set in ap, read the timebase value from the driver */
+        if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
+            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno));
+            return AVERROR(errno);
+        }
+    }
+    ap->time_base.num = tpf->numerator;
+    ap->time_base.den = tpf->denominator;
+
     return 0;
 }
 
@@ -706,7 +680,7 @@ static int v4l2_read_close(AVFormatContext *s1)
     return 0;
 }
 
-AVInputFormat v4l2_demuxer = {
+AVInputFormat ff_v4l2_demuxer = {
     "video4linux2",
     NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
     sizeof(struct video_data),