[x265] [PATCH] CEA 608/708 Support
Alex Giladi
alex.giladi at gmail.com
Wed Jun 20 17:15:42 CEST 2018
I would rename the "usersei-file" option into something like "nalu-file",
as the input file format allows arbitrary NAL units rather than only SEIs
(despite only prefix SEIs being implemented).
On Wed, Jun 20, 2018 at 4:43 AM, <indumathi at multicorewareinc.com> wrote:
> # HG changeset patch
> # User indumathi at multicorewareinc.com
> # Date 1528726491 -19800
> # Mon Jun 11 19:44:51 2018 +0530
> # Node ID e1dd8424a3bd5f9f61f4a73aec6f2aee27591772
> # Parent a8a5ccf5aaf7e04e439a216e5c396991c6b76999
> CEA 608/708 Support
>
> Parse the SEI messages from text file and insert it into the userSEI with
> cli option.
>
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd doc/reST/cli.rst
> --- a/doc/reST/cli.rst Wed Jun 13 09:54:27 2018 +0530
> +++ b/doc/reST/cli.rst Mon Jun 11 19:44:51 2018 +0530
> @@ -2135,6 +2135,12 @@
>
> Maximum luma value allowed for input pictures. Any values above
> max-luma
> are clipped. No default.
> +
> +.. option:: --usersei-file <filename>
> +
> + Text file containing userSEI in POC order :
> <POC><space><PREFIX><space><NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload>
> + Parse the input file specified and inserts SEI messages into the
> bitstream.
> + Currently, we support only PREFIX SEI messages. This is an
> "application-only" feature.
>
> .. option:: --atc-sei <integer>
>
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/CMakeLists.txt
> --- a/source/CMakeLists.txt Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/CMakeLists.txt Mon Jun 11 19:44:51 2018 +0530
> @@ -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 161)
> +set(X265_BUILD 162)
> configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
> "${PROJECT_BINARY_DIR}/x265.def")
> configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/common/param.cpp
> --- a/source/common/param.cpp Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/common/param.cpp Mon Jun 11 19:44:51 2018 +0530
> @@ -302,6 +302,7 @@
> param->bDisableLookahead = 0;
> param->bCopyPicToFrame = 1;
> param->maxAUSizeFactor = 1;
> + param->userSeiFile = NULL;
>
> /* DCT Approximations */
> param->bLowPassDct = 0;
> @@ -1048,6 +1049,7 @@
> OPT("pic-struct") p->pictureStructure = atoi(value);
> OPT("chunk-start") p->chunkStart = atoi(value);
> OPT("chunk-end") p->chunkEnd = atoi(value);
> + OPT("usersei-file") p->userSeiFile = strdup(value);
> else
> return X265_PARAM_BAD_NAME;
> }
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/encoder/encoder.cpp Mon Jun 11 19:44:51 2018 +0530
> @@ -79,6 +79,7 @@
> m_threadPool = NULL;
> m_analysisFileIn = NULL;
> m_analysisFileOut = NULL;
> + m_seiFile = NULL;
> m_offsetEmergency = NULL;
> m_iFrameNum = 0;
> m_iPPSQpMinus26 = 0;
> @@ -412,6 +413,20 @@
>
> m_emitCLLSEI = p->maxCLL || p->maxFALL;
>
> + if (m_param->userSeiFile)
> + {
> + m_seiFile = x265_fopen(m_param->userSeiFile, "r");
> + if (!m_seiFile)
> + {
> + x265_log_file(NULL, X265_LOG_ERROR, "%s file not found or
> Failed to open\n", m_param->userSeiFile);
> + m_aborted = true;
> + }
> + else
> + m_enableUserSei = 1;
> + }
> + else
> + m_enableUserSei = 0;
> +
> #if ENABLE_HDR10_PLUS
> if (m_bToneMap)
> m_numCimInfo = m_hdr10plus_api->hdr10plus_
> json_to_movie_cim(m_param->toneMapFile, m_cim);
> @@ -782,6 +797,8 @@
> }
> X265_FREE(temp);
> }
> + if (m_seiFile)
> + fclose(m_seiFile);
> if (m_param)
> {
> if (m_param->csvfpt)
> @@ -922,7 +939,14 @@
> }
> }
> #endif
> -
> +/* seiMsg will contain SEI messages specified in a fixed file format in
> POC order.
> +* Format of the file : <POC><space><PREFIX><space><NAL UNIT TYPE>/<SEI
> TYPE><space><SEI Payload> */
> + x265_sei_payload seiMsg;
> + seiMsg.payload = NULL;
> + if (m_enableUserSei)
> + {
> + seiMsg = readUserSeiFile(m_pocLast);
> + }
> 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",
> @@ -1008,6 +1032,8 @@
> if (m_bToneMap && toneMap.payload)
> toneMapEnable = 1;
> int numPayloads = pic_in->userSEI.numPayloads + toneMapEnable;
> + if (m_enableUserSei && seiMsg.payload)
> + numPayloads += m_enableUserSei;
> inFrame->m_userSEI.numPayloads = numPayloads;
>
> if (inFrame->m_userSEI.numPayloads)
> @@ -1023,6 +1049,8 @@
> x265_sei_payload input;
> if ((i == (numPayloads - 1)) && toneMapEnable)
> input = toneMap;
> + else if (m_enableUserSei)
> + input = seiMsg;
> else
> input = pic_in->userSEI.payloads[i];
> int size = inFrame->m_userSEI.payloads[i].payloadSize =
> input.payloadSize;
> @@ -1033,6 +1061,8 @@
> }
> if (toneMap.payload)
> x265_free(toneMap.payload);
> + if (seiMsg.payload)
> + x265_free(seiMsg.payload);
> }
>
> if (pic_in->quantOffsets != NULL)
> @@ -4706,6 +4736,55 @@
> TOOLCMP(oldParam->rc.rfConstant, newParam->rc.rfConstant, "crf=%f to
> %f\n");
> }
>
> +x265_sei_payload Encoder::readUserSeiFile(int curPoc)
> +{
> + x265_sei_payload seiMsg;
> + seiMsg.payload = NULL;
> + char line[1024];
> + while (!feof(m_seiFile))
> + {
> + fgets(line, sizeof(line), m_seiFile);
> + int poc = atoi(strtok(line, " "));
> + char *prefix = strtok(NULL, " ");
> + int nalType = atoi(strtok(NULL, "/"));
> + int payloadType = atoi(strtok(NULL, " "));
> + char *base64Encode = strtok(NULL, "\n");
> + int base64EncodeLength = (int)strlen(base64Encode);
> + char *base64Decode = SEI::base64Decode(base64Encode,
> base64EncodeLength);
> + if (nalType == NAL_UNIT_PREFIX_SEI && (!strcmp(prefix, "PREFIX")))
> + {
> + int currentPOC = curPoc + 1;
> + if (currentPOC == poc)
> + {
> + seiMsg.payloadSize = (base64EncodeLength / 4) * 3;
> + seiMsg.payload = (uint8_t*)x265_malloc(sizeof(uint8_t) *
> seiMsg.payloadSize);
> + if (!seiMsg.payload)
> + {
> + x265_log(m_param, X265_LOG_ERROR, "Unable to allocate
> memory for SEI payload\n");
> + break;
> + }
> + if (payloadType == 4)
> + seiMsg.payloadType = USER_DATA_REGISTERED_ITU_T_T35;
> + else if (payloadType == 5)
> + seiMsg.payloadType = USER_DATA_UNREGISTERED;
> + else
> + {
> + x265_log(m_param, X265_LOG_WARNING, "Unsupported SEI
> payload Type for frame %d\n", poc);
> + break;
> + }
> + memcpy(seiMsg.payload, base64Decode, seiMsg.payloadSize);
> + return seiMsg;
> + }
> + }
> + else
> + {
> + x265_log(m_param, X265_LOG_WARNING, "SEI message for frame %d
> is not inserted. Will support only PREFIX SEI messages.\n", poc);
> + break;
> + }
> + }
> + return seiMsg;
> +}
> +
> bool Encoder::computeSPSRPSIndex()
> {
> RPS* rpsInSPS = m_sps.spsrps;
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/encoder.h
> --- a/source/encoder/encoder.h Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/encoder/encoder.h Mon Jun 11 19:44:51 2018 +0530
> @@ -169,6 +169,7 @@
> Frame* m_exportedPic;
> FILE* m_analysisFileIn;
> FILE* m_analysisFileOut;
> + FILE* m_seiFile;
> x265_param* m_param;
> x265_param* m_latestParam; // Holds latest param during a
> reconfigure
> RateControl* m_rateControl;
> @@ -212,6 +213,7 @@
> double m_cR;
>
> int m_bToneMap; // Enables tone-mapping
> + int m_enableUserSei;
>
> #ifdef ENABLE_HDR10_PLUS
> const hdr10plus_api *m_hdr10plus_api;
> @@ -299,6 +301,8 @@
>
> int validateAnalysisData(x265_analysis_data* analysis, int
> readWriteFlag);
>
> + x265_sei_payload readUserSeiFile(int poc);
> +
> void calcRefreshInterval(Frame* frameEnc);
>
> void initRefIdx();
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/sei.cpp
> --- a/source/encoder/sei.cpp Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/encoder/sei.cpp Mon Jun 11 19:44:51 2018 +0530
> @@ -90,3 +90,63 @@
> {
> m_payloadSize = size;
> }
> +
> +/* charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcd
> efghijklmnopqrstuvwxyz0123456789+/" */
> +
> +char* SEI::base64Decode(char encodedString[], int base64EncodeLength)
> +{
> + char* decodedString;
> + decodedString = (char*)malloc(sizeof(char) * ((base64EncodeLength /
> 4) * 3));
> + int i, j, k = 0;
> + // stores the bitstream
> + int bitstream = 0;
> + // countBits stores current number of bits in bitstream
> + int countBits = 0;
> + // selects 4 characters from encodedString at a time. Find the
> position of each encoded character in charSet and stores in bitstream
> + for (i = 0; i < base64EncodeLength; i += 4)
> + {
> + bitstream = 0, countBits = 0;
> + for (j = 0; j < 4; j++)
> + {
> + // make space for 6 bits
> + if (encodedString[i + j] != '=')
> + {
> + bitstream = bitstream << 6;
> + countBits += 6;
> + }
> + // Finding the position of each encoded character in charSet
> and storing in bitstream, use OR '|' operator to store bits
> +
> + if (encodedString[i + j] >= 'A' && encodedString[i + j] <=
> 'Z')
> + bitstream = bitstream | (encodedString[i + j] - 'A');
> +
> + else if (encodedString[i + j] >= 'a' && encodedString[i + j]
> <= 'z')
> + bitstream = bitstream | (encodedString[i + j] - 'a' + 26);
> +
> + else if (encodedString[i + j] >= '0' && encodedString[i + j]
> <= '9')
> + bitstream = bitstream | (encodedString[i + j] - '0' + 52);
> +
> + // '+' occurs in 62nd position in charSet
> + else if (encodedString[i + j] == '+')
> + bitstream = bitstream | 62;
> +
> + // '/' occurs in 63rd position in charSet
> + else if (encodedString[i + j] == '/')
> + bitstream = bitstream | 63;
> +
> + // to delete appended bits during encoding
> + else
> + {
> + bitstream = bitstream >> 2;
> + countBits -= 2;
> + }
> + }
> +
> + while (countBits != 0)
> + {
> + countBits -= 8;
> + decodedString[k++] = (bitstream >> countBits) & 255;
> + }
> + }
> + return decodedString;
> +}
> +
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/sei.h
> --- a/source/encoder/sei.h Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/encoder/sei.h Mon Jun 11 19:44:51 2018 +0530
> @@ -41,6 +41,7 @@
> void alignAndSerialize(Bitstream& bs, int lastSei, int isSingleSei,
> NalUnitType nalUnitType, NALList& list);
> int countPayloadSize(const SPS& sps);
> void setSize(uint32_t size);
> + static char* base64Decode(char encodedString[], int
> base64EncodeLength);
> virtual ~SEI() {}
> protected:
> SEIPayloadType m_payloadType;
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/x265.h
> --- a/source/x265.h Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/x265.h Mon Jun 11 19:44:51 2018 +0530
> @@ -1641,6 +1641,8 @@
> * used in taking lookahead decisions, but, they will not be
> encoded.
> * Default 0 (disabled). */
> int chunkEnd;
> + /* File containing base64 encoded SEI messages in POC order */
> + const char* userSeiFile;
>
> } x265_param;
>
> diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/x265cli.h
> --- a/source/x265cli.h Wed Jun 13 09:54:27 2018 +0530
> +++ b/source/x265cli.h Mon Jun 11 19:44:51 2018 +0530
> @@ -304,6 +304,7 @@
> { "no-single-sei", no_argument, NULL, 0 },
> { "atc-sei", required_argument, NULL, 0 },
> { "pic-struct", required_argument, NULL, 0 },
> + { "usersei-file", required_argument, NULL, 0 },
> { 0, 0, 0, 0 },
> { 0, 0, 0, 0 },
> { 0, 0, 0, 0 },
> @@ -354,6 +355,7 @@
> H0(" --dhdr10-info <filename> JSON file containing the
> Creative Intent Metadata to be encoded as Dynamic Tone Mapping\n");
> H0(" --[no-]dhdr10-opt Insert tone mapping SEI only for
> IDR frames and when the tone mapping information changes. Default
> disabled\n");
> #endif
> + H0(" --usersei-file <filename> Text file containing SEI
> messages in the following format : <POC><space><PREFIX><space><NAL UNIT
> TYPE>/<SEI TYPE><space><SEI Payload>\n");
> 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");
>
> _______________________________________________
> 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/20180620/c89c4b36/attachment-0001.html>
More information about the x265-devel
mailing list