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

Keshav E keshav at multicorewareinc.com
Fri Mar 4 08:16:24 UTC 2022


Observed a warning in the patch sent in the previous email. Resolved the
warning and reattaching the patch here.
>From 0ba89aaa409d09f94348536edf7cede8f3f7f7e7 Mon Sep 17 00:00:00 2001
From: Keshav E <keshav at multicorewareinc.com>
Date: Fri, 4 Mar 2022 12:36:14 +0530
Subject: [PATCH] Add film grain characteristics as a SEI message to the
 bitstream

---
 doc/reST/cli.rst                 |  6 ++
 source/CMakeLists.txt            |  2 +-
 source/common/common.h           |  9 +++
 source/common/param.cpp          |  9 +++
 source/encoder/encoder.cpp       | 12 ++++
 source/encoder/encoder.h         |  2 +
 source/encoder/frameencoder.cpp  | 57 ++++++++++++++++++-
 source/encoder/frameencoder.h    | 29 ++++++++++
 source/encoder/sei.h             | 95 ++++++++++++++++++++++++++++++++
 source/test/regression-tests.txt |  4 ++
 source/test/smoke-tests.txt      |  4 ++
 source/x265.h                    |  3 +
 source/x265cli.cpp               |  3 +
 source/x265cli.h                 |  1 +
 14 files changed, 234 insertions(+), 2 deletions(-)

diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index 1491b63fe..1640c1f8e 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2659,6 +2659,12 @@ Bitstream options
  Emit SEI messages in a single NAL unit instead of multiple NALs. Default
disabled.
  When HRD SEI is enabled the HM decoder will throw a warning.

+.. option:: --film-grain <filename>
+
+    Refers to the film grain model characteristics for signal enhancement
information transmission
+
+    **CLI_ONLY**
+
 DCT Approximations
 =================

diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 60031df63..13e4750de 100755
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)
 option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)
 mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
 # X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 203)
+set(X265_BUILD 204)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff --git a/source/common/common.h b/source/common/common.h
index 8c06cd79e..a245c7dae 100644
--- a/source/common/common.h
+++ b/source/common/common.h
@@ -340,6 +340,7 @@ typedef int16_t  coeff_t;      // transform coefficient
 #define FILLER_OVERHEAD (NAL_TYPE_OVERHEAD + START_CODE_OVERHEAD + 1)

 #define MAX_NUM_DYN_REFINE          (NUM_CU_DEPTH *
X265_REFINE_INTER_LEVELS)
+#define X265_BYTE 8

 namespace X265_NS {

@@ -434,6 +435,14 @@ int      x265_rename(const char* oldName, const char*
newName);
 #define  x265_unlink(fileName) unlink(fileName)
 #define  x265_rename(oldName, newName) rename(oldName, newName)
 #endif
+/* Close a file */
+#define  x265_fclose(file) if (file != NULL) fclose(file); file=NULL;
+#define x265_fread(val, size, readSize, fileOffset,errorMessage)\
+    if (fread(val, size, readSize, fileOffset) != readSize)\
+    {\
+        x265_log(NULL, X265_LOG_ERROR, errorMessage); \
+        return; \
+    }
 int      x265_exp2fix8(double x);

 double   x265_ssim2dB(double ssim);
diff --git a/source/common/param.cpp b/source/common/param.cpp
index f72305372..ed6973d9c 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -384,6 +384,8 @@ void x265_param_default(x265_param* param)
     param->svtHevcParam = svtParam;
     svt_param_default(param);
 #endif
+    /* Film grain characteristics model filename */
+    param->filmGrain = NULL;
 }

 int x265_param_default_preset(x265_param* param, const char* preset, const
char* tune)
@@ -1460,6 +1462,8 @@ int x265_param_parse(x265_param* p, const char* name,
const char* value)
         OPT("video-signal-type-preset") p->videoSignalTypePreset =
strdup(value);
         OPT("eob") p->bEnableEndOfBitstream = atobool(value);
         OPT("eos") p->bEnableEndOfSequence = atobool(value);
+        /* Film grain characterstics model filename */
+        OPT("film-grain") p->filmGrain = (char* )value;
         else
             return X265_PARAM_BAD_NAME;
     }
