[FFmpeg-devel] [PATCH] libavcodec/h261dec: Fix keyframe markup and frame skipping.

Andrey Semashev andrey.semashev at gmail.com
Tue Oct 29 15:39:16 EET 2019


On 2019-10-26 14:05, Andrey Semashev wrote:
> The decoder never marks pictures as I-frames, which results in no
> keyframe indication and incorrect frame skipping, in cases when
> keyframes should be decoded.
> 
> This commit works around this decoder limitation and marks I-frames
> and keyframes based on "freeze picture release" bit in h261 picture
> header. This reflects h261enc behavior.

So, is this patch acceptable? If yes, could someone merge it please?

> ---
>   libavcodec/h261.h    |  1 +
>   libavcodec/h261dec.c | 27 ++++++++++++++++++---------
>   2 files changed, 19 insertions(+), 9 deletions(-)
> 
> diff --git a/libavcodec/h261.h b/libavcodec/h261.h
> index 399a404b2b..6662d38d6d 100644
> --- a/libavcodec/h261.h
> +++ b/libavcodec/h261.h
> @@ -37,6 +37,7 @@
>   typedef struct H261Context {
>       MpegEncContext s;
>   
> +    int freeze_picture_release; // 1 if freeze picture release bit is set in the picture header
>       int current_mba;
>       int mba_diff;
>       int mtype;
> diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
> index 14a874c45d..3b1711a21d 100644
> --- a/libavcodec/h261dec.c
> +++ b/libavcodec/h261dec.c
> @@ -502,9 +502,9 @@ static int h261_decode_picture_header(H261Context *h)
>       s->avctx->framerate = (AVRational) { 30000, 1001 };
>   
>       /* PTYPE starts here */
> -    skip_bits1(&s->gb); /* split screen off */
> -    skip_bits1(&s->gb); /* camera  off */
> -    skip_bits1(&s->gb); /* freeze picture release off */
> +    skip_bits1(&s->gb); /* split screen indicator */
> +    skip_bits1(&s->gb); /* document camera indicator */
> +    h->freeze_picture_release = get_bits1(&s->gb); /* freeze picture release */
>   
>       format = get_bits1(&s->gb);
>   
> @@ -532,7 +532,8 @@ static int h261_decode_picture_header(H261Context *h)
>   
>       /* H.261 has no I-frames, but if we pass AV_PICTURE_TYPE_I for the first
>        * frame, the codec crashes if it does not contain all I-blocks
> -     * (e.g. when a packet is lost). */
> +     * (e.g. when a packet is lost). We will fix the picture type in the
> +     * output frame based on h->freeze_picture_release later. */
>       s->pict_type = AV_PICTURE_TYPE_P;
>   
>       h->gob_number = 0;
> @@ -590,6 +591,7 @@ static int h261_decode_frame(AVCodecContext *avctx, void *data,
>       H261Context *h     = avctx->priv_data;
>       MpegEncContext *s  = &h->s;
>       int ret;
> +    enum AVPictureType pict_type;
>       AVFrame *pict = data;
>   
>       ff_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size);
> @@ -630,15 +632,17 @@ retry:
>           goto retry;
>       }
>   
> -    // for skipping the frame
> -    s->current_picture.f->pict_type = s->pict_type;
> -    s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I;
> +    // for skipping the frame and keyframe markup
> +    pict_type = h->freeze_picture_release ? AV_PICTURE_TYPE_I : s->pict_type;
>   
> -    if ((avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B) ||
> -        (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I) ||
> +    if ((avctx->skip_frame >= AVDISCARD_NONREF && pict_type == AV_PICTURE_TYPE_B) ||
> +        (avctx->skip_frame >= AVDISCARD_NONKEY && pict_type != AV_PICTURE_TYPE_I) ||
>            avctx->skip_frame >= AVDISCARD_ALL)
>           return get_consumed_bytes(s, buf_size);
>   
> +    s->current_picture.f->pict_type = s->pict_type;
> +    s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I;
> +
>       if (ff_mpv_frame_start(s, avctx) < 0)
>           return -1;
>   
> @@ -660,6 +664,11 @@ retry:
>   
>       if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0)
>           return ret;
> +
> +    // fix picture type and correctly mark keyframes
> +    pict->pict_type = pict_type;
> +    pict->key_frame = pict_type == AV_PICTURE_TYPE_I;
> +
>       ff_print_debug_info(s, s->current_picture_ptr, pict);
>   
>       *got_frame = 1;
> 



More information about the ffmpeg-devel mailing list