[x265] [PATCH 2 of 5] dhdr10-info: add tone-mapping metadata as SEI message with cli option

bhavna at multicorewareinc.com bhavna at multicorewareinc.com
Thu Apr 20 07:46:59 CEST 2017


# HG changeset patch
# User Bhavna Hariharan <bhavna at multicorewareinc.com>
# Date 1492645019 25200
#      Wed Apr 19 16:36:59 2017 -0700
# Node ID e2eb86dce7f493cd14ea3d8bc002d17f839b1aa7
# Parent  f0545a714a70c18bc462e477ce5ce962b9253cb7
dhdr10-info: add tone-mapping metadata as SEI message with cli option

diff -r f0545a714a70 -r e2eb86dce7f4 source/CMakeLists.txt
--- a/source/CMakeLists.txt	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/CMakeLists.txt	Wed Apr 19 16:36:59 2017 -0700
@@ -29,7 +29,7 @@
 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 114)
+set(X265_BUILD 115)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
@@ -363,6 +363,13 @@
 else(HIGH_BIT_DEPTH)
     add_definitions(-DHIGH_BIT_DEPTH=0 -DX265_DEPTH=8)
 endif(HIGH_BIT_DEPTH)
+# this option is to enable the inclusion of dynamic HDR10 library to the libx265 compilation
+option(ENABLE_DYNAMIC_HDR10 "Enable dynamic HDR10 compilation" OFF)
+if (ENABLE_DYNAMIC_HDR10)
+    add_subdirectory(dynamicHDR10)
+    include_directories(dynamicHDR10)
+    add_definitions(-DENABLE_DYNAMIC_HDR10)
+endif(ENABLE_DYNAMIC_HDR10)
 
 # this option can only be used when linking multiple libx265 libraries
 # together, and some alternate API access method is implemented.
@@ -502,9 +509,12 @@
         endforeach()
     endif()
 endif()
-
 source_group(ASM FILES ${ASM_SRCS})
-add_library(x265-static STATIC $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> ${ASM_OBJS} ${ASM_SRCS})
+if(ENABLE_DYNAMIC_HDR10)
+    add_library(x265-static STATIC $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> $<TARGET_OBJECTS:dynamicHDR10> ${ASM_OBJS} ${ASM_SRCS})
+else()
+    add_library(x265-static STATIC $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> ${ASM_OBJS} ${ASM_SRCS})
+endif()
 if(NOT MSVC)
     set_target_properties(x265-static PROPERTIES OUTPUT_NAME x265)
 endif()
@@ -535,11 +545,16 @@
 if(NOT (MSVC_IDE OR XCODE))
     add_custom_target(clean-generated COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/clean-generated.cmake)
 endif()
-
 option(ENABLE_SHARED "Build shared library" ON)
 if(ENABLE_SHARED)
-    add_library(x265-shared SHARED "${PROJECT_BINARY_DIR}/x265.def" ${ASM_OBJS}
-                ${X265_RC_FILE} $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common>)
+
+    if(ENABLE_DYNAMIC_HDR10)
+        add_library(x265-shared SHARED "${PROJECT_BINARY_DIR}/x265.def" ${ASM_OBJS}
+                    ${X265_RC_FILE} $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> $<TARGET_OBJECTS:dynamicHDR10>)
+    else()
+        add_library(x265-shared SHARED "${PROJECT_BINARY_DIR}/x265.def" ${ASM_OBJS}
+                   ${X265_RC_FILE} $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common>)
+    endif()
     if(EXTRA_LIB)
         target_link_libraries(x265-shared ${EXTRA_LIB})
     endif()
@@ -629,12 +644,17 @@
     if(WIN32)
         set(ExportDefs "${PROJECT_BINARY_DIR}/x265.def")
     endif(WIN32)
-
     if(XCODE)
         # Xcode seems unable to link the CLI with libs, so link as one targget
+        if(ENABLE_DYNAMIC_HDR10)
         add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT}
-                       x265.cpp x265.h x265cli.h x265-extras.h x265-extras.cpp
-                       $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> ${ASM_OBJS} ${ASM_SRCS})
+                        x265.cpp x265.h x265cli.h x265-extras.h x265-extras.cpp
+                        $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> $<TARGET_OBJECTS:dynamicHDR10> ${ASM_OBJS} ${ASM_SRCS})
+        else()
+            add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT}
+                        x265.cpp x265.h x265cli.h x265-extras.h x265-extras.cpp
+                        $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> ${ASM_OBJS} ${ASM_SRCS})
+        endif()
     else()
         add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT} ${X265_RC_FILE}
                        ${ExportDefs} x265.cpp x265.h x265cli.h x265-extras.h x265-extras.cpp)