@@ -2353,6 +2357,8 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
     s += sprintf(s, "conformance-window-offsets right=%d bottom=%d",
p->confWinRightOffset, p->confWinBottomOffset);
     s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate);
     BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");
+    if (p->filmGrain)
+        s += sprintf(s, " film-grain=%s", p->filmGrain); // Film grain
characteristics model filename
 #undef BOOL
     return buf;
 }
@@ -2726,6 +2732,9 @@ void x265_copy_params(x265_param* dst, x265_param*
src)
 #ifdef SVT_HEVC
     memcpy(dst->svtHevcParam, src->svtHevcParam,
sizeof(EB_H265_ENC_CONFIGURATION));
 #endif
+    /* Film grain */
+    if (src->filmGrain)
+        dst->filmGrain = src->filmGrain;
 }

 #ifdef SVT_HEVC
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 5d0c9a050..f33a6d053 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -142,6 +142,7 @@ Encoder::Encoder()
     m_threadPool = NULL;
     m_analysisFileIn = NULL;
     m_analysisFileOut = NULL;
+    m_filmGrainIn = NULL;
     m_naluFile = NULL;
     m_offsetEmergency = NULL;
     m_iFrameNum = 0;
@@ -551,6 +552,15 @@ void Encoder::create()
             }
         }
     }
+    if (m_param->filmGrain)
+    {
+        m_filmGrainIn = x265_fopen(m_param->filmGrain, "rb");
+        if (!m_filmGrainIn)
+        {
+            x265_log_file(NULL, X265_LOG_ERROR, "Failed to open film grain
characteristics binary file %s\n", m_param->filmGrain);
+        }
+    }
+
     m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth &&
m_param->frameNumThreads == 1 && m_param->maxSlices == 1;
     m_aborted |= parseLambdaFile(m_param);

@@ -996,6 +1006,8 @@ void Encoder::destroy()
      }
     if (m_naluFile)
         fclose(m_naluFile);
+    if (m_filmGrainIn)
+        x265_fclose(m_filmGrainIn);

 #ifdef SVT_HEVC
     X265_FREE(m_svtAppData);
diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
index 2ee5bdaee..cfbb55fe0 100644
--- a/source/encoder/encoder.h
+++ b/source/encoder/encoder.h
@@ -295,6 +295,8 @@ public:

     ThreadSafeInteger* zoneReadCount;
     ThreadSafeInteger* zoneWriteCount;
+    /* Film grain model file */
+    FILE* m_filmGrainIn;

     Encoder();
     ~Encoder()
diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index 1b3875a25..9dc9242f6 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -762,7 +762,14 @@ void FrameEncoder::compressFrame()
         m_seiAlternativeTC.m_preferredTransferCharacteristics =
m_param->preferredTransferCharacteristics;
         m_seiAlternativeTC.writeSEImessages(m_bs, *slice->m_sps,
NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal);
     }
-
+    /* Write Film grain characteristics if present */
+    if (this->m_top->m_filmGrainIn)
+    {
+        FilmGrainCharacteristics m_filmGrain;
+        /* Read the Film grain model file */
+        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);
+    }
     /* Write user SEI */
     for (int i = 0; i < m_frame->m_userSEI.numPayloads; i++)
     {
@@ -2133,6 +2140,54 @@ void FrameEncoder::noiseReductionUpdate()
         m_nr->nrOffsetDenoise[cat][0] = 0;
     }
 }
