[FFmpeg-devel] [PATCH v2] lavc/vvc: Use a bitfield to store MIP information

Nuo Mi nuomi2021 at gmail.com
Sat Dec 7 11:42:24 EET 2024


Applied.
Thank you, Frank

On Wed, Dec 4, 2024 at 4:57 AM Frank Plowman <post at frankplowman.com> wrote:

> Reduces memory consumption by ~4MB for 1080p video with a maximum delay
> of 16 frames by packing various information related to MIP:
> * intra_mip_flag, 1 bit
> * intra_mip_transposed_flag, 1 bit
> * intra_mip_mode, 4 bits
> Into a single byte.
>
> Co-authored-by: Nuo Mi <nuomi2021 at gmail.com>
> Signed-off-by: Frank Plowman <post at frankplowman.com>
> ---
> Changes since v1 (posted as attachment in other thread).
> * Renamed (de)?structure_mip_info to (un)?pack_mip_info
> * Remove coerce_to_bool argument added to get_inc.  Instead, define a
>   variant of get_inc, get_mip_inc, particular to the MIP flag which
>   performs the necessary transformations.
>
> I did also try implementing this patch as I mentioned I might on the
> other thread: by adding a function pointer argument to get_inc and
> get_left_top which can be used to transform values read from tables
> before they are used.  I realised while doing so, however, that there is
> really no need for such complexity for get_left_top as it returns left
> and top separately, hence the caller can simply transform them itself.
> Then, get_inc is very simple and only called in two places, and so it is
> not fitting to employ such heavy-duty abstractions only for that
> function.
>
> ---
>  libavcodec/vvc/cabac.c          | 10 +++++++++-
>  libavcodec/vvc/ctu.c            | 12 +++++++++---
>  libavcodec/vvc/dec.c            |  2 --
>  libavcodec/vvc/dec.h            |  4 +---
>  libavcodec/vvc/dsp.c            |  9 +++++++++
>  libavcodec/vvc/intra_template.c |  5 +++--
>  6 files changed, 31 insertions(+), 11 deletions(-)
>
> diff --git a/libavcodec/vvc/cabac.c b/libavcodec/vvc/cabac.c
> index 0d45eec751..5510144893 100644
> --- a/libavcodec/vvc/cabac.c
> +++ b/libavcodec/vvc/cabac.c
> @@ -1257,11 +1257,19 @@ int ff_vvc_pred_mode_ibc_flag(VVCLocalContext *lc,
> const int is_chroma)
>      return GET_CABAC(PRED_MODE_IBC_FLAG + inc);
>  }
>
> +static av_always_inline
> +uint8_t get_mip_inc(VVCLocalContext *lc, const uint8_t *ctx)
> +{
> +    uint8_t left = 0, top = 0;
> +    get_left_top(lc, &left, &top, lc->cu->x0, lc->cu->y0, ctx, ctx);
> +    return (left & 1) + (top & 1);
> +}
> +
>  int ff_vvc_intra_mip_flag(VVCLocalContext *lc, const uint8_t
> *intra_mip_flag)
>  {
>      const int w   = lc->cu->cb_width;
>      const int h   = lc->cu->cb_height;
> -    const int inc =  (w > h * 2 || h > w * 2) ? 3 : get_inc(lc,
> intra_mip_flag);
> +    const int inc =  (w > h * 2 || h > w * 2) ? 3 : get_mip_inc(lc,
> intra_mip_flag);
>      return GET_CABAC(INTRA_MIP_FLAG + inc);
>  }
>
> diff --git a/libavcodec/vvc/ctu.c b/libavcodec/vvc/ctu.c
> index 505099bc76..382fa582f4 100644
> --- a/libavcodec/vvc/ctu.c
> +++ b/libavcodec/vvc/ctu.c
> @@ -946,6 +946,12 @@ static void
> derive_chroma_intra_pred_mode(VVCLocalContext *lc,
>      }
>  }
>
> +static av_always_inline uint8_t pack_mip_info(int intra_mip_flag,
> +    int intra_mip_transposed_flag, int intra_mip_mode)
> +{
> +    return (intra_mip_mode << 2) | (intra_mip_transposed_flag << 1) |
> intra_mip_flag;
> +}
> +
>  static void intra_luma_pred_modes(VVCLocalContext *lc)
>  {
>      VVCFrameContext *fc             = lc->fc;
> @@ -974,9 +980,9 @@ static void intra_luma_pred_modes(VVCLocalContext *lc)
>              int x = y_cb * pps->min_cb_width + x_cb;
>              for (int y = 0; y < (cb_height>>log2_min_cb_size); y++) {
>                  int width = cb_width>>log2_min_cb_size;
> -                memset(&fc->tab.imf[x],  cu->intra_mip_flag, width);
> -                memset(&fc->tab.imtf[x], intra_mip_transposed_flag,
> width);
> -                memset(&fc->tab.imm[x], intra_mip_mode, width);
> +                const uint8_t mip_info = pack_mip_info(cu->intra_mip_flag,
> +                        intra_mip_transposed_flag, intra_mip_mode);
> +                memset(&fc->tab.imf[x], mip_info, width);
>                  x += pps->min_cb_width;
>              }
>              cu->intra_pred_mode_y = intra_mip_mode;
> diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
> index 50be9f9922..fef7339294 100644
> --- a/libavcodec/vvc/dec.c
> +++ b/libavcodec/vvc/dec.c
> @@ -128,7 +128,6 @@ static void min_cb_tl_init(TabList *l, VVCFrameContext
> *fc)
>      tl_init(l, 1, changed);
>
>      TL_ADD(imf,  pic_size_in_min_cb);
> -    TL_ADD(imm,  pic_size_in_min_cb);
>
>      for (int i = LUMA; i <= CHROMA; i++)
>          TL_ADD(cb_width[i],  pic_size_in_min_cb);   //is_a0_available
> requires this
> @@ -143,7 +142,6 @@ static void min_cb_nz_tl_init(TabList *l,
> VVCFrameContext *fc)
>      tl_init(l, 0, changed);
>
>      TL_ADD(skip, pic_size_in_min_cb);
> -    TL_ADD(imtf, pic_size_in_min_cb);
>      TL_ADD(ipm,  pic_size_in_min_cb);
>
>      for (int i = LUMA; i <= CHROMA; i++) {
> diff --git a/libavcodec/vvc/dec.h b/libavcodec/vvc/dec.h
> index f7cd5b678c..0f8f1f721d 100644
> --- a/libavcodec/vvc/dec.h
> +++ b/libavcodec/vvc/dec.h
> @@ -161,9 +161,7 @@ typedef struct VVCFrameContext {
>          uint8_t *skip;                                  ///<
> CuSkipFlag[][]
>          uint8_t *ispmf;                                 ///<
> intra_sub_partitions_mode_flag
>          uint8_t *msm[2];                                ///<
> MttSplitMode[][][] in 32 pixels
> -        uint8_t *imf;                                   ///<
> IntraMipFlag[][]
> -        uint8_t *imtf;                                  ///<
> intra_mip_transposed_flag[][]
> -        uint8_t *imm;                                   ///<
> intra_mip_mode[][]
> +        uint8_t *imf;                                   ///<
> IntraMipFlag[][], intra_mip_transposed_flag[][], intra_mip_mode[][]
>          uint8_t *ipm;                                   ///<
> IntraPredModeY[][]
>          uint8_t *cpm[2];                                ///<
> CuPredMode[][][]
>          uint8_t *msf;                                   ///<
> MergeSubblockFlag[][]
> diff --git a/libavcodec/vvc/dsp.c b/libavcodec/vvc/dsp.c
> index 9bfa46b03d..af392f2754 100644
> --- a/libavcodec/vvc/dsp.c
> +++ b/libavcodec/vvc/dsp.c
> @@ -44,6 +44,15 @@ static int vvc_sad(const int16_t *src0, const int16_t
> *src1, int dx, int dy,
>      return sad;
>  }
>
> +static av_always_inline void unpack_mip_info(int
> *intra_mip_transposed_flag,
> +    int *intra_mip_mode, const uint8_t mip_info)
> +{
> +    if (intra_mip_transposed_flag)
> +        *intra_mip_transposed_flag = (mip_info >> 1) & 0x1;
> +    if (intra_mip_mode)
> +        *intra_mip_mode = (mip_info >> 2) & 0xf;
> +}
> +
>  typedef struct IntraEdgeParams {
>      uint8_t* top;
>      uint8_t* left;
> diff --git a/libavcodec/vvc/intra_template.c
> b/libavcodec/vvc/intra_template.c
> index 62342c8142..440ac5b6cc 100644
> --- a/libavcodec/vvc/intra_template.c
> +++ b/libavcodec/vvc/intra_template.c
> @@ -627,8 +627,9 @@ static void FUNC(intra_pred)(const VVCLocalContext
> *lc, int x0, int y0,
>      FUNC(prepare_intra_edge_params)(lc, &edge, src, stride, x, y, w, h,
> c_idx, is_intra_mip, mode, ref_idx, need_pdpc);
>
>      if (is_intra_mip) {
> -        int intra_mip_transposed_flag = SAMPLE_CTB(fc->tab.imtf, x_cb,
> y_cb);
> -        int intra_mip_mode = SAMPLE_CTB(fc->tab.imm, x_cb, y_cb);
> +        int intra_mip_transposed_flag;
> +        int intra_mip_mode;
> +        unpack_mip_info(&intra_mip_transposed_flag, &intra_mip_mode,
> intra_mip_flag);
>
>          fc->vvcdsp.intra.pred_mip((uint8_t *)src, edge.top, edge.left,
>                          w, h, stride, intra_mip_mode,
> intra_mip_transposed_flag);
> --
> 2.47.0
>
>


More information about the ffmpeg-devel mailing list