[x265] [PATCH] Add Aom film grain characteristics as SEI message to the bitstream
Karam Singh
karam.singh at multicorewareinc.com
Fri Oct 4 07:48:17 UTC 2024
This patch has been pushed to the master branch.
*__________________________*
*Karam Singh*
*Ph.D. IIT Guwahati*
Senior Software (Video Coding) Engineer
Mobile: +91 8011279030
Block 9A, 6th floor, DLF Cyber City
Manapakkam, Chennai 600 089
On Fri, Sep 27, 2024 at 6:03 PM Anusuya Kumarasamy <
anusuya.kumarasamy at multicorewareinc.com> wrote:
>
>
> 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
>>
>> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20241004/c261d265/attachment-0001.htm>
More information about the x265-devel
mailing list