aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndriy Gelman <andriy.gelman@gmail.com>2020-08-23 13:33:37 -0400
committerAndriy Gelman <andriy.gelman@gmail.com>2020-08-23 13:42:07 -0400
commit8bc7f69cefbcbb265b41717608dc8436dc864a55 (patch)
tree3d2de02c4d41984956f1aee890d12da3058c0d3a
parent994d2567f13c11422aeb6506b6afca42a900d620 (diff)
downloadffmpeg-8bc7f69cefbcbb265b41717608dc8436dc864a55.tar.gz
avcodec/v4l2_m2m_enc: buffer frame if it cannot be enqueued
Currently if the frame buffers are full, the frame is unrefed and dropped. Instead buffer the frame so that it is enqueued in the next v4l2_receive_packet() call. The behavior was observed on DragonBoard 410c. Signed-off-by: Andriy Gelman <andriy.gelman@gmail.com>
-rw-r--r--libavcodec/v4l2_m2m.c1
-rw-r--r--libavcodec/v4l2_m2m_enc.c8
2 files changed, 7 insertions, 2 deletions
diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c
index 31600617fd..cdfd579810 100644
--- a/libavcodec/v4l2_m2m.c
+++ b/libavcodec/v4l2_m2m.c
@@ -329,6 +329,7 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context)
sem_destroy(&s->refsync);
close(s->fd);
+ av_frame_unref(s->frame);
av_frame_free(&s->frame);
av_packet_unref(&s->buf_pkt);
diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c
index af0ed1e306..4230a415fd 100644
--- a/libavcodec/v4l2_m2m_enc.c
+++ b/libavcodec/v4l2_m2m_enc.c
@@ -295,16 +295,20 @@ static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
if (s->draining)
goto dequeue;
+ if (!frame->buf[0]) {
ret = ff_encode_get_frame(avctx, frame);
if (ret < 0 && ret != AVERROR_EOF)
return ret;
if (ret == AVERROR_EOF)
frame = NULL;
+ }
ret = v4l2_send_frame(avctx, frame);
- av_frame_unref(frame);
- if (ret < 0)
+ if (ret != AVERROR(EAGAIN))
+ av_frame_unref(frame);
+
+ if (ret < 0 && ret != AVERROR(EAGAIN))
return ret;
if (!output->streamon) {