[x265] [PATCH] Add Aom film grain characteristics as SEI message to the bitstream

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Fri Sep 27 12:33:06 UTC 2024


On Fri, Sep 27, 2024 at 3:35 PM Anusuya Kumarasamy <
anusuya.kumarasamy at multicorewareinc.com> wrote:

> From acb4ab5a4f14b7a88ccdf3bdc4b01ddf68fcec29 Mon Sep 17 00:00:00 2001
> From: Hazarath Kumar M <hazarathkumar at multicorewareinc.com>
> Date: Wed, 25 Sep 2024 14:35:27 +0530
> Subject: [PATCH 4/5] Add Aom film grain characteristics as SEI message to
> the
>  bitstream
>
> ---
>  doc/reST/cli.rst                |   4 +
>  source/common/param.cpp         |   7 ++
>  source/encoder/encoder.cpp      |  11 +++
>  source/encoder/encoder.h        |   2 +
>  source/encoder/frameencoder.cpp |  92 ++++++++++++++++++++++
>  source/encoder/frameencoder.h   |  31 ++++++++
>  source/encoder/sei.h            | 131 ++++++++++++++++++++++++++++++++
>  source/x265.h                   |   3 +
>  source/x265cli.cpp              |   1 +
>  source/x265cli.h                |   1 +
>  10 files changed, 283 insertions(+)
>
> diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
> index 95cb37f20..a4907f7d2 100755
> --- a/doc/reST/cli.rst
> +++ b/doc/reST/cli.rst
> @@ -2702,6 +2702,10 @@ Bitstream options
>
>      Refers to the film grain model characteristics for signal enhancement
> information transmission.
>
> +.. option:: --aom-film-grain <filename>
> +
> + Refers to the AOM film grain model characteristics
> +
>      **CLI_ONLY**
>
>  DCT Approximations
> diff --git a/source/common/param.cpp b/source/common/param.cpp
> index d08bb604e..ceef42589 100755
> --- a/source/common/param.cpp
> +++ b/source/common/param.cpp
> @@ -402,6 +402,7 @@ void x265_param_default(x265_param* param)
>  #endif
>      /* Film grain characteristics model filename */
>      param->filmGrain = NULL;
> +    param->aomFilmGrain = NULL;
>      param->bEnableSBRC = 0;
>
>      /* Multi-View Encoding*/
> @@ -1455,6 +1456,7 @@ int x265_param_parse(x265_param* p, const char*
> name, const char* value)
>          OPT("eos") p->bEnableEndOfSequence = atobool(value);
>          /* Film grain characterstics model filename */
>          OPT("film-grain") p->filmGrain = (char* )value;
> +        OPT("aom-film-grain") p->aomFilmGrain = (char*)value;
>          OPT("mcstf") p->bEnableTemporalFilter = atobool(value);
>          OPT("sbrc") p->bEnableSBRC = atobool(value);
>  #if ENABLE_ALPHA
> @@ -2403,6 +2405,8 @@ char *x265_param2string(x265_param* p, int padx, int
> pady)
>      BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");
>      if (p->filmGrain)
>          s += sprintf(s, " film-grain=%s", p->filmGrain); // Film grain
> characteristics model filename
> +    if (p->aomFilmGrain)
> +        s += sprintf(s, " aom-film-grain=%s", p->aomFilmGrain);
>      BOOL(p->bEnableTemporalFilter, "mcstf");
>  #if ENABLE_ALPHA
>      BOOL(p->bEnableAlpha, "alpha");
> @@ -2956,6 +2960,9 @@ void x265_copy_params(x265_param* dst, x265_param*
> src)
>      /* Film grain */
>      if (src->filmGrain)
>          dst->filmGrain = src->filmGrain;
> +    /* Aom Film grain*/
> +    if (src->aomFilmGrain)
> +        dst->aomFilmGrain = src->aomFilmGrain;
>      dst->bEnableSBRC = src->bEnableSBRC;
>  }
>
> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
> index 13b98e986..c78413bfb 100644
> --- a/source/encoder/encoder.cpp
> +++ b/source/encoder/encoder.cpp
> @@ -142,6 +142,7 @@ Encoder::Encoder()
>      m_analysisFileIn = NULL;
>      m_analysisFileOut = NULL;
>      m_filmGrainIn = NULL;
> +    m_aomFilmGrainIn = NULL;
>      m_naluFile = NULL;
>      m_offsetEmergency = NULL;
>      m_iFrameNum = 0;
> @@ -533,6 +534,14 @@ void Encoder::create()
>              x265_log_file(NULL, X265_LOG_ERROR, "Failed to open film
> grain characteristics binary file %s\n", m_param->filmGrain);
>          }
>      }
> +    if (m_param->aomFilmGrain)
> +    {
> +        m_aomFilmGrainIn = x265_fopen(m_param->aomFilmGrain, "rb");
> +        if (!m_aomFilmGrainIn)
> +        {
> +            x265_log_file(NULL, X265_LOG_ERROR, "Failed to open Aom film
> grain characteristics binary file %s\n", m_param->aomFilmGrain);
> +        }
> +    }
>
>      m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth &&
> m_param->frameNumThreads == 1 && m_param->maxSlices == 1;
>      m_aborted |= parseLambdaFile(m_param);
> @@ -973,6 +982,8 @@ void Encoder::destroy()
>          fclose(m_naluFile);
>      if (m_filmGrainIn)
>          x265_fclose(m_filmGrainIn);
> +    if (m_aomFilmGrainIn)
> +        x265_fclose(m_aomFilmGrainIn);
>
>  #ifdef SVT_HEVC
>      X265_FREE(m_svtAppData);
> diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
> index e5020c1dc..4b72f8bf9 100644
> --- a/source/encoder/encoder.h
> +++ b/source/encoder/encoder.h
> @@ -285,6 +285,8 @@ public:
>      ThreadSafeInteger* zoneWriteCount;
>      /* Film grain model file */
>      FILE* m_filmGrainIn;
> +    /* Aom film grain model file*/
> +    FILE* m_aomFilmGrainIn;
>      OrigPicBuffer*          m_origPicBuffer;
>
>      Encoder();
> diff --git a/source/encoder/frameencoder.cpp
> b/source/encoder/frameencoder.cpp
> index deb478a0f..e21dbfa85 100644
> --- a/source/encoder/frameencoder.cpp
> +++ b/source/encoder/frameencoder.cpp
> @@ -872,6 +872,14 @@ void FrameEncoder::compressFrame(int layer)
>          readModel(&m_filmGrain, this->m_top->m_filmGrainIn);
>          m_filmGrain.writeSEImessages(m_bs, *slice->m_sps,
> NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal, layer);
>      }
> +    /* Write Aom film grain characteristics if present */
> +    if (this->m_top->m_aomFilmGrainIn)
> +    {
> +        AomFilmGrainCharacteristics m_aomFilmGrain;
> +        /* Read the Film grain model file */
> +        readAomModel(&m_aomFilmGrain, this->m_top->m_aomFilmGrainIn);
> +        m_aomFilmGrain.writeSEImessages(m_bs, *slice->m_sps,
> NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal);
> +    }
>      /* Write user SEI */
>      for (int i = 0; i < m_frame[layer]->m_userSEI.numPayloads; i++)
>      {
> @@ -2335,6 +2343,90 @@ void
> FrameEncoder::readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgr
>          }
>      }
>  }
> +
> +void FrameEncoder::readAomModel(AomFilmGrainCharacteristics*
> m_aomFilmGrain, FILE* Aomfilmgrain)
> +{
> +    char const* errorMessage = "Error reading Aom FilmGrain
> characteristics\n";
> +    AomFilmGrain m_afg;
> +    x265_fread((char*)&m_aomFilmGrain->m_apply_grain, sizeof(int32_t), 1,
> Aomfilmgrain, errorMessage);
> +    x265_fread((char*)&m_aomFilmGrain->m_grain_seed, sizeof(uint16_t), 1,
> Aomfilmgrain, errorMessage);
> +    x265_fread((char*)&m_aomFilmGrain->m_update_grain, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    x265_fread((char*)&m_aomFilmGrain->m_num_y_points, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    if (m_aomFilmGrain->m_num_y_points)
> +    {
> +        for (int i = 0; i < m_aomFilmGrain->m_num_y_points; i++)
> +        {
> +            for (int j = 0; j < 2; j++)
> +            {
> +
>  x265_fread((char*)&m_aomFilmGrain->m_scaling_points_y[i][j],
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +            }
> +        }
> +    }
> +    x265_fread((char*)&m_aomFilmGrain->m_num_cb_points, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    if (m_aomFilmGrain->m_num_cb_points)
> +    {
> +        for (int i = 0; i < m_aomFilmGrain->m_num_cb_points; i++)
> +        {
> +            for (int j = 0; j < 2; j++)
> +            {
> +
>  x265_fread((char*)&m_aomFilmGrain->m_scaling_points_cb[i][j],
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +            }
> +        }
> +    }
> +    x265_fread((char*)&m_aomFilmGrain->m_num_cr_points, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    if (m_aomFilmGrain->m_num_cr_points)
> +    {
> +        for (int i = 0; i < m_aomFilmGrain->m_num_cr_points; i++)
> +        {
> +            for (int j = 0; j < 2; j++)
> +            {
> +
>  x265_fread((char*)&m_aomFilmGrain->m_scaling_points_cr[i][j],
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +            }
> +        }
> +    }
> +    x265_fread((char*)&m_aomFilmGrain->m_scaling_shift, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    x265_fread((char*)&m_aomFilmGrain->m_ar_coeff_lag, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    if (m_aomFilmGrain->m_num_y_points)
> +    {
> +
> +        for (int i = 0; i < 24; i++)
> +        {
> +            x265_fread((char*)&m_aomFilmGrain->m_ar_coeffs_y[i],
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +        }
> +    }
> +    if (m_aomFilmGrain->m_num_cb_points ||
> m_afg.m_chroma_scaling_from_luma)
> +    {
> +        for (int i = 0; i < 25; i++)
> +        {
> +            x265_fread((char*)&m_aomFilmGrain->m_ar_coeffs_cb[i],
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +        }
> +    }
> +    if (m_aomFilmGrain->m_num_cr_points ||
> m_afg.m_chroma_scaling_from_luma)
> +    {
> +
> +        for (int i = 0; i < 25; i++)
> +        {
> +            x265_fread((char*)&m_aomFilmGrain->m_ar_coeffs_cr[i],
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +        }
> +    }
> +    x265_fread((char*)&m_aomFilmGrain->m_ar_coeff_shift, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    x265_fread((char*)&m_aomFilmGrain->m_grain_scale_shift,
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +    if (m_aomFilmGrain->m_num_cb_points)
> +    {
> +        x265_fread((char*)&m_aomFilmGrain->m_cb_mult, sizeof(int32_t), 1,
> Aomfilmgrain, errorMessage);
> +        x265_fread((char*)&m_aomFilmGrain->m_cb_luma_mult,
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +        x265_fread((char*)&m_aomFilmGrain->m_cb_offset, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    }
> +    if (m_aomFilmGrain->m_num_cr_points)
> +    {
> +        x265_fread((char*)&m_aomFilmGrain->m_cr_mult, sizeof(int32_t), 1,
> Aomfilmgrain, errorMessage);
> +        x265_fread((char*)&m_aomFilmGrain->m_cr_luma_mult,
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +        x265_fread((char*)&m_aomFilmGrain->m_cr_offset, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    }
> +    x265_fread((char*)&m_aomFilmGrain->m_overlap_flag, sizeof(int32_t),
> 1, Aomfilmgrain, errorMessage);
> +    x265_fread((char*)&m_aomFilmGrain->m_clip_to_restricted_range,
> sizeof(int32_t), 1, Aomfilmgrain, errorMessage);
> +}
> +
>  #if ENABLE_LIBVMAF
>  void FrameEncoder::vmafFrameLevelScore()
>  {
> diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h
> index ebc6e57c5..21d05c2f2 100644
> --- a/source/encoder/frameencoder.h
> +++ b/source/encoder/frameencoder.h
> @@ -142,6 +142,36 @@ struct FGPresent
>      bool        m_presentFlag[3];
>  };
>
> +struct AomFilmGrain
> +{
> +    int32_t     m_apply_grain;
> +    int32_t     m_update_grain;
> +    int32_t     m_scaling_points_y[14][2];
> +    int32_t     m_num_y_points;
> +    int32_t     m_scaling_points_cb[10][2];
> +    int32_t     m_num_cb_points;
> +    int32_t     m_scaling_points_cr[10][2];
> +    int32_t     m_num_cr_points;
> +    int32_t     m_scaling_shift;
> +    int32_t     m_ar_coeff_lag;
> +    int32_t     m_ar_coeffs_y[24];
> +    int32_t     m_ar_coeffs_cb[25];
> +    int32_t     m_ar_coeffs_cr[25];
> +    int32_t     m_ar_coeff_shift;
> +    int32_t     m_cb_mult;
> +    int32_t     m_cb_luma_mult;
> +    int32_t     m_cb_offset;
> +    int32_t     m_cr_mult;
> +    int32_t     m_cr_luma_mult;
> +    int32_t     m_cr_offset;
> +    int32_t     m_overlap_flag;
> +    int32_t     m_clip_to_restricted_range;
> +    int32_t     m_bitDepth;
> +    int32_t     m_chroma_scaling_from_luma;
> +    int32_t     m_grain_scale_shift;
> +    uint16_t    m_grain_seed;
> +};
> +
>  // Manages the wave-front processing of a single encoding frame
>  class FrameEncoder : public WaveFront, public Thread
>  {
> @@ -287,6 +317,7 @@ protected:
>      void computeAvgTrainingData(int layer);
>      void collectDynDataRow(CUData& ctu, FrameStats* rowStats);
>      void readModel(FilmGrainCharacteristics* m_filmGrain, FILE*
> filmgrain);
> +    void readAomModel(AomFilmGrainCharacteristics* m_aomFilmGrain, FILE*
> Aomfilmgrain);
>  };
>  }
>
> diff --git a/source/encoder/sei.h b/source/encoder/sei.h
> index e357a1bf5..1fa4dc69b 100644
> --- a/source/encoder/sei.h
> +++ b/source/encoder/sei.h
> @@ -168,6 +168,137 @@ class FilmGrainCharacteristics : public SEI
>      }
>  };
>
> +class AomFilmGrainCharacteristics : public SEI {
> +
> +public:
> +
> +    AomFilmGrainCharacteristics()
> +    {
> +        m_payloadType = USER_DATA_REGISTERED_ITU_T_T35;
> +        m_payloadSize = 0;
> +    }
> +
> +    int32_t     m_apply_grain;
> +    int32_t     m_update_grain;
> +    int32_t     m_scaling_points_y[14][2];
> +    int32_t     m_num_y_points;
> +    int32_t     m_scaling_points_cb[10][2];
> +    int32_t     m_num_cb_points;
> +    int32_t     m_scaling_points_cr[10][2];
> +    int32_t     m_num_cr_points;
> +    int32_t     m_scaling_shift;
> +    int32_t     m_ar_coeff_lag;
> +    int32_t     m_ar_coeffs_y[24];
> +    int32_t     m_ar_coeffs_cb[25];
> +    int32_t     m_ar_coeffs_cr[25];
> +    int32_t     m_ar_coeff_shift;
> +    int32_t     m_cb_mult;
> +    int32_t     m_cb_luma_mult;
> +    int32_t     m_cb_offset;
> +    int32_t     m_cr_mult;
> +    int32_t     m_cr_luma_mult;
> +    int32_t     m_cr_offset;
> +    int32_t     m_overlap_flag;
> +    int32_t     m_clip_to_restricted_range;
> +    int32_t     m_bitDepth;
> +    int32_t     m_chroma_scaling_from_luma;
> +    int32_t     m_grain_scale_shift;
> +    uint16_t    m_grain_seed;
> +
> +    void writeSEI(const SPS&)
> +    {
> +        WRITE_CODE(0x26, 8, "country_code");
> +        WRITE_CODE(0x5890, 16, "provider_code");
> +        WRITE_CODE(0x0001, 16, "provider_oriented_code");
> +        WRITE_FLAG(m_apply_grain, "afgs1_enable_flag");
> +        WRITE_CODE(m_grain_seed, 16, "grain_seed");
> +        WRITE_CODE(0, 3, "film_grain_param_set_idx");
> +        WRITE_CODE(m_update_grain, 1, "update_grain");
> +        WRITE_CODE(m_num_y_points, 4, "num_y_points");
> +        if (m_num_y_points)
> +        {
> +            for (int i = 0; i < m_num_y_points; i++)
> +            {
> +                for (int j = 0; j < 2; j++)
> +                {
> +                    WRITE_CODE(m_scaling_points_y[i][j], 8,
> "scaling_points_y[i][j]");
> +                }
> +            }
> +        }
> +        WRITE_FLAG(m_num_cb_points == 0 && m_num_cr_points == 0,
> "luma_only_flag");
> +        WRITE_FLAG(0, "chroma_scaling_from_luma");
> +        WRITE_CODE(m_num_cb_points, 4, "num_cb_points");
> +        if (m_num_cb_points)
> +        {
> +            for (int i = 0; i < m_num_cb_points; i++)
> +            {
> +                for (int j = 0; j < 2; j++)
> +                {
> +                    WRITE_CODE(m_scaling_points_cb[i][j], 8,
> "scaling_points_cb[i][j]");
> +                }
> +            }
> +        }
> +        WRITE_CODE(m_num_cr_points, 4, "num_cr_points");
> +        if (m_num_cr_points)
> +        {
> +            for (int i = 0; i < m_num_cr_points; i++)
> +            {
> +                for (int j = 0; j < 2; j++)
> +                {
> +                    WRITE_CODE(m_scaling_points_cr[i][j], 8,
> "scaling_points_cr[i][j]");
> +                }
> +            }
> +        }
> +        WRITE_CODE(m_scaling_shift - 8, 2, "scaling_shift");
> +        WRITE_CODE(m_ar_coeff_lag, 2, "ar_coeff_lag");
> +        if (m_num_y_points)
> +        {
> +            for (int i = 0; i < 24; i++)
> +            {
> +                WRITE_CODE(m_ar_coeffs_y[i] + 128, 8, "ar_coeff_y[i]");
> +            }
> +        }
> +        if (m_num_cb_points || m_chroma_scaling_from_luma)
> +        {
> +            for (int i = 0; i < 25; i++)
> +            {
> +                WRITE_CODE(m_ar_coeffs_cb[i] + 128, 8, "ar_coeff_cb[i]");
> +            }
> +        }
> +        if (m_num_cr_points || m_chroma_scaling_from_luma)
> +        {
> +            for (int i = 0; i < 25; i++)
> +            {
> +                WRITE_CODE(m_ar_coeffs_cr[i] + 128, 8, "ar_coeff_cr[i]");
> +            }
> +        }
> +        WRITE_CODE(m_ar_coeff_shift - 6, 2, "ar_coeff_shift");
> +        WRITE_CODE(m_grain_scale_shift, 2, "grain_scale_shift");
> +        if (m_num_cb_points)
> +        {
> +            WRITE_CODE(m_cb_mult, 8, "cb_mult");
> +            WRITE_CODE(m_cb_luma_mult, 8, "cb_luma_mult");
> +            WRITE_CODE(m_cb_offset, 9, "cb_offset");
> +        }
> +        if (m_num_cr_points)
> +        {
> +            WRITE_CODE(m_cr_mult, 8, "cr_mult");
> +            WRITE_CODE(m_cr_luma_mult, 8, "cr_luma_mult");
> +            WRITE_CODE(m_cr_offset, 9, "cr_offset");
> +        }
> +        WRITE_FLAG(m_overlap_flag, "overlap_flag");
> +        WRITE_FLAG(m_clip_to_restricted_range,
> "clip_to_restricted_range");
> +        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
> +        {
> +            WRITE_FLAG(1, "payload_bit_equal_to_one");
> +            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
> +            {
> +                WRITE_FLAG(0, "payload_bit_equal_to_zero");
> +            }
> +        }
> +    }
> +};
> +
>  static const uint32_t ISO_IEC_11578_LEN = 16;
>
>  class SEIuserDataUnregistered : public SEI
> diff --git a/source/x265.h b/source/x265.h
> index 532d01b22..54e699317 100644
> --- a/source/x265.h
> +++ b/source/x265.h
> @@ -2307,6 +2307,9 @@ typedef struct x265_param
>      /* Film Grain Characteristic file */
>      char* filmGrain;
>
> +    /* Aom Film Grain Characteristic file */
> +    char* aomFilmGrain;
> +
>      /*Motion compensated temporal filter*/
>      int      bEnableTemporalFilter;
>      double   temporalFilterStrength;
> diff --git a/source/x265cli.cpp b/source/x265cli.cpp
> index ca7d9c973..b9ce96f19 100755
> --- a/source/x265cli.cpp
> +++ b/source/x265cli.cpp
> @@ -408,6 +408,7 @@ namespace X265_NS {
>          H1("    4 - encoder abort\n");
>          H0("\nSEI Message Options\n");
>          H0("   --film-grain <filename>           File containing Film
> Grain Characteristics to be written as a SEI Message\n");
> +        H0("   --aom-film-grain <filename>       File containing Aom Film
> Grain Characteristics to be written as a SEI Message\n");
>
>  #undef OPT
>  #undef H0
> diff --git a/source/x265cli.h b/source/x265cli.h
> index 2ec48352d..3df0fa7a6 100644
> --- a/source/x265cli.h
> +++ b/source/x265cli.h
> @@ -395,6 +395,7 @@ static const struct option long_options[] =
>      { "max-vbv-fullness", required_argument, NULL, 0 },
>      { "scenecut-qp-config", required_argument, NULL, 0 },
>      { "film-grain", required_argument, NULL, 0 },
> +    { "aom-film-grain", required_argument, NULL, 0 },
>      { 0, 0, 0, 0 },
>      { 0, 0, 0, 0 },
>      { 0, 0, 0, 0 },
> --
> 2.36.0.windows.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240927/c39e7571/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-Add-Aom-film-grain-characteristics-as-SEI-message-to.patch
Type: application/octet-stream
Size: 17733 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240927/c39e7571/attachment-0001.obj>


More information about the x265-devel mailing list