+
+void FrameEncoder::readModel(FilmGrainCharacteristics* m_filmGrain, FILE*
filmgrain)
+{
+    char const* errorMessage = "Error reading FilmGrain characteristics\n";
+    FilmGrain m_fg;
+    x265_fread((char* )&m_fg, sizeof(bool) * 3 + sizeof(uint8_t), 1,
filmgrain, errorMessage);
+    m_filmGrain->m_filmGrainCharacteristicsCancelFlag =
m_fg.m_filmGrainCharacteristicsCancelFlag;
+    m_filmGrain->m_filmGrainCharacteristicsPersistenceFlag =
m_fg.m_filmGrainCharacteristicsPersistenceFlag;
+    m_filmGrain->m_filmGrainModelId = m_fg.m_filmGrainModelId;
+    m_filmGrain->m_separateColourDescriptionPresentFlag =
m_fg.m_separateColourDescriptionPresentFlag;
+    if (m_filmGrain->m_separateColourDescriptionPresentFlag)
+    {
+        ColourDescription m_clr;
+        x265_fread((char* )&m_clr, sizeof(bool) + sizeof(uint8_t) * 5, 1,
filmgrain, errorMessage);
+        m_filmGrain->m_filmGrainBitDepthLumaMinus8 =
m_clr.m_filmGrainBitDepthLumaMinus8;
+        m_filmGrain->m_filmGrainBitDepthChromaMinus8 =
m_clr.m_filmGrainBitDepthChromaMinus8;
+        m_filmGrain->m_filmGrainFullRangeFlag =
m_clr.m_filmGrainFullRangeFlag;
+        m_filmGrain->m_filmGrainColourPrimaries =
m_clr.m_filmGrainColourPrimaries;
+        m_filmGrain->m_filmGrainTransferCharacteristics =
m_clr.m_filmGrainTransferCharacteristics;
+        m_filmGrain->m_filmGrainMatrixCoeffs =
m_clr.m_filmGrainMatrixCoeffs;
+    }
+    FGPresent m_present;
+    x265_fread((char* )&m_present, sizeof(bool) * 3 + sizeof(uint8_t) * 2,
1, filmgrain, errorMessage);
+    m_filmGrain->m_blendingModeId = m_present.m_blendingModeId;
+    m_filmGrain->m_log2ScaleFactor = m_present.m_log2ScaleFactor;
+    m_filmGrain->m_compModel[0].bPresentFlag = m_present.m_presentFlag[0];
+    m_filmGrain->m_compModel[1].bPresentFlag = m_present.m_presentFlag[1];
+    m_filmGrain->m_compModel[2].bPresentFlag = m_present.m_presentFlag[2];
+    for (int i = 0; i < MAX_NUM_COMPONENT; i++)
+    {
+        if (m_filmGrain->m_compModel[i].bPresentFlag)
+        {
+            x265_fread((char*
)(&m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1),
sizeof(uint8_t), 1, filmgrain, errorMessage);
+            x265_fread((char*
)(&m_filmGrain->m_compModel[i].numModelValues), sizeof(uint8_t), 1,
filmgrain, errorMessage);
+            m_filmGrain->m_compModel[i].intensityValues =
(FilmGrainCharacteristics::CompModelIntensityValues* )
malloc(sizeof(FilmGrainCharacteristics::CompModelIntensityValues) *
(m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1+1)) ;
+            for (int j = 0; j <=
m_filmGrain->m_compModel[i].m_filmGrainNumIntensityIntervalMinus1; j++)
+            {
+                x265_fread((char*
)(&m_filmGrain->m_compModel[i].intensityValues[j].intensityIntervalLowerBound),
sizeof(uint8_t), 1, filmgrain, errorMessage);
+                x265_fread((char*
)(&m_filmGrain->m_compModel[i].intensityValues[j].intensityIntervalUpperBound),
sizeof(uint8_t), 1, filmgrain, errorMessage);
+
 m_filmGrain->m_compModel[i].intensityValues[j].compModelValue = (int* )
malloc(sizeof(int) * (m_filmGrain->m_compModel[i].numModelValues));
+                for (int k = 0; k <
m_filmGrain->m_compModel[i].numModelValues; k++)
+                {
+                    x265_fread((char*
)(&m_filmGrain->m_compModel[i].intensityValues[j].compModelValue[k]),
sizeof(int), 1, filmgrain, errorMessage);
+                }
+            }
+        }
+    }
+}
 #if ENABLE_LIBVMAF
 void FrameEncoder::vmafFrameLevelScore()
 {
diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h
index f4cfc624d..5d972cb26 100644
--- a/source/encoder/frameencoder.h
+++ b/source/encoder/frameencoder.h
@@ -113,6 +113,34 @@ struct CTURow
     }
 };

+/*Film grain characteristics*/
+struct FilmGrain
+{
+    bool    m_filmGrainCharacteristicsCancelFlag;
+    bool    m_filmGrainCharacteristicsPersistenceFlag;
+    bool    m_separateColourDescriptionPresentFlag;
+    uint8_t m_filmGrainModelId;
+    uint8_t m_blendingModeId;
+    uint8_t m_log2ScaleFactor;
+};
+
+struct ColourDescription
+{
+    bool        m_filmGrainFullRangeFlag;
+    uint8_t     m_filmGrainBitDepthLumaMinus8;
+    uint8_t     m_filmGrainBitDepthChromaMinus8;
+    uint8_t     m_filmGrainColourPrimaries;
+    uint8_t     m_filmGrainTransferCharacteristics;
+    uint8_t     m_filmGrainMatrixCoeffs;
+};
+
+struct FGPresent
+{
+    uint8_t     m_blendingModeId;
+    uint8_t     m_log2ScaleFactor;
+    bool        m_presentFlag[3];
+};
+
 // Manages the wave-front processing of a single encoding frame
 class FrameEncoder : public WaveFront, public Thread
 {
@@ -250,6 +278,7 @@ protected:
     void collectDynDataFrame();
     void computeAvgTrainingData();
     void collectDynDataRow(CUData& ctu, FrameStats* rowStats);
+    void readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain);
 };
 }

diff --git a/source/encoder/sei.h b/source/encoder/sei.h
index 61d39edd9..03e210639 100644
--- a/source/encoder/sei.h
+++ b/source/encoder/sei.h
@@ -73,6 +73,101 @@ public:
     }
 };

