Commit 3d857f21 authored by Dave Stevenson's avatar Dave Stevenson Committed by Aman Gupta

avcodec/omx: Fix handling of fragmented buffers

See https://trac.ffmpeg.org/ticket/7687

If an encoded frame is returned split over two or more
IL buffers due to the size, then there is a race between
whether get_buffer will fail, return NULL, and a truncated
frame is passed on, or IL will return the remaining part
of the encoded frame.
If get_buffer returns NULL, part of the frame is left behind
in the codec, and will be collected on the next call. That
then leaves a frame stuck in the codec. Repeat enough times
and the codec FIFO is full, and the pipeline stalls.

A performance improvement in the Raspberry Pi firmware means
that the timing has changed, and now frequently drops into the
case where get_buffer returns NULL.

Add code such that should a buffer be received without
OMX_BUFFERFLAG_ENDOFFRAME that get_buffer is called with wait
set, so we wait for the remainder of the frame.
This code has been made conditional on the Pi build in case
other IL implementations don't handle ENDOFFRAME correctly.
Signed-off-by: 's avatarDave Stevenson <dave.stevenson@raspberrypi.org>
Signed-off-by: 's avatarAman Gupta <aman@tmm1.net>
Signed-off-by: 's avatarMartin Storsjö <martin@martin.st>
parent 23a3e146
...@@ -735,6 +735,7 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ...@@ -735,6 +735,7 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
int ret = 0; int ret = 0;
OMX_BUFFERHEADERTYPE* buffer; OMX_BUFFERHEADERTYPE* buffer;
OMX_ERRORTYPE err; OMX_ERRORTYPE err;
int had_partial = 0;
if (frame) { if (frame) {
uint8_t *dst[4]; uint8_t *dst[4];
...@@ -846,7 +847,7 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ...@@ -846,7 +847,7 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
// packet, or get EOS. // packet, or get EOS.
buffer = get_buffer(&s->output_mutex, &s->output_cond, buffer = get_buffer(&s->output_mutex, &s->output_cond,
&s->num_done_out_buffers, s->done_out_buffers, &s->num_done_out_buffers, s->done_out_buffers,
!frame); !frame || had_partial);
if (!buffer) if (!buffer)
break; break;
...@@ -881,6 +882,9 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ...@@ -881,6 +882,9 @@ static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
s->output_buf = NULL; s->output_buf = NULL;
s->output_buf_size = 0; s->output_buf_size = 0;
} }
#if CONFIG_OMX_RPI
had_partial = 1;
#endif
} else { } else {
// End of frame, and the caller provided a preallocated frame // End of frame, and the caller provided a preallocated frame
if ((ret = ff_alloc_packet2(avctx, pkt, s->output_buf_size + buffer->nFilledLen, 0)) < 0) { if ((ret = ff_alloc_packet2(avctx, pkt, s->output_buf_size + buffer->nFilledLen, 0)) < 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment