[FFmpeg-devel] [PATCH] avcodec/qtrle: return last frame even if unchanged

Marton Balint cus at passwd.hu
Thu May 16 22:29:26 EEST 2019


On Wed, 15 May 2019, Michael Niedermayer wrote:

> Fixes: Ticket7880
>
> Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
> ---
> libavcodec/qtrle.c        | 27 +++++++++++++++++++++++++--
> tests/ref/fate/qtrle-8bit |  1 +
> 2 files changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
> index 2c29547e5a..11226cb842 100644
> --- a/libavcodec/qtrle.c
> +++ b/libavcodec/qtrle.c
> @@ -45,6 +45,7 @@ typedef struct QtrleContext {
>
>     GetByteContext g;
>     uint32_t pal[256];
> +    int need_flush;
> } QtrleContext;
> 
> #define CHECK_PIXEL_PTR(n)                                                            \
> @@ -444,6 +445,12 @@ static av_cold int qtrle_decode_init(AVCodecContext *avctx)
>     return 0;
> }
> 
> +static void qtrle_flush(AVCodecContext *avctx){
> +    QtrleContext *s = avctx->priv_data;
> +
> +    s->need_flush = 0;
> +}
> +
> static int qtrle_decode_frame(AVCodecContext *avctx,
>                               void *data, int *got_frame,
>                               AVPacket *avpkt)
> @@ -454,11 +461,26 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
>     int has_palette = 0;
>     int ret, size;
> 
> +    if (!avpkt->data) {
> +        if (s->need_flush) {
> +            s->need_flush = 0;
> +            if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
> +                return ret;
> +            if ((ret = av_frame_ref(data, s->frame)) < 0)
> +                return ret;
> +            *got_frame = 1;
> +        }
> +        return 0;
> +    }
> +
>     bytestream2_init(&s->g, avpkt->data, avpkt->size);
>
>     /* check if this frame is even supposed to change */
> -    if (avpkt->size < 8)
> +    if (avpkt->size < 8) {
> +        s->need_flush = 1;

You probably have to set need_flush for the other two cases where you 
return avpkt->size for undersized packets.

>         return avpkt->size;
> +    }
> +    s->need_flush = 0;
>
>     /* start after the chunk size */
>     size = bytestream2_get_be32(&s->g) & 0x3FFFFFFF;
> @@ -572,5 +594,6 @@ AVCodec ff_qtrle_decoder = {
>     .init           = qtrle_decode_init,
>     .close          = qtrle_decode_end,
>     .decode         = qtrle_decode_frame,
> -    .capabilities   = AV_CODEC_CAP_DR1,
> +    .flush          = qtrle_flush,
> +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
> };
> diff --git a/tests/ref/fate/qtrle-8bit b/tests/ref/fate/qtrle-8bit
> index 27bb8aad71..39a03b7b6c 100644
> --- a/tests/ref/fate/qtrle-8bit
> +++ b/tests/ref/fate/qtrle-8bit
> @@ -61,3 +61,4 @@
> 0,        160,        160,        1,   921600, 0xcfd6ad2b
> 0,        163,        163,        1,   921600, 0x3b372379
> 0,        165,        165,        1,   921600, 0x36f245f5
> +0,        166,        166,        1,   921600, 0x36f245f5
> --

I tested your patch and it looks like pkt_dts and pkt_pos is lost for the 
last frame. Having no pkt_dts can be an issue later, because pkt_pts is 
already deprecated.

Regards,
Marton


More information about the ffmpeg-devel mailing list