diff -r f0545a714a70 -r e2eb86dce7f4 source/common/param.cpp
--- a/source/common/param.cpp	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/common/param.cpp	Wed Apr 19 16:36:59 2017 -0700
@@ -272,6 +272,7 @@
     param->bAQMotion = 0;
     param->bHDROpt = 0;
     param->analysisRefineLevel = 5;
+    param->toneMapFile = NULL;
 }
 int x265_param_default_preset(x265_param* param, const char* preset, const char* tune)
 {
@@ -948,6 +949,7 @@
         OPT("hdr") p->bEmitHDRSEI = atobool(value);
         OPT("hdr-opt") p->bHDROpt = atobool(value);
         OPT("limit-sao") p->bLimitSAO = atobool(value);
+        OPT("dhdr10-info") p->toneMapFile = strdup(value);
         else
             return X265_PARAM_BAD_NAME;
     }
@@ -1467,6 +1469,9 @@
     TOOLOPT(!param->bSaoNonDeblocked && param->bEnableSAO, "sao");
     TOOLOPT(param->rc.bStatWrite, "stats-write");
     TOOLOPT(param->rc.bStatRead,  "stats-read");
+#if ENABLE_DYNAMIC_HDR10
+    TOOLVAL(param->toneMapFile != NULL, "dhdr10-info");
+#endif
     x265_log(param, X265_LOG_INFO, "tools:%s\n", buf);
     fflush(stderr);
 }
diff -r f0545a714a70 -r e2eb86dce7f4 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/encoder/encoder.cpp	Wed Apr 19 16:36:59 2017 -0700
@@ -84,10 +84,11 @@
     m_cR = 1.0;
     for (int i = 0; i < X265_MAX_FRAME_THREADS; i++)
         m_frameEncoder[i] = NULL;
-
     MotionEstimate::initScales();
+#if ENABLE_DYNAMIC_HDR10
+    api = hdr10plus_api_get();
+#endif
 }
-
 inline char *strcatFilename(const char *input, const char *suffix)
 {
     char *output = X265_MALLOC(char, strlen(input) + strlen(suffix) + 1);
@@ -502,7 +503,7 @@
         free((char*)m_param->scalingLists);
         free((char*)m_param->numaPools);
         free((char*)m_param->masteringDisplayColorVolume);
-
+        free((char*)m_param->toneMapFile);
         PARAM_NS::x265_param_free(m_param);
     }
 }
@@ -593,9 +594,24 @@
         m_exportedPic = NULL;
         m_dpb->recycleUnreferenced();
     }
