[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