+/* Film grain characteristics */
+class FilmGrainCharacteristics : public SEI
+{
+  public:
+
+    FilmGrainCharacteristics()
+    {
+        m_payloadType = FILM_GRAIN_CHARACTERISTICS;
+        m_payloadSize = 0;
+    }
+
+    struct CompModelIntensityValues
+    {
+        uint8_t intensityIntervalLowerBound;
+        uint8_t intensityIntervalUpperBound;
+        int*    compModelValue;
+    };
+
+    struct CompModel
+    {
+        bool    bPresentFlag;
+        uint8_t numModelValues;
+        uint8_t m_filmGrainNumIntensityIntervalMinus1;
+        CompModelIntensityValues* intensityValues;
+    };
+
+    CompModel   m_compModel[MAX_NUM_COMPONENT];
+    bool        m_filmGrainCharacteristicsPersistenceFlag;
+    bool        m_filmGrainCharacteristicsCancelFlag;
+    bool        m_separateColourDescriptionPresentFlag;
+    bool        m_filmGrainFullRangeFlag;
+    uint8_t     m_filmGrainModelId;
+    uint8_t     m_blendingModeId;
+    uint8_t     m_log2ScaleFactor;
+    uint8_t     m_filmGrainBitDepthLumaMinus8;
+    uint8_t     m_filmGrainBitDepthChromaMinus8;
+    uint8_t     m_filmGrainColourPrimaries;
+    uint8_t     m_filmGrainTransferCharacteristics;
+    uint8_t     m_filmGrainMatrixCoeffs;
+
+    void writeSEI(const SPS&)
+    {
+        WRITE_FLAG(m_filmGrainCharacteristicsCancelFlag,
"film_grain_characteristics_cancel_flag");
+
+        if (!m_filmGrainCharacteristicsCancelFlag)
+        {
+            WRITE_CODE(m_filmGrainModelId, 2, "film_grain_model_id");
+            WRITE_FLAG(m_separateColourDescriptionPresentFlag,
"separate_colour_description_present_flag");
+            if (m_separateColourDescriptionPresentFlag)
+            {
+                WRITE_CODE(m_filmGrainBitDepthLumaMinus8, 3,
"film_grain_bit_depth_luma_minus8");
+                WRITE_CODE(m_filmGrainBitDepthChromaMinus8, 3,
"film_grain_bit_depth_chroma_minus8");
+                WRITE_FLAG(m_filmGrainFullRangeFlag,
"film_grain_full_range_flag");
+                WRITE_CODE(m_filmGrainColourPrimaries, X265_BYTE,
"film_grain_colour_primaries");
+                WRITE_CODE(m_filmGrainTransferCharacteristics, X265_BYTE,
"film_grain_transfer_characteristics");
+                WRITE_CODE(m_filmGrainMatrixCoeffs, X265_BYTE,
"film_grain_matrix_coeffs");
+            }
+            WRITE_CODE(m_blendingModeId, 2, "blending_mode_id");
+            WRITE_CODE(m_log2ScaleFactor, 4, "log2_scale_factor");
+            for (uint8_t c = 0; c < 3; c++)
+            {
+                WRITE_FLAG(m_compModel[c].bPresentFlag &&
m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 &&
m_compModel[c].numModelValues > 0, "comp_model_present_flag[c]");
+            }
+            for (uint8_t c = 0; c < 3; c++)
+            {
+                if (m_compModel[c].bPresentFlag &&
m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 &&
m_compModel[c].numModelValues > 0)
+                {
+
 assert(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 <= 256);
+                    assert(m_compModel[c].numModelValues <= X265_BYTE);
+
 WRITE_CODE(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 ,
X265_BYTE, "num_intensity_intervals_minus1[c]");
+                    WRITE_CODE(m_compModel[c].numModelValues - 1, 3,
"num_model_values_minus1[c]");
+                    for (uint8_t interval = 0; interval <
m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1; interval++)
+                    {
+
 WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalLowerBound,
X265_BYTE, "intensity_interval_lower_bound[c][i]");
+
 WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalUpperBound,
X265_BYTE, "intensity_interval_upper_bound[c][i]");
+                        for (uint8_t j = 0; j <
m_compModel[c].numModelValues; j++)
+                        {
+
 WRITE_SVLC(m_compModel[c].intensityValues[interval].compModelValue[j],"comp_model_value[c][i]");
+                        }
+                    }
+                }
+            }
+            WRITE_FLAG(m_filmGrainCharacteristicsPersistenceFlag,
"film_grain_characteristics_persistence_flag");
+        }
+        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/test/regression-tests.txt
b/source/test/regression-tests.txt
index 26d43b28a..10a4449e7 100644
--- a/source/test/regression-tests.txt
+++ b/source/test/regression-tests.txt
@@ -195,4 +195,8 @@ CrowdRun_1920x1080_50_10bit_422.yuv,--no-cutree
--analysis-save x265_analysis.da
 #segment encoding
 BasketballDrive_1920x1080_50.y4m, --preset ultrafast --no-open-gop
--chunk-start 100 --chunk-end 200

+#Test FG SEI message addition
+#OldTownCross_1920x1080_50_10bit_422.yuv,--preset slower --tune grain
--film-grain "OldTownCross_1920x1080_50_10bit_422.bin"
+#RaceHorses_416x240_30_10bit.yuv,--preset ultrafast --signhide
--colormatrix bt709 --film-grain "RaceHorses_416x240_30_10bit.bin"
+
 # vim: tw=200
diff --git a/source/test/smoke-tests.txt b/source/test/smoke-tests.txt
index 041b97e76..a88a225b4 100644
--- a/source/test/smoke-tests.txt
+++ b/source/test/smoke-tests.txt
@@ -23,3 +23,7 @@ CrowdRun_1920x1080_50_10bit_444.yuv,--preset=superfast
--bitrate 7000 --sao --li
 # Main12 intraCost overflow bug test
 720p50_parkrun_ter.y4m,--preset medium
 720p50_parkrun_ter.y4m,--preset=fast --hevc-aq --no-cutree
+# Test FG SEI message addition
+# CrowdRun_1920x1080_50_10bit_444.yuv,--preset=ultrafast --weightp
--keyint -1 --film-grain "CrowdRun_1920x1080_50_10bit_444.bin"
+# DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset=veryfast --min-cu 16
--film-grain "DucksAndLegs_1920x1080_60_10bit_422.bin"
+# 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"
diff --git a/source/x265.h b/source/x265.h
index bf945498f..5d242d653 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -1989,6 +1989,9 @@ typedef struct x265_param
     /* Flag to turn on/off traditional scenecut detection in histogram
based scenecut detection.
      * When false, only spatial properties are used for scenecut
detection. Default true */
     int      bEnableTradScdInHscd;