-
     if (pic_in)
     {
+        x265_sei_payload toneMap;
+        toneMap.payload = NULL;
+#if ENABLE_DYNAMIC_HDR10
+        if (m_bToneMap)
+        {
+            uint8_t *cim = NULL;
+            if (api->hdr10plus_json_to_frame_cim(m_param->toneMapFile, pic_in->poc, cim))
+            {
+                toneMap.payload = (uint8_t*)x265_malloc(sizeof(uint8_t) * cim[0]);
+                toneMap.payloadSize = cim[0];
+                toneMap.payloadType = USER_DATA_REGISTERED_ITU_T_T35;
+                memcpy(toneMap.payload, cim, toneMap.payloadSize);
+            }
+        }
+#endif
+
         if (pic_in->bitDepth < 8 || pic_in->bitDepth > 16)
         {
             x265_log(m_param, X265_LOG_ERROR, "Input bit depth (%d) must be between 8 and 16\n",
@@ -677,17 +693,29 @@
         inFrame->m_forceqp   = pic_in->forceqp;
         inFrame->m_param     = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param;
 
-        if (pic_in->userSEI.numPayloads)
+        int toneMapEnable = 0;
+        if (m_bToneMap && toneMap.payload)
+            toneMapEnable = 1;
+        int numPayloads = pic_in->userSEI.numPayloads + toneMapEnable;
+        inFrame->m_userSEI.numPayloads = numPayloads;
+
+        if (inFrame->m_userSEI.numPayloads)
         {
-            int numPayloads = inFrame->m_userSEI.numPayloads = pic_in->userSEI.numPayloads;
             inFrame->m_userSEI.payloads = new x265_sei_payload[numPayloads];
             for (int i = 0; i < numPayloads; i++)
             {
-                int size = inFrame->m_userSEI.payloads[i].payloadSize = pic_in->userSEI.payloads[i].payloadSize;
-                inFrame->m_userSEI.payloads[i].payloadType = pic_in->userSEI.payloads[i].payloadType;
+                x265_sei_payload input;
+                if (i == (numPayloads - 1))
+                    input = toneMap;
+                else
+                    input = pic_in->userSEI.payloads[i];
+                int size = inFrame->m_userSEI.payloads[i].payloadSize = input.payloadSize;
+                inFrame->m_userSEI.payloads[i].payloadType = input.payloadType;
                 inFrame->m_userSEI.payloads[i].payload = new uint8_t[size];
-                memcpy(inFrame->m_userSEI.payloads[i].payload, pic_in->userSEI.payloads[i].payload, size);
+                memcpy(inFrame->m_userSEI.payloads[i].payload, input.payload, size);
             }
+            if (toneMap.payload)
+                x265_free(toneMap.payload);
         }
 
         if (pic_in->quantOffsets != NULL)
@@ -2198,6 +2226,28 @@
         p->dynamicRd = 0;
         x265_log(p, X265_LOG_WARNING, "Dynamic-rd disabled, requires RD <= 4, VBV and aq-mode enabled\n");
     }
+#ifdef ENABLE_DYNAMIC_HDR10
+    if (m_param->toneMapFile)
+    {
+        if (!x265_fopen(p->toneMapFile, "r"))
+        {
+            x265_log(p, X265_LOG_WARNING, "Unable to open tone-map file. Disabling --dhdr10-info\n");
+            m_bToneMap = 0;
+            m_param->toneMapFile = NULL;
+        }
+        else
+            m_bToneMap = 1;
+    }
+    else
+        m_bToneMap = 0;
+#else
+    if (m_param->toneMapFile)
+    {
+        x265_log(p, X265_LOG_WARNING, "--dhdr10-info disabled. Enable dynamic HDR in cmake.\n");
+        m_bToneMap = 0;
+        m_param->toneMapFile = NULL;
+    }
+#endif
 
     if (p->uhdBluray)
     {
diff -r f0545a714a70 -r e2eb86dce7f4 source/encoder/encoder.h
--- a/source/encoder/encoder.h	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/encoder/encoder.h	Wed Apr 19 16:36:59 2017 -0700
@@ -31,9 +31,9 @@
 #include "x265.h"
 #include "nal.h"
 #include "framedata.h"
+#include "dynamicHDR10\hdr10plus.h"
 
 struct x265_encoder {};
-
 namespace X265_NS {
 // private namespace
 extern const char g_sliceTypeToChar[3];
@@ -172,10 +172,10 @@
     /* For HDR*/
     double                m_cB;
     double                m_cR;
-
+    int                m_bToneMap; // Enables tone-mapping
+    const hdr10plus_api*     api;
     Encoder();
     ~Encoder() {}
-
     void create();
     void stopJobs();
     void destroy();
diff -r f0545a714a70 -r e2eb86dce7f4 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/encoder/frameencoder.cpp	Wed Apr 19 16:36:59 2017 -0700
@@ -615,18 +615,31 @@
     for (int i = 0; i < m_frame->m_userSEI.numPayloads; i++)
     {
         x265_sei_payload *payload = &m_frame->m_userSEI.payloads[i];
-        SEIuserDataUnregistered sei;
+        if (payload->payloadType != USER_DATA_REGISTERED_ITU_T_T35)
+        {
+            SEIuserDataUnregistered sei;
+            sei.m_payloadType = payload->payloadType;
+            sei.m_userDataLength = payload->payloadSize;
+            sei.m_userData = payload->payload;
+            m_bs.resetBits();
+            sei.write(m_bs, *slice->m_sps);
+            m_bs.writeByteAlignment();
+            m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+        }
+#if ENABLE_DYNAMIC_HDR10
+        else if (m_param->toneMapFile != NULL)
+        {
+            SEICreativeIntentMeta sei;
 
-        sei.m_payloadType = payload->payloadType;
-        sei.m_userDataLength = payload->payloadSize;
-        sei.m_userData = payload->payload;
+            sei.cim = payload->payload;
 
-        m_bs.resetBits();
-        sei.write(m_bs, *slice->m_sps);
-        m_bs.writeByteAlignment();
-        m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+            m_bs.resetBits();
+            sei.write(m_bs, *slice->m_sps);
+            m_bs.writeByteAlignment();
+            m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+        }
+#endif
     }
-
     /* CQP and CRF (without capped VBV) doesn't use mid-frame statistics to 
      * tune RateControl parameters for other frames.
      * Hence, for these modes, update m_startEndOrder and unlock RC for previous threads waiting in
diff -r f0545a714a70 -r e2eb86dce7f4 source/encoder/sei.h
--- a/source/encoder/sei.h	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/encoder/sei.h	Wed Apr 19 16:36:59 2017 -0700
@@ -313,6 +313,43 @@
         writeByteAlign();
     }
 };
+
+//seongnam.oh at samsung.com :: for the Creative Intent Meta Data Encoding
+class SEICreativeIntentMeta : public SEI
+{
+public:
+    uint8_t *cim;
+
+    SEIPayloadType payloadType() const { return USER_DATA_REGISTERED_ITU_T_T35; }
+
+    // daniel.vt at samsung.com :: for the Creative Intent Meta Data Encoding ( seongnam.oh at samsung.com )
+    void write(Bitstream& bs, const SPS&)
+    {
+        if (!cim)
+        {
+            return;
+        }
+
+        m_bitIf = &bs;
+        WRITE_CODE(USER_DATA_REGISTERED_ITU_T_T35, 8, "payload_type");
+        int i = 0;
+        int payloadSize = cim[0];
+        while (cim[i] == 0xFF)
+        {
+            i++;
+            payloadSize += cim[i];
+            WRITE_CODE(0xFF, 8, "payload_size");
+        }
+        WRITE_CODE((uint8_t)payloadSize, 8, "payload_size");
+        i++;
+        payloadSize += i;
+        for (; i < payloadSize; ++i)
+        {
+            WRITE_CODE(cim[i], 8, "creative_intent_metadata");
+        }
+
+    }
+};
+
 }
-
 #endif // ifndef X265_SEI_H
diff -r f0545a714a70 -r e2eb86dce7f4 source/x265.h
--- a/source/x265.h	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/x265.h	Wed Apr 19 16:36:59 2017 -0700
@@ -1379,11 +1379,15 @@
     * information stored/reused in save/load analysis-mode. Higher the refine
     * level higher the informtion stored/reused. Default is 5 */
     int       analysisRefineLevel;
+
      /* Limit Sample Adaptive Offset filter computation by early terminating SAO
      * process based on inter prediction mode, CTU spatial-domain correlations,
      * and relations between luma and chroma */
     int       bLimitSAO;
 
+    /* File containing the tone mapping information */
+    const char*     toneMapFile;
+
 } x265_param;
 /* x265_param_alloc:
  *  Allocates an x265_param instance. The returned param structure is not
diff -r f0545a714a70 -r e2eb86dce7f4 source/x265cli.h
--- a/source/x265cli.h	Wed Mar 22 14:33:20 2017 +0530
+++ b/source/x265cli.h	Wed Apr 19 16:36:59 2017 -0700
@@ -268,6 +268,7 @@
     { "no-hdr-opt",           no_argument, NULL, 0 },
     { "limit-sao",            no_argument, NULL, 0 },
     { "no-limit-sao",         no_argument, NULL, 0 },
+    { "dhdr10-info",    required_argument, NULL, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
@@ -313,6 +314,9 @@
     H1("                                 1 - i420 (4:2:0 default)\n");
     H1("                                 2 - i422 (4:2:2)\n");
     H1("                                 3 - i444 (4:4:4)\n");
+#if ENABLE_DYNAMIC_HDR10
+    H0("   --dhdr10-info <filename>      JSON file containing the Creative Intent Metadata to be encoded as Dynamic Tone Mapping \n");
+#endif
     H0("-f/--frames <integer>            Maximum number of frames to encode. Default all\n");
     H0("   --seek <integer>              First frame to encode\n");
     H1("   --[no-]interlace <bff|tff>    Indicate input pictures are interlace fields in temporal order. Default progressive\n");


More information about the x265-devel mailing list