lavd/v4l2: introduce enqueue_buffer()
authorGiorgio Vazzana <mywing81@gmail.com>
Mon, 1 Sep 2014 20:20:05 +0000 (22:20 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 5 Sep 2014 22:05:59 +0000 (00:05 +0200)
Additionally, make sure a buffer gets enqueued again (even in error paths) after
it has been succesfully dequeued.

Tested-by: Dmitry Volyntsev <xeioexception@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavdevice/v4l2.c

index b473f7e..cf7a92c 100644 (file)
@@ -399,10 +399,23 @@ static void dummy_release_buffer(AVPacket *pkt)
 }
 #endif
 
+static int enqueue_buffer(struct video_data *s, struct v4l2_buffer *buf)
+{
+    int res = 0;
+
+    if (v4l2_ioctl(s->fd, VIDIOC_QBUF, buf) < 0) {
+        res = AVERROR(errno);
+        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
+    } else {
+        avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
+    }
+
+    return res;
+}
+
 static void mmap_release_buffer(void *opaque, uint8_t *data)
 {
     struct v4l2_buffer buf = { 0 };
-    int res;
     struct buff_data *buf_descriptor = opaque;
     struct video_data *s = buf_descriptor->s;
 
@@ -411,13 +424,7 @@ static void mmap_release_buffer(void *opaque, uint8_t *data)
     buf.index = buf_descriptor->index;
     av_free(buf_descriptor);
 
-    if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
-        res = AVERROR(errno);
-        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
-               av_err2str(res));
-    }
-
-    avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
+    enqueue_buffer(s, &buf);
 }
 
 #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
@@ -520,6 +527,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
         av_log(ctx, AV_LOG_ERROR,
                "The v4l2 frame is %d bytes, but %d bytes are expected\n",
                buf.bytesused, s->frame_size);
+        enqueue_buffer(s, &buf);
         return AVERROR_INVALIDDATA;
     }
 
@@ -529,19 +537,16 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
         res = av_new_packet(pkt, buf.bytesused);
         if (res < 0) {
             av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
-            if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
-                avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
+            enqueue_buffer(s, &buf);
             return res;
         }
         memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);
 
-        if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
-            res = AVERROR(errno);
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
+        res = enqueue_buffer(s, &buf);
+        if (res) {
             av_free_packet(pkt);
             return res;
         }
-        avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
     } else {
         struct buff_data *buf_descriptor;
 
@@ -559,8 +564,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
              * allocate a buffer for memcpying into it
              */
             av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
-            if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
-                avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
+            enqueue_buffer(s, &buf);
 
             return AVERROR(ENOMEM);
         }
@@ -571,8 +575,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                                     buf_descriptor, 0);
         if (!pkt->buf) {
             av_log(ctx, AV_LOG_ERROR, "Failed to create a buffer\n");
-            if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
-                avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
+            enqueue_buffer(s, &buf);
             av_freep(&buf_descriptor);
             return AVERROR(ENOMEM);
         }