+
+    /* Film Grain Characteristic file */
+    char* filmGrain;
 } x265_param;

 /* x265_param_alloc:
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index bfb6293f3..3a03de579 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -391,6 +391,9 @@ namespace X265_NS {
         H1("    2 - unable to open encoder\n");
         H1("    3 - unable to generate stream headers\n");
         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");
+
 #undef OPT
 #undef H0
 #undef H1
diff --git a/source/x265cli.h b/source/x265cli.h
index 8fcf37b8a..7072f7616 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -380,6 +380,7 @@ static const struct option long_options[] =
     { "abr-ladder", required_argument, NULL, 0 },
     { "min-vbv-fullness", required_argument, NULL, 0 },
     { "max-vbv-fullness", required_argument, NULL, 0 },
+    { "film-grain", required_argument, NULL, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
-- 
2.20.1.windows.1


On Fri, Mar 4, 2022 at 11:09 AM Srikanth Kurapati <
srikanth.kurapati at multicorewareinc.com> wrote:

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

system:      Sitar
hardware:    
testharness: 6909fedd61fbd858320887ec1c5e506c0c14a700
commit 21a67ff4944097c6052fc9936d5741083d605342
Author: Keshav E <keshav at multicorewareinc.com>
Date:   Thu Mar 3 14:30:57 2022 +0530

    Add film grain characteristics as a SEI message to the bitstream
Uncommitted changes in the working directory:
commit 21a67ff4944097c6052fc9936d5741083d605342
Author: Keshav E <keshav at multicorewareinc.com>
Date:   Thu Mar 3 14:30:57 2022 +0530

    Add film grain characteristics as a SEI message to the bitstream


Running /home/mcw/keshav/x265_new/source/test/smoke-tests.txt

cur build: gcc-main10-debug group=gcc-main10deb
generator: Unix Makefiles
options  : warn debug main10 tests checked {}

cur build: gccmain12 group=gcc-main12
generator: Unix Makefiles
options  : warn tests main12 checked {}

cur build: gcc-debug group=gccdeb
generator: Unix Makefiles
options  : warn debug tests checked {}

cur build: gcc group=gcc
generator: Unix Makefiles
options  : warn tests checked {}

cur build: gcc-multilib group=gcc-multilib
generator: Unix Makefiles
options  : warn checked {'add-depths': ['10bit', '12bit']}

cur build: gcc-main10 group=gcc-main10
generator: Unix Makefiles
options  : warn main10 tests checked {}

cur build: gccmain12-debug group=gcc-main12deb
generator: Unix Makefiles
options  : warn debug tests main12 checked {}

cur build: gcc-32 group=gcc-32
generator: Unix Makefiles
options  : static warn checked {'CFLAGS': '-m32'}

cur build: gcc-main10-debug group=gcc-main10deb
generator: Unix Makefiles
options  : warn debug main10 tests checked {}

cur build: gcc group=gcc
generator: Unix Makefiles
options  : warn tests checked {}

cur build: gcc-debug group=gccdeb
generator: Unix Makefiles
options  : warn debug tests checked {}

cur build: gcc-multilib group=gcc-multilib
generator: Unix Makefiles
options  : warn checked {'add-depths': ['10bit', '12bit']}

cur build: gcc-main10 group=gcc-main10
generator: Unix Makefiles
options  : warn main10 tests checked {}

cur build: gccmain12 group=gcc-main12
generator: Unix Makefiles
options  : warn tests main12 checked {}

cur build: gccmain12-debug group=gcc-main12deb
generator: Unix Makefiles
options  : warn debug tests main12 checked {}

cur build: gcc-32 group=gcc-32
generator: Unix Makefiles
options  : static warn checked {'CFLAGS': '-m32'}


All tests passed for 21a67ff4944097c6052fc9936d5741083d605342 on Sitar
-------------- next part --------------

system:      
hardware:    
testharness: 6909fedd61fbd858320887ec1c5e506c0c14a700
commit ec0305cf6e30adac41711279c50b3513d3cc6f92
Author: Keshav E <keshav at multicorewareinc.com>
Date:   Fri Mar 4 12:36:14 2022 +0530

    Add film grain characteristics as a SEI message to the bitstream


Running C:\Users\mcw\Desktop\keshav\smoke_test\x265_test\x265_patch\source\test\smoke-tests.txt

cur build: vc12_64_multilib group=vc12_multi
generator: Visual Studio 12 Win64
options  : warn dhdr10 checked {'add-depths': ['10bit', '12bit']}

cur build: vc12_64_main12 group=vc12_12bit
generator: Visual Studio 12 Win64
options  : tests main12 warn dhdr10 checked {}

cur build: vc12_64_8bpp_debug group=vc12deb
generator: Visual Studio 12 Win64
options  : tests warn debug dhdr10 checked {}

cur build: vc12_64_8bpp group=vc12
generator: Visual Studio 12 Win64
options  : tests warn dhdr10 checked {}

cur build: vc12_64_16bpp group=vc12_16bit
generator: Visual Studio 12 Win64
options  : tests main10 warn dhdr10 checked {}

cur build: vc12_64_16bpp_debug group=vc12_16deb
generator: Visual Studio 12 Win64
options  : tests main10 debug dhdr10 warn checked {}

cur build: vc12_64_main12_debug group=vc12_12deb
generator: Visual Studio 12 Win64
options  : tests main12 debug dhdr10 warn checked {}

cur build: vc12_64_multilib group=vc12_multi
generator: Visual Studio 12 Win64
options  : warn dhdr10 checked {'add-depths': ['10bit', '12bit']}

cur build: vc12_64_main12 group=vc12_12bit
generator: Visual Studio 12 Win64
options  : tests main12 warn dhdr10 checked {}

cur build: vc12_64_8bpp_debug group=vc12deb
generator: Visual Studio 12 Win64
options  : tests warn debug dhdr10 checked {}

cur build: vc12_64_8bpp group=vc12
generator: Visual Studio 12 Win64
options  : tests warn dhdr10 checked {}

cur build: vc12_64_16bpp group=vc12_16bit
generator: Visual Studio 12 Win64
options  : tests main10 warn dhdr10 checked {}

cur build: vc12_64_16bpp_debug group=vc12_16deb
generator: Visual Studio 12 Win64
options  : tests main10 debug dhdr10 warn checked {}

cur build: vc12_64_main12_debug group=vc12_12deb
generator: Visual Studio 12 Win64
options  : tests main12 debug dhdr10 warn checked {}


All tests passed for ec0305cf6e30adac41711279c50b3513d3cc6f92 on 
-------------- next part --------------

system:      iMac
hardware:    OSX10.12.6_Sierra_IntelCorei5 at 3GHz_RAM8GB
testharness: 6909fedd61fbd858320887ec1c5e506c0c14a700
commit 204792b05bd60171d92f42e50b65ed1317119d16
Author: Keshav E <keshav at multicorewareinc.com>
Date:   Fri Mar 4 12:36:14 2022 +0530

    Add film grain characteristics as a SEI message to the bitstream


Running /Users/mcw/keshav/x265_git/source/test/smoke-tests.txt

cur build: xcode_16bpp group=xcode10
generator: Unix Makefiles
options  : main10 {}

cur build: xcode_8bpp group=xcode
generator: Unix Makefiles
options  : checked {}

cur build: xcode_main12 group=xcodemain12
generator: Unix Makefiles
options  : main12 {}

cur build: xcode_16bpp group=xcode10
generator: Unix Makefiles
options  : main10 {}

cur build: xcode_8bpp group=xcode
generator: Unix Makefiles
options  : checked {}

cur build: xcode_main12 group=xcodemain12
generator: Unix Makefiles
options  : main12 {}


All tests passed for 204792b05bd60171d92f42e50b65ed1317119d16 on iMac
-------------- next part --------------
A non-text attachment was scrubbed...
Name: final_patch_v1_1.diff
Type: application/octet-stream
Size: 20286 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20220304/5d70a38b/attachment-0001.obj>


More information about the x265-devel mailing list