Browse code

lavd/v4l2: correctly handle error conditions in mmap_read_frame()

In particular:

1) save errno before it (possibly) gets overwritten by other calls
2) do not forget to enqueue the buffer again in case of error

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Giorgio Vazzana authored on 2013/03/09 22:36:56
Showing 1 changed files
... ...
@@ -610,15 +610,17 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
610 610
         res = av_new_packet(pkt, buf.bytesused);
611 611
         if (res < 0) {
612 612
             av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
613
+            if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
614
+                avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
613 615
             return res;
614 616
         }
615 617
         memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);
616 618
 
617
-        res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
618
-        if (res < 0) {
619
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
619
+        if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
620
+            res = AVERROR(errno);
621
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
620 622
             av_free_packet(pkt);
621
-            return AVERROR(errno);
623
+            return res;
622 624
         }
623 625
         avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
624 626
     } else {
... ...
@@ -636,7 +638,8 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
636 636
              * allocate a buffer for memcpying into it
637 637
              */
638 638
             av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
639
-            res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
639
+            if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
640
+                avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
640 641
 
641 642
             return AVERROR(ENOMEM);
642 643
         }
... ...
@@ -647,6 +650,9 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
647 647
         pkt->buf = av_buffer_create(pkt->data, pkt->size, mmap_release_buffer,
648 648
                                     buf_descriptor, 0);
649 649
         if (!pkt->buf) {
650
+            av_log(ctx, AV_LOG_ERROR, "Failed to create a buffer\n");
651
+            if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
652
+                avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
650 653
             av_freep(&buf_descriptor);
651 654
             return AVERROR(ENOMEM);
652 655
         }