Ticket #7687: 0001-avcodec-omx-Fix-handling-of-fragmented-buffers.patch

File 0001-avcodec-omx-Fix-handling-of-fragmented-buffers.patch, 2.5 KB (added by 6by9, 8 years ago)

The attached patch solves the issue by adopting waiting in get_buffer if we've had a partial frame.

  • libavcodec/omx.c

    From e729ce6f24d3bc850c9dfdbd8684d1a54864df2b Mon Sep 17 00:00:00 2001
    From: Dave Stevenson <dave.stevenson@raspberrypi.org>
    Date: Thu, 17 Jan 2019 17:39:34 +0000
    Subject: [PATCH] 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: Dave Stevenson <dave.stevenson@raspberrypi.org>
    ---
     libavcodec/omx.c | 6 +++++-
     1 file changed, 5 insertions(+), 1 deletion(-)
    
    diff --git a/libavcodec/omx.c b/libavcodec/omx.c
    index 466e0be..e813362 100644
    a b static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,  
    739739    int ret = 0;
    740740    OMX_BUFFERHEADERTYPE* buffer;
    741741    OMX_ERRORTYPE err;
     742    int had_partial = 0;
    742743
    743744    if (frame) {
    744745        uint8_t *dst[4];
    … … static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,  
    830831        // packet, or get EOS.
    831832        buffer = get_buffer(&s->output_mutex, &s->output_cond,
    832833                            &s->num_done_out_buffers, s->done_out_buffers,
    833                             !frame);
     834                            !frame || had_partial);
    834835        if (!buffer)
    835836            break;
    836837
    … … static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,  
    865866                    s->output_buf = NULL;
    866867                    s->output_buf_size = 0;
    867868                }
     869#if CONFIG_OMX_RPI
     870                had_partial = 1;
     871#endif
    868872            } else {
    869873                // End of frame, and the caller provided a preallocated frame
    870874                if ((ret = ff_alloc_packet2(avctx, pkt, s->output_buf_size + buffer->nFilledLen, 0)) < 0) {