On Thursday, October 10, 2013, John Stebbins wrote:

> This can be optionally disabled whith the "showall" flags2 option.
> When in "showall" mode, incomplete frames are signalled through
> AVFrame.flags FRAME_FLAG_INCOMPLETE_FRAME.
> ---
>  libavcodec/avcodec.h       |  1 +
>  libavcodec/h264.c          | 44
> ++++++++++++++++++++++++++++++++++++++++----
>  libavcodec/h264.h          |  9 +++++++++
>  libavcodec/mpegvideo.h     |  1 +
>  libavcodec/options_table.h |  1 +
>  libavutil/frame.c          |  1 +
>  libavutil/frame.h          |  3 +++
>  7 files changed, 56 insertions(+), 4 deletions(-)
>
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index d535308..c76680d 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -660,6 +660,7 @@ typedef struct RcOverride{
>  #define CODEC_FLAG2_IGNORE_CROP   0x00010000 ///< Discard cropping
> information from SPS.
>
>  #define CODEC_FLAG2_CHUNKS        0x00008000 ///< Input bitstream might
> be truncated at a packet boundaries instead of only at frame boundaries.
> +#define CODEC_FLAG2_SHOW_ALL      0x00400000 ///< Show all frames before
> the first keyframe


It'd nice if you bumped _MICRO version because of this flag.


>
>  /* Unsupported options :
>   *              Syntax Arithmetic coding (SAC)
> diff --git a/libavcodec/h264.c b/libavcodec/h264.c
> index 7311e6a..0024b33 100644
> --- a/libavcodec/h264.c
> +++ b/libavcodec/h264.c
> @@ -336,6 +336,7 @@ static int ref_picture(H264Context *h, Picture *dst,
> Picture *src)
>      dst->field_picture = src->field_picture;
>      dst->needs_realloc = src->needs_realloc;
>      dst->reference     = src->reference;
> +    dst->recovered     = src->recovered;
>
>      return 0;
>  fail:
> @@ -1560,6 +1561,8 @@ av_cold int ff_h264_decode_init(AVCodecContext
> *avctx)
>      h->prev_poc_msb = 1 << 16;
>      h->x264_build   = -1;
>      ff_h264_reset_sei(h);
> +    h->recovery_frame = -1;
> +    h->frame_recovered = 0;
>      if (avctx->codec_id == AV_CODEC_ID_H264) {
>          if (avctx->ticks_per_frame == 1)
>              h->avctx->time_base.den *= 2;
> @@ -1830,6 +1833,9 @@ static int
> decode_update_thread_context(AVCodecContext *dst,
>      h->prev_frame_num        = h->frame_num;
>      h->outputed_poc          = h->next_outputed_poc;
>
> +    h->recovery_frame        = h1->recovery_frame;
> +    h->frame_recovered       = h1->frame_recovered;
> +
>      return err;
>  }
>
> @@ -1859,6 +1865,7 @@ static int h264_frame_start(H264Context *h)
>       */
>      pic->f.key_frame = 0;
>      pic->mmco_reset  = 0;
> +    pic->recovered   = 0;
>
>      if ((ret = alloc_picture(h, pic)) < 0)
>          return ret;
> @@ -2130,6 +2137,15 @@ static void decode_postinit(H264Context *h, int
> setup_finished)
>          av_log(h->avctx, AV_LOG_DEBUG, "no picture\n");
>      }
>
> +    if (h->next_output_pic) {
> +        if (h->next_output_pic->recovered) {
> +            // Setting bit 0 means we have reached an recovery point and
> all
> +            // frames after it in display order are "recovered".
> +            h->frame_recovered |= 1;
> +        }
> +        h->next_output_pic->recovered |= !!(h->frame_recovered & 1);
> +    }
> +
>      if (setup_finished && !h->avctx->hwaccel)
>          ff_thread_finish_setup(h->avctx);
>  }
> @@ -2711,6 +2727,8 @@ static void flush_change(H264Context *h)
>      memset(h->default_ref_list[0], 0, sizeof(h->default_ref_list[0]));
>      memset(h->default_ref_list[1], 0, sizeof(h->default_ref_list[1]));
>      ff_h264_reset_sei(h);
> +    h->recovery_frame = -1;
> +    h->frame_recovered = 0;
>  }
>
>  /* forget old pics after a seek */
> @@ -4587,10 +4605,26 @@ again:
>                  if ((err = decode_slice_header(hx, h)))
>                      break;
>
> +                if (h->sei_recovery_frame_cnt >= 0 && h->recovery_frame <
> 0) {
> +                    h->recovery_frame =
> +                        (h->frame_num + h->sei_recovery_frame_cnt) %
> +                        (1 << h->sps.log2_max_frame_num);
> +                }
> +
>                  h->cur_pic_ptr->f.key_frame |=
>                      (hx->nal_unit_type == NAL_IDR_SLICE) ||
>                      (h->sei_recovery_frame_cnt >= 0);
>
> +                if (hx->nal_unit_type == NAL_IDR_SLICE ||
> +                    h->recovery_frame == h->frame_num) {
> +                    h->recovery_frame = -1;
> +                    h->cur_pic_ptr->recovered = 1;
> +                }
> +                // Setting bit 1 means we have seen an IDR and all frames
> +                // after it in decoded order are "recovered".
> +                h->frame_recovered |= 2 * !!(hx->nal_unit_type ==
> NAL_IDR_SLICE);
> +                h->cur_pic_ptr->recovered |= !!(h->frame_recovered & 2);
> +
>                  if (h->current_slice == 1) {
>                      if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS))
>                          decode_postinit(h, nal_index >= nals_needed);
> @@ -4820,10 +4854,12 @@ out:
>
>          field_end(h, 0);
>
> -        if (!h->next_output_pic) {
> -            /* Wait for second field. */
> -            *got_frame = 0;
> -        } else {
> +        /* Wait for second field. */
> +        *got_frame = 0;
> +        if (h->next_output_pic && ((avctx->flags2 & CODEC_FLAG2_SHOW_ALL)
> ||
> +            h->next_output_pic->recovered)) {
> +            if (!h->next_output_pic->recovered)
> +                h->next_output_pic->f.flags |=
> FRAME_FLAG_INCOMPLETE_FRAME;
>              ret = output_frame(h, pict, &h->next_output_pic->f);
>              if (ret < 0)
>                  return ret;
> diff --git a/libavcodec/h264.h b/libavcodec/h264.h
> index 3ef8420..0fe9921 100644
> --- a/libavcodec/h264.h
> +++ b/libavcodec/h264.h
> @@ -611,6 +611,15 @@ typedef struct H264Context {
>       */
>      int sei_recovery_frame_cnt;
>
> +    /**
> +     * recovery_frame is the frame_num at which the next frame should
> +     * be fully constructed.
> +     *
> +     * Set to -1 when not expecting a recovery point.
> +     */
> +    int recovery_frame;
> +    int frame_recovered;    ///< Initial frame has been completely
> recovered
> +
>      int luma_weight_flag[2];    ///< 7.4.3.2 luma_weight_lX_flag
>      int chroma_weight_flag[2];  ///< 7.4.3.2 chroma_weight_lX_flag
>
> diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
> index 81e3d2b..48b3cae 100644
> --- a/libavcodec/mpegvideo.h
> +++ b/libavcodec/mpegvideo.h
> @@ -172,6 +172,7 @@ typedef struct Picture{
>
>      int reference;
>      int shared;
> +    int recovered;              ///< Picture at IDR or recovery point +
> recovery count
>  } Picture;


I'm not sure I understand why this is needed here, AVFrame seems enough to
store recovery information no?


>
>  /**
> diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
> index 5e9d484..9113272 100644
> --- a/libavcodec/options_table.h
> +++ b/libavcodec/options_table.h
> @@ -72,6 +72,7 @@ static const AVOption avcodec_options[] = {
>  {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 =
> CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"},
>  {"ignorecrop", "ignore cropping information from sps", 1,
> AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX,
> V|D, "flags2"},
>  {"local_header", "place global headers at every keyframe instead of in
> extradata", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_LOCAL_HEADER },
> INT_MIN, INT_MAX, V|E, "flags2"},
> +{"showall", "Show all frames before the first keyframe", 0,
> AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D,
> "flags2"},
>  {"me_method", "set motion estimation method", OFFSET(me_method),
> AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"},
>  {"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64
> = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" },
>  {"full", "full motion estimation (slowest)", 0, AV_OPT_TYPE_CONST, {.i64
> = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" },
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index 098bbed..78bad66 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -379,6 +379,7 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame
> *src)
>      dst->quality             = src->quality;
>      dst->coded_picture_number = src->coded_picture_number;
>      dst->display_picture_number = src->display_picture_number;
> +    dst->flags               = src->flags;
>
>      memcpy(dst->error, src->error, sizeof(dst->error));
>
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index b0676e7..19fdc1b 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -350,6 +350,9 @@ typedef struct AVFrame {
>
>      AVFrameSideData **side_data;
>      int            nb_side_data;
> +
> +    int flags;
> +#define FRAME_FLAG_INCOMPLETE_FRAME 0x0001
>  } AVFrame;


I adding the flag here breaks ABI; this kind on data should go in side_data
in my opinion. Also you always set this flag but never read it, is this the
intended behavior?

Vittorio


>
>  /**
> --
> 1.8.3.1
>
> _______________________________________________
> libav-devel mailing list
> [email protected] <javascript:;>
> https://lists.libav.org/mailman/listinfo/libav-devel
>
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to