diff options
author | Giorgio Vazzana <mywing81@gmail.com> | 2014-09-01 22:20:05 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-09-06 00:05:59 +0200 |
commit | d7e088849e33fc339ab14d3d10ada241c50880c1 (patch) | |
tree | 1b1cb413d5f1bfbaa70a5c09fd9d0cbf2f35eb97 | |
parent | c368538667121fb20c5414dfaf0fb273035a0854 (diff) | |
download | ffmpeg-d7e088849e33fc339ab14d3d10ada241c50880c1.tar.gz |
lavd/v4l2: introduce enqueue_buffer()
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>
-rw-r--r-- | libavdevice/v4l2.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index b473f7e6a3..cf7a92cdd4 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -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); } |