<div dir="ltr">Pushed to master branch</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 4, 2022 at 1:46 PM Keshav E <<a href="mailto:keshav@multicorewareinc.com">keshav@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Observed a warning in the patch sent in the previous email. Resolved the warning and reattaching the patch here.<div>From 0ba89aaa409d09f94348536edf7cede8f3f7f7e7 Mon Sep 17 00:00:00 2001<br>From: Keshav E <<a href="mailto:keshav@multicorewareinc.com" target="_blank">keshav@multicorewareinc.com</a>><br>Date: Fri, 4 Mar 2022 12:36:14 +0530<br>Subject: [PATCH] Add film grain characteristics as a SEI message to the<br> bitstream<br><br>---<br> doc/reST/cli.rst | 6 ++<br> source/CMakeLists.txt | 2 +-<br> source/common/common.h | 9 +++<br> source/common/param.cpp | 9 +++<br> source/encoder/encoder.cpp | 12 ++++<br> source/encoder/encoder.h | 2 +<br> source/encoder/frameencoder.cpp | 57 ++++++++++++++++++-<br> source/encoder/frameencoder.h | 29 ++++++++++<br> source/encoder/sei.h | 95 ++++++++++++++++++++++++++++++++<br> source/test/regression-tests.txt | 4 ++<br> source/test/smoke-tests.txt | 4 ++<br> source/x265.h | 3 +<br> source/x265cli.cpp | 3 +<br> source/x265cli.h | 1 +<br> 14 files changed, 234 insertions(+), 2 deletions(-)<br><br>diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>index 1491b63fe..1640c1f8e 100755<br>--- a/doc/reST/cli.rst<br>+++ b/doc/reST/cli.rst<br>@@ -2659,6 +2659,12 @@ Bitstream options<br> Emit SEI messages in a single NAL unit instead of multiple NALs. Default disabled.<br> When HRD SEI is enabled the HM decoder will throw a warning.<br> <br>+.. option:: --film-grain <filename><br>+<br>+ Refers to the film grain model characteristics for signal enhancement information transmission<br>+<br>+ **CLI_ONLY**<br>+<br> DCT Approximations<br> =================<br> <br>diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt<br>index 60031df63..13e4750de 100755<br>--- a/source/CMakeLists.txt<br>+++ b/source/CMakeLists.txt<br>@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)<br> option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br> mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br> # X265_BUILD must be incremented each time the public API is changed<br>-set(X265_BUILD 203)<br>+set(X265_BUILD 204)<br> configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265.def.in" target="_blank">x265.def.in</a>"<br> "${PROJECT_BINARY_DIR}/x265.def")<br> configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265_config.h.in" target="_blank">x265_config.h.in</a>"<br>diff --git a/source/common/common.h b/source/common/common.h<br>index 8c06cd79e..a245c7dae 100644<br>--- a/source/common/common.h<br>+++ b/source/common/common.h<br>@@ -340,6 +340,7 @@ typedef int16_t coeff_t; // transform coefficient<br> #define FILLER_OVERHEAD (NAL_TYPE_OVERHEAD + START_CODE_OVERHEAD + 1)<br> <br> #define MAX_NUM_DYN_REFINE (NUM_CU_DEPTH * X265_REFINE_INTER_LEVELS)<br>+#define X265_BYTE 8<br> <br> namespace X265_NS {<br> <br>@@ -434,6 +435,14 @@ int x265_rename(const char* oldName, const char* newName);<br> #define x265_unlink(fileName) unlink(fileName)<br> #define x265_rename(oldName, newName) rename(oldName, newName)<br> #endif<br>+/* Close a file */<br>+#define x265_fclose(file) if (file != NULL) fclose(file); file=NULL;<br>+#define x265_fread(val, size, readSize, fileOffset,errorMessage)\<br>+ if (fread(val, size, readSize, fileOffset) != readSize)\<br>+ {\<br>+ x265_log(NULL, X265_LOG_ERROR, errorMessage); \<br>+ return; \<br>+ }<br> int x265_exp2fix8(double x);<br> <br> double x265_ssim2dB(double ssim);<br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index f72305372..ed6973d9c 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -384,6 +384,8 @@ void x265_param_default(x265_param* param)<br> param->svtHevcParam = svtParam;<br> svt_param_default(param);<br> #endif<br>+ /* Film grain characteristics model filename */<br>+ param->filmGrain = NULL;<br> }<br> <br> int x265_param_default_preset(x265_param* param, const char* preset, const char* tune)<br>@@ -1460,6 +1462,8 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br> OPT("video-signal-type-preset") p->videoSignalTypePreset = strdup(value);<br> OPT("eob") p->bEnableEndOfBitstream = atobool(value);<br> OPT("eos") p->bEnableEndOfSequence = atobool(value);<br>+ /* Film grain characterstics model filename */<br>+ OPT("film-grain") p->filmGrain = (char* )value;<br> else<br> return X265_PARAM_BAD_NAME;<br> }<br>@@ -2353,6 +2357,8 @@ char *x265_param2string(x265_param* p, int padx, int pady)<br> s += sprintf(s, "conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset);<br> s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate);<br> BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");<br>+ if (p->filmGrain)<br>+ s += sprintf(s, " film-grain=%s", p->filmGrain); // Film grain characteristics model filename<br> #undef BOOL<br> return buf;<br> }<br>@@ -2726,6 +2732,9 @@ void x265_copy_params(x265_param* dst, x265_param* src)<br> #ifdef SVT_HEVC<br> memcpy(dst->svtHevcParam, src->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION));<br> #endif<br>+ /* Film grain */<br>+ if (src->filmGrain)<br>+ dst->filmGrain = src->filmGrain;<br> }<br> <br> #ifdef SVT_HEVC<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 5d0c9a050..f33a6d053 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -142,6 +142,7 @@ Encoder::Encoder()<br> m_threadPool = NULL;<br> m_analysisFileIn = NULL;<br> m_analysisFileOut = NULL;<br>+ m_filmGrainIn = NULL;<br> m_naluFile = NULL;<br> m_offsetEmergency = NULL;<br> m_iFrameNum = 0;<br>@@ -551,6 +552,15 @@ void Encoder::create()<br> }<br> }<br> }<br>+ if (m_param->filmGrain)<br>+ {<br>+ m_filmGrainIn = x265_fopen(m_param->filmGrain, "rb");<br>+ if (!m_filmGrainIn)<br>+ {<br>+ x265_log_file(NULL, X265_LOG_ERROR, "Failed to open film grain characteristics binary file %s\n", m_param->filmGrain);<br>+ }<br>+ }<br>+<br> m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth && m_param->frameNumThreads == 1 && m_param->maxSlices == 1;<br> m_aborted |= parseLambdaFile(m_param);<br> <br>@@ -996,6 +1006,8 @@ void Encoder::destroy()<br> }<br> if (m_naluFile)<br> fclose(m_naluFile);<br>+ if (m_filmGrainIn)<br>+ x265_fclose(m_filmGrainIn);<br> <br> #ifdef SVT_HEVC<br> X265_FREE(m_svtAppData);<br>diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h<br>index 2ee5bdaee..cfbb55fe0 100644<br>--- a/source/encoder/encoder.h<br>+++ b/source/encoder/encoder.h<br>@@ -295,6 +295,8 @@ public:<br> <br> ThreadSafeInteger* zoneReadCount;<br> ThreadSafeInteger* zoneWriteCount;<br>+ /* Film grain model file */<br>+ FILE* m_filmGrainIn;<br> <br> Encoder();<br> ~Encoder()<br>diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp<br>index 1b3875a25..9dc9242f6 100644<br>--- a/source/encoder/frameencoder.cpp<br>+++ b/source/encoder/frameencoder.cpp<br>@@ -762,7 +762,14 @@ void FrameEncoder::compressFrame()<br> m_seiAlternativeTC.m_preferredTransferCharacteristics = m_param->preferredTransferCharacteristics;<br> m_seiAlternativeTC.writeSEImessages(m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal);<br> }<br>-<br>+ /* Write Film grain characteristics if present */<br>+ if (this->m_top->m_filmGrainIn)<br>+ {<br>+ FilmGrainCharacteristics m_filmGrain;<br>+ /* Read the Film grain model file */<br>+ readModel(&m_filmGrain, this->m_top->m_filmGrainIn);<br>+ m_filmGrain.writeSEImessages(m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal);<br>+ }<br> /* Write user SEI */<br> for (int i = 0; i < m_frame->m_userSEI.numPayloads; i++)<br> {<br>@@ -2133,6 +2140,54 @@ void FrameEncoder::noiseReductionUpdate()<br> m_nr->nrOffsetDenoise[cat][0] = 0;<br> }<br> }<br>+<br>+void FrameEncoder::readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain)<br>+{<br>+ char const* errorMessage = "Error reading FilmGrain characteristics\n";<br>+ FilmGrain m_fg;<br>+ x265_fread((char* )&m_fg, sizeof(bool) * 3 + sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_filmGrainCharacteristicsCancelFlag = m_fg.m_filmGrainCharacteristicsCancelFlag;<br>+ m_filmGrain->m_filmGrainCharacteristicsPersistenceFlag = m_fg.m_filmGrainCharacteristicsPersistenceFlag;<br>+ m_filmGrain->m_filmGrainModelId = m_fg.m_filmGrainModelId;<br>+ m_filmGrain->m_separateColourDescriptionPresentFlag = m_fg.m_separateColourDescriptionPresentFlag;<br>+ if (m_filmGrain->m_separateColourDescriptionPresentFlag)<br>+ {<br>+ ColourDescription m_clr;<br>+ x265_fread((char* )&m_clr, sizeof(bool) + sizeof(uint8_t) * 5, 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_filmGrainBitDepthLumaMinus8 = m_clr.m_filmGrainBitDepthLumaMinus8;<br>+ m_filmGrain->m_filmGrainBitDepthChromaMinus8 = m_clr.m_filmGrainBitDepthChromaMinus8;<br>+ m_filmGrain->m_filmGrainFullRangeFlag = m_clr.m_filmGrainFullRangeFlag;<br>+ m_filmGrain->m_filmGrainColourPrimaries = m_clr.m_filmGrainColourPrimaries;<br>+ m_filmGrain->m_filmGrainTransferCharacteristics = m_clr.m_filmGrainTransferCharacteristics;<br>+ m_filmGrain->m_filmGrainMatrixCoeffs = m_clr.m_filmGrainMatrixCoeffs;<br>+ }<br>+ FGPresent m_present;<br>+ x265_fread((char* )&m_present, sizeof(bool) * 3 + sizeof(uint8_t) * 2, 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_blendingModeId = m_present.m_blendingModeId;<br>+ m_filmGrain->m_log2ScaleFactor = m_present.m_log2ScaleFactor;<br>+ m_filmGrain->m_compModel[0].bPresentFlag = m_present.m_presentFlag[0];<br>+ m_filmGrain->m_compModel[1].bPresentFlag = m_present.m_presentFlag[1];<br>+ m_filmGrain->m_compModel[2].bPresentFlag = m_present.m_presentFlag[2];<br>+ for (int i = 0; i < MAX_NUM_COMPONENT; i++)<br>+ {<br>+ if (m_filmGrain->m_compModel[i].bPresentFlag)<br>+ {<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].numModelValues), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_compModel[i].intensityValues = (FilmGrainCharacteristics::CompModelIntensityValues* ) malloc(sizeof(FilmGrainCharacteristics::CompModelIntensityValues) * (m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1+1)) ;<br>+ for (int j = 0; j <= m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1; j++)<br>+ {<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].intensityValues[j].intensityIntervalLowerBound), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].intensityValues[j].intensityIntervalUpperBound), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_compModel[i].intensityValues[j].compModelValue = (int* ) malloc(sizeof(int) * (m_filmGrain->m_compModel[i].numModelValues));<br>+ for (int k = 0; k < m_filmGrain->m_compModel[i].numModelValues; k++)<br>+ {<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].intensityValues[j].compModelValue[k]), sizeof(int), 1, filmgrain, errorMessage);<br>+ }<br>+ }<br>+ }<br>+ }<br>+}<br> #if ENABLE_LIBVMAF<br> void FrameEncoder::vmafFrameLevelScore()<br> {<br>diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h<br>index f4cfc624d..5d972cb26 100644<br>--- a/source/encoder/frameencoder.h<br>+++ b/source/encoder/frameencoder.h<br>@@ -113,6 +113,34 @@ struct CTURow<br> }<br> };<br> <br>+/*Film grain characteristics*/<br>+struct FilmGrain<br>+{<br>+ bool m_filmGrainCharacteristicsCancelFlag;<br>+ bool m_filmGrainCharacteristicsPersistenceFlag;<br>+ bool m_separateColourDescriptionPresentFlag;<br>+ uint8_t m_filmGrainModelId;<br>+ uint8_t m_blendingModeId;<br>+ uint8_t m_log2ScaleFactor;<br>+};<br>+<br>+struct ColourDescription<br>+{<br>+ bool m_filmGrainFullRangeFlag;<br>+ uint8_t m_filmGrainBitDepthLumaMinus8;<br>+ uint8_t m_filmGrainBitDepthChromaMinus8;<br>+ uint8_t m_filmGrainColourPrimaries;<br>+ uint8_t m_filmGrainTransferCharacteristics;<br>+ uint8_t m_filmGrainMatrixCoeffs;<br>+};<br>+<br>+struct FGPresent<br>+{<br>+ uint8_t m_blendingModeId;<br>+ uint8_t m_log2ScaleFactor;<br>+ bool m_presentFlag[3];<br>+};<br>+<br> // Manages the wave-front processing of a single encoding frame<br> class FrameEncoder : public WaveFront, public Thread<br> {<br>@@ -250,6 +278,7 @@ protected:<br> void collectDynDataFrame();<br> void computeAvgTrainingData();<br> void collectDynDataRow(CUData& ctu, FrameStats* rowStats); <br>+ void readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain);<br> };<br> }<br> <br>diff --git a/source/encoder/sei.h b/source/encoder/sei.h<br>index 61d39edd9..03e210639 100644<br>--- a/source/encoder/sei.h<br>+++ b/source/encoder/sei.h<br>@@ -73,6 +73,101 @@ public:<br> }<br> };<br> <br>+/* Film grain characteristics */<br>+class FilmGrainCharacteristics : public SEI<br>+{<br>+ public:<br>+<br>+ FilmGrainCharacteristics()<br>+ {<br>+ m_payloadType = FILM_GRAIN_CHARACTERISTICS;<br>+ m_payloadSize = 0;<br>+ }<br>+<br>+ struct CompModelIntensityValues<br>+ {<br>+ uint8_t intensityIntervalLowerBound;<br>+ uint8_t intensityIntervalUpperBound;<br>+ int* compModelValue;<br>+ };<br>+<br>+ struct CompModel<br>+ {<br>+ bool bPresentFlag;<br>+ uint8_t numModelValues;<br>+ uint8_t m_filmGrainNumIntensityIntervalMinus1;<br>+ CompModelIntensityValues* intensityValues;<br>+ };<br>+<br>+ CompModel m_compModel[MAX_NUM_COMPONENT];<br>+ bool m_filmGrainCharacteristicsPersistenceFlag;<br>+ bool m_filmGrainCharacteristicsCancelFlag;<br>+ bool m_separateColourDescriptionPresentFlag;<br>+ bool m_filmGrainFullRangeFlag;<br>+ uint8_t m_filmGrainModelId;<br>+ uint8_t m_blendingModeId;<br>+ uint8_t m_log2ScaleFactor;<br>+ uint8_t m_filmGrainBitDepthLumaMinus8;<br>+ uint8_t m_filmGrainBitDepthChromaMinus8;<br>+ uint8_t m_filmGrainColourPrimaries;<br>+ uint8_t m_filmGrainTransferCharacteristics;<br>+ uint8_t m_filmGrainMatrixCoeffs;<br>+<br>+ void writeSEI(const SPS&)<br>+ {<br>+ WRITE_FLAG(m_filmGrainCharacteristicsCancelFlag, "film_grain_characteristics_cancel_flag");<br>+<br>+ if (!m_filmGrainCharacteristicsCancelFlag)<br>+ {<br>+ WRITE_CODE(m_filmGrainModelId, 2, "film_grain_model_id");<br>+ WRITE_FLAG(m_separateColourDescriptionPresentFlag, "separate_colour_description_present_flag");<br>+ if (m_separateColourDescriptionPresentFlag)<br>+ {<br>+ WRITE_CODE(m_filmGrainBitDepthLumaMinus8, 3, "film_grain_bit_depth_luma_minus8");<br>+ WRITE_CODE(m_filmGrainBitDepthChromaMinus8, 3, "film_grain_bit_depth_chroma_minus8");<br>+ WRITE_FLAG(m_filmGrainFullRangeFlag, "film_grain_full_range_flag");<br>+ WRITE_CODE(m_filmGrainColourPrimaries, X265_BYTE, "film_grain_colour_primaries");<br>+ WRITE_CODE(m_filmGrainTransferCharacteristics, X265_BYTE, "film_grain_transfer_characteristics");<br>+ WRITE_CODE(m_filmGrainMatrixCoeffs, X265_BYTE, "film_grain_matrix_coeffs");<br>+ }<br>+ WRITE_CODE(m_blendingModeId, 2, "blending_mode_id");<br>+ WRITE_CODE(m_log2ScaleFactor, 4, "log2_scale_factor");<br>+ for (uint8_t c = 0; c < 3; c++)<br>+ {<br>+ WRITE_FLAG(m_compModel[c].bPresentFlag && m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 && m_compModel[c].numModelValues > 0, "comp_model_present_flag[c]");<br>+ }<br>+ for (uint8_t c = 0; c < 3; c++)<br>+ {<br>+ if (m_compModel[c].bPresentFlag && m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 && m_compModel[c].numModelValues > 0)<br>+ {<br>+ assert(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 <= 256);<br>+ assert(m_compModel[c].numModelValues <= X265_BYTE);<br>+ WRITE_CODE(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 , X265_BYTE, "num_intensity_intervals_minus1[c]");<br>+ WRITE_CODE(m_compModel[c].numModelValues - 1, 3, "num_model_values_minus1[c]");<br>+ for (uint8_t interval = 0; interval < m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1; interval++)<br>+ {<br>+ WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalLowerBound, X265_BYTE, "intensity_interval_lower_bound[c][i]");<br>+ WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalUpperBound, X265_BYTE, "intensity_interval_upper_bound[c][i]");<br>+ for (uint8_t j = 0; j < m_compModel[c].numModelValues; j++)<br>+ {<br>+ WRITE_SVLC(m_compModel[c].intensityValues[interval].compModelValue[j],"comp_model_value[c][i]");<br>+ }<br>+ }<br>+ }<br>+ }<br>+ WRITE_FLAG(m_filmGrainCharacteristicsPersistenceFlag, "film_grain_characteristics_persistence_flag");<br>+ }<br>+ if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)<br>+ {<br>+ WRITE_FLAG(1, "payload_bit_equal_to_one");<br>+ while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)<br>+ {<br>+ WRITE_FLAG(0, "payload_bit_equal_to_zero");<br>+ }<br>+ }<br>+ }<br>+};<br>+<br> static const uint32_t ISO_IEC_11578_LEN = 16;<br> <br> class SEIuserDataUnregistered : public SEI<br>diff --git a/source/test/regression-tests.txt b/source/test/regression-tests.txt<br>index 26d43b28a..10a4449e7 100644<br>--- a/source/test/regression-tests.txt<br>+++ b/source/test/regression-tests.txt<br>@@ -195,4 +195,8 @@ CrowdRun_1920x1080_50_10bit_422.yuv,--no-cutree --analysis-save x265_analysis.da<br> #segment encoding<br> BasketballDrive_1920x1080_50.y4m, --preset ultrafast --no-open-gop --chunk-start 100 --chunk-end 200<br> <br>+#Test FG SEI message addition<br>+#OldTownCross_1920x1080_50_10bit_422.yuv,--preset slower --tune grain --film-grain "OldTownCross_1920x1080_50_10bit_422.bin"<br>+#RaceHorses_416x240_30_10bit.yuv,--preset ultrafast --signhide --colormatrix bt709 --film-grain "RaceHorses_416x240_30_10bit.bin"<br>+<br> # vim: tw=200<br>diff --git a/source/test/smoke-tests.txt b/source/test/smoke-tests.txt<br>index 041b97e76..a88a225b4 100644<br>--- a/source/test/smoke-tests.txt<br>+++ b/source/test/smoke-tests.txt<br>@@ -23,3 +23,7 @@ CrowdRun_1920x1080_50_10bit_444.yuv,--preset=superfast --bitrate 7000 --sao --li<br> # Main12 intraCost overflow bug test<br> 720p50_parkrun_ter.y4m,--preset medium<br> 720p50_parkrun_ter.y4m,--preset=fast --hevc-aq --no-cutree<br>+# Test FG SEI message addition<br>+# CrowdRun_1920x1080_50_10bit_444.yuv,--preset=ultrafast --weightp --keyint -1 --film-grain "CrowdRun_1920x1080_50_10bit_444.bin"<br>+# DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset=veryfast --min-cu 16 --film-grain "DucksAndLegs_1920x1080_60_10bit_422.bin"<br>+# NebutaFestival_2560x1600_60_10bit_crop.yuv,--preset=superfast --bitrate 10000 --sao --limit-sao --cll --max-cll "1000,400" --film-grain "NebutaFestival_2560x1600_60_10bit_crop.bin"<br>diff --git a/source/x265.h b/source/x265.h<br>index bf945498f..5d242d653 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -1989,6 +1989,9 @@ typedef struct x265_param<br> /* Flag to turn on/off traditional scenecut detection in histogram based scenecut detection.<br> * When false, only spatial properties are used for scenecut detection. Default true */<br> int bEnableTradScdInHscd;<br>+<br>+ /* Film Grain Characteristic file */<br>+ char* filmGrain;<br> } x265_param;<br> <br> /* x265_param_alloc:<br>diff --git a/source/x265cli.cpp b/source/x265cli.cpp<br>index bfb6293f3..3a03de579 100755<br>--- a/source/x265cli.cpp<br>+++ b/source/x265cli.cpp<br>@@ -391,6 +391,9 @@ namespace X265_NS {<br> H1(" 2 - unable to open encoder\n");<br> H1(" 3 - unable to generate stream headers\n");<br> H1(" 4 - encoder abort\n");<br>+ H0("\nSEI Message Options\n");<br>+ H0(" --film-grain <filename> File containing Film Grain Characteristics to be written as a SEI Message\n");<br>+<br> #undef OPT<br> #undef H0<br> #undef H1<br>diff --git a/source/x265cli.h b/source/x265cli.h<br>index 8fcf37b8a..7072f7616 100644<br>--- a/source/x265cli.h<br>+++ b/source/x265cli.h<br>@@ -380,6 +380,7 @@ static const struct option long_options[] =<br> { "abr-ladder", required_argument, NULL, 0 },<br> { "min-vbv-fullness", required_argument, NULL, 0 },<br> { "max-vbv-fullness", required_argument, NULL, 0 },<br>+ { "film-grain", required_argument, NULL, 0 },<br> { 0, 0, 0, 0 },<br> { 0, 0, 0, 0 },<br> { 0, 0, 0, 0 },<br>-- <br>2.20.1.windows.1<br><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 4, 2022 at 11:09 AM Srikanth Kurapati <<a href="mailto:srikanth.kurapati@multicorewareinc.com" target="_blank">srikanth.kurapati@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">This patch looks good to be pushed.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 4, 2022 at 10:32 AM Keshav E <<a href="mailto:keshav@multicorewareinc.com" target="_blank">keshav@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">From 10084990ea36a8d29432996b81fe6de427daaf69 Mon Sep 17 00:00:00 2001<br>From: Keshav E <<a href="mailto:keshav@multicorewareinc.com" target="_blank">keshav@multicorewareinc.com</a>><br>Date: Thu, 3 Mar 2022 14:30:57 +0530<br>Subject: [PATCH] Add film grain characteristics as a SEI message to the<br> bitstream<br><br>---<br> doc/reST/cli.rst | 6 ++<br> source/CMakeLists.txt | 2 +-<br> source/common/common.h | 9 +++<br> source/common/param.cpp | 9 +++<br> source/encoder/encoder.cpp | 12 ++++<br> source/encoder/encoder.h | 2 +<br> source/encoder/frameencoder.cpp | 57 ++++++++++++++++++-<br> source/encoder/frameencoder.h | 29 ++++++++++<br> source/encoder/sei.h | 95 ++++++++++++++++++++++++++++++++<br> source/test/regression-tests.txt | 4 ++<br> source/test/smoke-tests.txt | 4 ++<br> source/x265.h | 3 +<br> source/x265cli.cpp | 3 +<br> source/x265cli.h | 1 +<br> 14 files changed, 234 insertions(+), 2 deletions(-)<br><br>diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>index 1491b63fe..1640c1f8e 100755<br>--- a/doc/reST/cli.rst<br>+++ b/doc/reST/cli.rst<br>@@ -2659,6 +2659,12 @@ Bitstream options<br> Emit SEI messages in a single NAL unit instead of multiple NALs. Default disabled.<br> When HRD SEI is enabled the HM decoder will throw a warning.<br> <br>+.. option:: --film-grain <filename><br>+<br>+ Refers to the film grain model characteristics for signal enhancement information transmission<br>+<br>+ **CLI_ONLY**<br>+<br> DCT Approximations<br> =================<br> <br>diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt<br>index 60031df63..13e4750de 100755<br>--- a/source/CMakeLists.txt<br>+++ b/source/CMakeLists.txt<br>@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)<br> option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br> mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br> # X265_BUILD must be incremented each time the public API is changed<br>-set(X265_BUILD 203)<br>+set(X265_BUILD 204)<br> configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265.def.in" target="_blank">x265.def.in</a>"<br> "${PROJECT_BINARY_DIR}/x265.def")<br> configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265_config.h.in" target="_blank">x265_config.h.in</a>"<br>diff --git a/source/common/common.h b/source/common/common.h<br>index 8c06cd79e..a245c7dae 100644<br>--- a/source/common/common.h<br>+++ b/source/common/common.h<br>@@ -340,6 +340,7 @@ typedef int16_t coeff_t; // transform coefficient<br> #define FILLER_OVERHEAD (NAL_TYPE_OVERHEAD + START_CODE_OVERHEAD + 1)<br> <br> #define MAX_NUM_DYN_REFINE (NUM_CU_DEPTH * X265_REFINE_INTER_LEVELS)<br>+#define X265_BYTE 8<br> <br> namespace X265_NS {<br> <br>@@ -434,6 +435,14 @@ int x265_rename(const char* oldName, const char* newName);<br> #define x265_unlink(fileName) unlink(fileName)<br> #define x265_rename(oldName, newName) rename(oldName, newName)<br> #endif<br>+/* Close a file */<br>+#define x265_fclose(file) if (file != NULL) fclose(file); file=NULL;<br>+#define x265_fread(val, size, readSize, fileOffset,errorMessage)\<br>+ if (fread(val, size, readSize, fileOffset) != readSize)\<br>+ {\<br>+ x265_log(NULL, X265_LOG_ERROR, errorMessage); \<br>+ return; \<br>+ }<br> int x265_exp2fix8(double x);<br> <br> double x265_ssim2dB(double ssim);<br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index f72305372..ed6973d9c 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -384,6 +384,8 @@ void x265_param_default(x265_param* param)<br> param->svtHevcParam = svtParam;<br> svt_param_default(param);<br> #endif<br>+ /* Film grain characteristics model filename */<br>+ param->filmGrain = NULL;<br> }<br> <br> int x265_param_default_preset(x265_param* param, const char* preset, const char* tune)<br>@@ -1460,6 +1462,8 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br> OPT("video-signal-type-preset") p->videoSignalTypePreset = strdup(value);<br> OPT("eob") p->bEnableEndOfBitstream = atobool(value);<br> OPT("eos") p->bEnableEndOfSequence = atobool(value);<br>+ /* Film grain characterstics model filename */<br>+ OPT("film-grain") p->filmGrain = (char* )value;<br> else<br> return X265_PARAM_BAD_NAME;<br> }<br>@@ -2353,6 +2357,8 @@ char *x265_param2string(x265_param* p, int padx, int pady)<br> s += sprintf(s, "conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset);<br> s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate);<br> BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");<br>+ if (p->filmGrain)<br>+ s += sprintf(s, " film-grain=%s", p->filmGrain); // Film grain characteristics model filename<br> #undef BOOL<br> return buf;<br> }<br>@@ -2726,6 +2732,9 @@ void x265_copy_params(x265_param* dst, x265_param* src)<br> #ifdef SVT_HEVC<br> memcpy(dst->svtHevcParam, src->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION));<br> #endif<br>+ /* Film grain */<br>+ if (src->filmGrain)<br>+ dst->filmGrain = src->filmGrain;<br> }<br> <br> #ifdef SVT_HEVC<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 5d0c9a050..f33a6d053 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -142,6 +142,7 @@ Encoder::Encoder()<br> m_threadPool = NULL;<br> m_analysisFileIn = NULL;<br> m_analysisFileOut = NULL;<br>+ m_filmGrainIn = NULL;<br> m_naluFile = NULL;<br> m_offsetEmergency = NULL;<br> m_iFrameNum = 0;<br>@@ -551,6 +552,15 @@ void Encoder::create()<br> }<br> }<br> }<br>+ if (m_param->filmGrain)<br>+ {<br>+ m_filmGrainIn = x265_fopen(m_param->filmGrain, "rb");<br>+ if (!m_filmGrainIn)<br>+ {<br>+ x265_log_file(NULL, X265_LOG_ERROR, "Failed to open film grain characteristics binary file %s\n", m_param->filmGrain);<br>+ }<br>+ }<br>+<br> m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth && m_param->frameNumThreads == 1 && m_param->maxSlices == 1;<br> m_aborted |= parseLambdaFile(m_param);<br> <br>@@ -996,6 +1006,8 @@ void Encoder::destroy()<br> }<br> if (m_naluFile)<br> fclose(m_naluFile);<br>+ if (m_filmGrainIn)<br>+ x265_fclose(m_filmGrainIn);<br> <br> #ifdef SVT_HEVC<br> X265_FREE(m_svtAppData);<br>diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h<br>index 2ee5bdaee..cfbb55fe0 100644<br>--- a/source/encoder/encoder.h<br>+++ b/source/encoder/encoder.h<br>@@ -295,6 +295,8 @@ public:<br> <br> ThreadSafeInteger* zoneReadCount;<br> ThreadSafeInteger* zoneWriteCount;<br>+ /* Film grain model file */<br>+ FILE* m_filmGrainIn;<br> <br> Encoder();<br> ~Encoder()<br>diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp<br>index 1b3875a25..44415d079 100644<br>--- a/source/encoder/frameencoder.cpp<br>+++ b/source/encoder/frameencoder.cpp<br>@@ -762,7 +762,14 @@ void FrameEncoder::compressFrame()<br> m_seiAlternativeTC.m_preferredTransferCharacteristics = m_param->preferredTransferCharacteristics;<br> m_seiAlternativeTC.writeSEImessages(m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal);<br> }<br>-<br>+ /* Write Film grain characteristics if present */<br>+ if (this->m_top->m_filmGrainIn)<br>+ {<br>+ FilmGrainCharacteristics m_filmGrain;<br>+ /* Read the Film grain model file */<br>+ readModel(&m_filmGrain, this->m_top->m_filmGrainIn);<br>+ m_filmGrain.writeSEImessages(m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal);<br>+ }<br> /* Write user SEI */<br> for (int i = 0; i < m_frame->m_userSEI.numPayloads; i++)<br> {<br>@@ -2133,6 +2140,54 @@ void FrameEncoder::noiseReductionUpdate()<br> m_nr->nrOffsetDenoise[cat][0] = 0;<br> }<br> }<br>+<br>+void FrameEncoder::readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain)<br>+{<br>+ char* errorMessage = "Error reading FilmGrain characteristics\n";<br>+ FilmGrain m_fg;<br>+ x265_fread((char* )&m_fg, sizeof(bool) * 3 + sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_filmGrainCharacteristicsCancelFlag = m_fg.m_filmGrainCharacteristicsCancelFlag;<br>+ m_filmGrain->m_filmGrainCharacteristicsPersistenceFlag = m_fg.m_filmGrainCharacteristicsPersistenceFlag;<br>+ m_filmGrain->m_filmGrainModelId = m_fg.m_filmGrainModelId;<br>+ m_filmGrain->m_separateColourDescriptionPresentFlag = m_fg.m_separateColourDescriptionPresentFlag;<br>+ if (m_filmGrain->m_separateColourDescriptionPresentFlag)<br>+ {<br>+ ColourDescription m_clr;<br>+ x265_fread((char* )&m_clr, sizeof(bool) + sizeof(uint8_t) * 5, 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_filmGrainBitDepthLumaMinus8 = m_clr.m_filmGrainBitDepthLumaMinus8;<br>+ m_filmGrain->m_filmGrainBitDepthChromaMinus8 = m_clr.m_filmGrainBitDepthChromaMinus8;<br>+ m_filmGrain->m_filmGrainFullRangeFlag = m_clr.m_filmGrainFullRangeFlag;<br>+ m_filmGrain->m_filmGrainColourPrimaries = m_clr.m_filmGrainColourPrimaries;<br>+ m_filmGrain->m_filmGrainTransferCharacteristics = m_clr.m_filmGrainTransferCharacteristics;<br>+ m_filmGrain->m_filmGrainMatrixCoeffs = m_clr.m_filmGrainMatrixCoeffs;<br>+ }<br>+ FGPresent m_present;<br>+ x265_fread((char* )&m_present, sizeof(bool) * 3 + sizeof(uint8_t) * 2, 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_blendingModeId = m_present.m_blendingModeId;<br>+ m_filmGrain->m_log2ScaleFactor = m_present.m_log2ScaleFactor;<br>+ m_filmGrain->m_compModel[0].bPresentFlag = m_present.m_presentFlag[0];<br>+ m_filmGrain->m_compModel[1].bPresentFlag = m_present.m_presentFlag[1];<br>+ m_filmGrain->m_compModel[2].bPresentFlag = m_present.m_presentFlag[2];<br>+ for (int i = 0; i < MAX_NUM_COMPONENT; i++)<br>+ {<br>+ if (m_filmGrain->m_compModel[i].bPresentFlag)<br>+ {<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].numModelValues), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_compModel[i].intensityValues = (FilmGrainCharacteristics::CompModelIntensityValues* ) malloc(sizeof(FilmGrainCharacteristics::CompModelIntensityValues) * (m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1+1)) ;<br>+ for (int j = 0; j <= m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1; j++)<br>+ {<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].intensityValues[j].intensityIntervalLowerBound), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].intensityValues[j].intensityIntervalUpperBound), sizeof(uint8_t), 1, filmgrain, errorMessage);<br>+ m_filmGrain->m_compModel[i].intensityValues[j].compModelValue = (int* ) malloc(sizeof(int) * (m_filmGrain->m_compModel[i].numModelValues));<br>+ for (int k = 0; k < m_filmGrain->m_compModel[i].numModelValues; k++)<br>+ {<br>+ x265_fread((char* )(&m_filmGrain->m_compModel[i].intensityValues[j].compModelValue[k]), sizeof(int), 1, filmgrain, errorMessage);<br>+ }<br>+ }<br>+ }<br>+ }<br>+}<br> #if ENABLE_LIBVMAF<br> void FrameEncoder::vmafFrameLevelScore()<br> {<br>diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h<br>index f4cfc624d..5d972cb26 100644<br>--- a/source/encoder/frameencoder.h<br>+++ b/source/encoder/frameencoder.h<br>@@ -113,6 +113,34 @@ struct CTURow<br> }<br> };<br> <br>+/*Film grain characteristics*/<br>+struct FilmGrain<br>+{<br>+ bool m_filmGrainCharacteristicsCancelFlag;<br>+ bool m_filmGrainCharacteristicsPersistenceFlag;<br>+ bool m_separateColourDescriptionPresentFlag;<br>+ uint8_t m_filmGrainModelId;<br>+ uint8_t m_blendingModeId;<br>+ uint8_t m_log2ScaleFactor;<br>+};<br>+<br>+struct ColourDescription<br>+{<br>+ bool m_filmGrainFullRangeFlag;<br>+ uint8_t m_filmGrainBitDepthLumaMinus8;<br>+ uint8_t m_filmGrainBitDepthChromaMinus8;<br>+ uint8_t m_filmGrainColourPrimaries;<br>+ uint8_t m_filmGrainTransferCharacteristics;<br>+ uint8_t m_filmGrainMatrixCoeffs;<br>+};<br>+<br>+struct FGPresent<br>+{<br>+ uint8_t m_blendingModeId;<br>+ uint8_t m_log2ScaleFactor;<br>+ bool m_presentFlag[3];<br>+};<br>+<br> // Manages the wave-front processing of a single encoding frame<br> class FrameEncoder : public WaveFront, public Thread<br> {<br>@@ -250,6 +278,7 @@ protected:<br> void collectDynDataFrame();<br> void computeAvgTrainingData();<br> void collectDynDataRow(CUData& ctu, FrameStats* rowStats); <br>+ void readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain);<br> };<br> }<br> <br>diff --git a/source/encoder/sei.h b/source/encoder/sei.h<br>index 61d39edd9..03e210639 100644<br>--- a/source/encoder/sei.h<br>+++ b/source/encoder/sei.h<br>@@ -73,6 +73,101 @@ public:<br> }<br> };<br> <br>+/* Film grain characteristics */<br>+class FilmGrainCharacteristics : public SEI<br>+{<br>+ public:<br>+<br>+ FilmGrainCharacteristics()<br>+ {<br>+ m_payloadType = FILM_GRAIN_CHARACTERISTICS;<br>+ m_payloadSize = 0;<br>+ }<br>+<br>+ struct CompModelIntensityValues<br>+ {<br>+ uint8_t intensityIntervalLowerBound;<br>+ uint8_t intensityIntervalUpperBound;<br>+ int* compModelValue;<br>+ };<br>+<br>+ struct CompModel<br>+ {<br>+ bool bPresentFlag;<br>+ uint8_t numModelValues;<br>+ uint8_t m_filmGrainNumIntensityIntervalMinus1;<br>+ CompModelIntensityValues* intensityValues;<br>+ };<br>+<br>+ CompModel m_compModel[MAX_NUM_COMPONENT];<br>+ bool m_filmGrainCharacteristicsPersistenceFlag;<br>+ bool m_filmGrainCharacteristicsCancelFlag;<br>+ bool m_separateColourDescriptionPresentFlag;<br>+ bool m_filmGrainFullRangeFlag;<br>+ uint8_t m_filmGrainModelId;<br>+ uint8_t m_blendingModeId;<br>+ uint8_t m_log2ScaleFactor;<br>+ uint8_t m_filmGrainBitDepthLumaMinus8;<br>+ uint8_t m_filmGrainBitDepthChromaMinus8;<br>+ uint8_t m_filmGrainColourPrimaries;<br>+ uint8_t m_filmGrainTransferCharacteristics;<br>+ uint8_t m_filmGrainMatrixCoeffs;<br>+<br>+ void writeSEI(const SPS&)<br>+ {<br>+ WRITE_FLAG(m_filmGrainCharacteristicsCancelFlag, "film_grain_characteristics_cancel_flag");<br>+<br>+ if (!m_filmGrainCharacteristicsCancelFlag)<br>+ {<br>+ WRITE_CODE(m_filmGrainModelId, 2, "film_grain_model_id");<br>+ WRITE_FLAG(m_separateColourDescriptionPresentFlag, "separate_colour_description_present_flag");<br>+ if (m_separateColourDescriptionPresentFlag)<br>+ {<br>+ WRITE_CODE(m_filmGrainBitDepthLumaMinus8, 3, "film_grain_bit_depth_luma_minus8");<br>+ WRITE_CODE(m_filmGrainBitDepthChromaMinus8, 3, "film_grain_bit_depth_chroma_minus8");<br>+ WRITE_FLAG(m_filmGrainFullRangeFlag, "film_grain_full_range_flag");<br>+ WRITE_CODE(m_filmGrainColourPrimaries, X265_BYTE, "film_grain_colour_primaries");<br>+ WRITE_CODE(m_filmGrainTransferCharacteristics, X265_BYTE, "film_grain_transfer_characteristics");<br>+ WRITE_CODE(m_filmGrainMatrixCoeffs, X265_BYTE, "film_grain_matrix_coeffs");<br>+ }<br>+ WRITE_CODE(m_blendingModeId, 2, "blending_mode_id");<br>+ WRITE_CODE(m_log2ScaleFactor, 4, "log2_scale_factor");<br>+ for (uint8_t c = 0; c < 3; c++)<br>+ {<br>+ WRITE_FLAG(m_compModel[c].bPresentFlag && m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 && m_compModel[c].numModelValues > 0, "comp_model_present_flag[c]");<br>+ }<br>+ for (uint8_t c = 0; c < 3; c++)<br>+ {<br>+ if (m_compModel[c].bPresentFlag && m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 && m_compModel[c].numModelValues > 0)<br>+ {<br>+ assert(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 <= 256);<br>+ assert(m_compModel[c].numModelValues <= X265_BYTE);<br>+ WRITE_CODE(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 , X265_BYTE, "num_intensity_intervals_minus1[c]");<br>+ WRITE_CODE(m_compModel[c].numModelValues - 1, 3, "num_model_values_minus1[c]");<br>+ for (uint8_t interval = 0; interval < m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1; interval++)<br>+ {<br>+ WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalLowerBound, X265_BYTE, "intensity_interval_lower_bound[c][i]");<br>+ WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalUpperBound, X265_BYTE, "intensity_interval_upper_bound[c][i]");<br>+ for (uint8_t j = 0; j < m_compModel[c].numModelValues; j++)<br>+ {<br>+ WRITE_SVLC(m_compModel[c].intensityValues[interval].compModelValue[j],"comp_model_value[c][i]");<br>+ }<br>+ }<br>+ }<br>+ }<br>+ WRITE_FLAG(m_filmGrainCharacteristicsPersistenceFlag, "film_grain_characteristics_persistence_flag");<br>+ }<br>+ if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)<br>+ {<br>+ WRITE_FLAG(1, "payload_bit_equal_to_one");<br>+ while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)<br>+ {<br>+ WRITE_FLAG(0, "payload_bit_equal_to_zero");<br>+ }<br>+ }<br>+ }<br>+};<br>+<br> static const uint32_t ISO_IEC_11578_LEN = 16;<br> <br> class SEIuserDataUnregistered : public SEI<br>diff --git a/source/test/regression-tests.txt b/source/test/regression-tests.txt<br>index 26d43b28a..10a4449e7 100644<br>--- a/source/test/regression-tests.txt<br>+++ b/source/test/regression-tests.txt<br>@@ -195,4 +195,8 @@ CrowdRun_1920x1080_50_10bit_422.yuv,--no-cutree --analysis-save x265_analysis.da<br> #segment encoding<br> BasketballDrive_1920x1080_50.y4m, --preset ultrafast --no-open-gop --chunk-start 100 --chunk-end 200<br> <br>+#Test FG SEI message addition<br>+#OldTownCross_1920x1080_50_10bit_422.yuv,--preset slower --tune grain --film-grain "OldTownCross_1920x1080_50_10bit_422.bin"<br>+#RaceHorses_416x240_30_10bit.yuv,--preset ultrafast --signhide --colormatrix bt709 --film-grain "RaceHorses_416x240_30_10bit.bin"<br>+<br> # vim: tw=200<br>diff --git a/source/test/smoke-tests.txt b/source/test/smoke-tests.txt<br>index 041b97e76..a88a225b4 100644<br>--- a/source/test/smoke-tests.txt<br>+++ b/source/test/smoke-tests.txt<br>@@ -23,3 +23,7 @@ CrowdRun_1920x1080_50_10bit_444.yuv,--preset=superfast --bitrate 7000 --sao --li<br> # Main12 intraCost overflow bug test<br> 720p50_parkrun_ter.y4m,--preset medium<br> 720p50_parkrun_ter.y4m,--preset=fast --hevc-aq --no-cutree<br>+# Test FG SEI message addition<br>+# CrowdRun_1920x1080_50_10bit_444.yuv,--preset=ultrafast --weightp --keyint -1 --film-grain "CrowdRun_1920x1080_50_10bit_444.bin"<br>+# DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset=veryfast --min-cu 16 --film-grain "DucksAndLegs_1920x1080_60_10bit_422.bin"<br>+# NebutaFestival_2560x1600_60_10bit_crop.yuv,--preset=superfast --bitrate 10000 --sao --limit-sao --cll --max-cll "1000,400" --film-grain "NebutaFestival_2560x1600_60_10bit_crop.bin"<br>diff --git a/source/x265.h b/source/x265.h<br>index bf945498f..5d242d653 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -1989,6 +1989,9 @@ typedef struct x265_param<br> /* Flag to turn on/off traditional scenecut detection in histogram based scenecut detection.<br> * When false, only spatial properties are used for scenecut detection. Default true */<br> int bEnableTradScdInHscd;<br>+<br>+ /* Film Grain Characteristic file */<br>+ char* filmGrain;<br> } x265_param;<br> <br> /* x265_param_alloc:<br>diff --git a/source/x265cli.cpp b/source/x265cli.cpp<br>index bfb6293f3..3a03de579 100755<br>--- a/source/x265cli.cpp<br>+++ b/source/x265cli.cpp<br>@@ -391,6 +391,9 @@ namespace X265_NS {<br> H1(" 2 - unable to open encoder\n");<br> H1(" 3 - unable to generate stream headers\n");<br> H1(" 4 - encoder abort\n");<br>+ H0("\nSEI Message Options\n");<br>+ H0(" --film-grain <filename> File containing Film Grain Characteristics to be written as a SEI Message\n");<br>+<br> #undef OPT<br> #undef H0<br> #undef H1<br>diff --git a/source/x265cli.h b/source/x265cli.h<br>index 8fcf37b8a..7072f7616 100644<br>--- a/source/x265cli.h<br>+++ b/source/x265cli.h<br>@@ -380,6 +380,7 @@ static const struct option long_options[] =<br> { "abr-ladder", required_argument, NULL, 0 },<br> { "min-vbv-fullness", required_argument, NULL, 0 },<br> { "max-vbv-fullness", required_argument, NULL, 0 },<br>+ { "film-grain", required_argument, NULL, 0 },<br> { 0, 0, 0, 0 },<br> { 0, 0, 0, 0 },<br> { 0, 0, 0, 0 },<br>-- <br>2.20.1.windows.1<br><br></div>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><b style="background-color:rgb(255,255,255)"><font color="#0b5394">With Regards,</font></b><div><b style="background-color:rgb(255,255,255)"><font color="#0b5394">Srikanth Kurapati.</font></b></div></div></div>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div>