You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
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>
This commit is contained in:
committed by
Michael Niedermayer
parent
c368538667
commit
d7e088849e
@@ -399,10 +399,23 @@ static void dummy_release_buffer(AVPacket *pkt)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
static void mmap_release_buffer(void *opaque, uint8_t *data)
|
||||||
{
|
{
|
||||||
struct v4l2_buffer buf = { 0 };
|
struct v4l2_buffer buf = { 0 };
|
||||||
int res;
|
|
||||||
struct buff_data *buf_descriptor = opaque;
|
struct buff_data *buf_descriptor = opaque;
|
||||||
struct video_data *s = buf_descriptor->s;
|
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;
|
buf.index = buf_descriptor->index;
|
||||||
av_free(buf_descriptor);
|
av_free(buf_descriptor);
|
||||||
|
|
||||||
if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
|
enqueue_buffer(s, &buf);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
|
#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,
|
av_log(ctx, AV_LOG_ERROR,
|
||||||
"The v4l2 frame is %d bytes, but %d bytes are expected\n",
|
"The v4l2 frame is %d bytes, but %d bytes are expected\n",
|
||||||
buf.bytesused, s->frame_size);
|
buf.bytesused, s->frame_size);
|
||||||
|
enqueue_buffer(s, &buf);
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,19 +537,16 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
|
|||||||
res = av_new_packet(pkt, buf.bytesused);
|
res = av_new_packet(pkt, buf.bytesused);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
|
av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
|
||||||
if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
|
enqueue_buffer(s, &buf);
|
||||||
avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);
|
memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);
|
||||||
|
|
||||||
if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
|
res = enqueue_buffer(s, &buf);
|
||||||
res = AVERROR(errno);
|
if (res) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
|
|
||||||
av_free_packet(pkt);
|
av_free_packet(pkt);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
|
|
||||||
} else {
|
} else {
|
||||||
struct buff_data *buf_descriptor;
|
struct buff_data *buf_descriptor;
|
||||||
|
|
||||||
@@ -559,8 +564,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
|||||||
* allocate a buffer for memcpying into it
|
* allocate a buffer for memcpying into it
|
||||||
*/
|
*/
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
|
av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
|
||||||
if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
|
enqueue_buffer(s, &buf);
|
||||||
avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
|
|
||||||
|
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
@@ -571,8 +575,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
|||||||
buf_descriptor, 0);
|
buf_descriptor, 0);
|
||||||
if (!pkt->buf) {
|
if (!pkt->buf) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to create a buffer\n");
|
av_log(ctx, AV_LOG_ERROR, "Failed to create a buffer\n");
|
||||||
if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) == 0)
|
enqueue_buffer(s, &buf);
|
||||||
avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
|
|
||||||
av_freep(&buf_descriptor);
|
av_freep(&buf_descriptor);
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user