[x265] [PATCH] Add support for Dolby Vision RPU muxing
Kalyan Goswami
kalyan at multicorewareinc.com
Wed Dec 12 12:18:31 CET 2018
pushed
Thanks,
Kalyan Goswami, PhD
Video Architect @ MulticoreWare
http: <http://www.multicorewareinc.com/>//www.multicorewareinc.com
<http://www.multicorewareinc.com/>
+91 9884989331
On Mon, Dec 10, 2018 at 3:29 PM Aruna Matheswaran <
aruna at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Aruna Matheswaran <aruna at multicorewareinc.com>
> # Date 1538037975 -19800
> # Thu Sep 27 14:16:15 2018 +0530
> # Node ID e50f803e26fb3926dc695e0aeea39681fe1eacbd
> # Parent b748ee9f44657a9468b9d62c85d02dfafcbc4039
> Add support for Dolby Vision RPU muxing
>
> diff -r b748ee9f4465 -r e50f803e26fb doc/reST/cli.rst
> --- a/doc/reST/cli.rst Fri Sep 28 10:45:23 2018 +0530
> +++ b/doc/reST/cli.rst Thu Sep 27 14:16:15 2018 +0530
> @@ -2208,6 +2208,15 @@
>
> Currently only profile 5 enabled, Default 0 (disabled)
>
> +.. option:: --dolby-vision-rpu
> +
> + File containing Dolby Vision RPU metadata. If given, x265's Dolby
> Vision
> + metadata parser will fill the RPU field of input pictures with the
> metadata
> + read from the file. The library will interleave access units with
> RPUs in the
> + bitstream. Default NULL (disabled).
> +
> + **CLI ONLY**
> +
> .. option:: --info, --no-info
>
> Emit an informational SEI with the stream headers which describes
> diff -r b748ee9f4465 -r e50f803e26fb source/CMakeLists.txt
> --- a/source/CMakeLists.txt Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/CMakeLists.txt Thu Sep 27 14:16:15 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 166)
> +set(X265_BUILD 167)
> configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
> "${PROJECT_BINARY_DIR}/x265.def")
> configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
> diff -r b748ee9f4465 -r e50f803e26fb source/common/frame.cpp
> --- a/source/common/frame.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/common/frame.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -44,6 +44,8 @@
> m_param = NULL;
> m_userSEI.numPayloads = 0;
> m_userSEI.payloads = NULL;
> + m_rpu.payloadSize = 0;
> + m_rpu.payload = NULL;
> memset(&m_lowres, 0, sizeof(m_lowres));
> m_rcData = NULL;
> m_encodeStartTime = 0;
> diff -r b748ee9f4465 -r e50f803e26fb source/common/frame.h
> --- a/source/common/frame.h Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/common/frame.h Thu Sep 27 14:16:15 2018 +0530
> @@ -98,6 +98,7 @@
>
> float* m_quantOffsets; // points to
> quantOffsets in x265_picture
> x265_sei m_userSEI;
> + x265_dolby_vision_rpu m_rpu;
>
> /* Frame Parallelism - notification between FrameEncoders of
> available motion reference rows */
> ThreadSafeInteger* m_reconRowFlag; // flag of CTU rows
> completely reconstructed and extended for motion reference
> diff -r b748ee9f4465 -r e50f803e26fb source/encoder/api.cpp
> --- a/source/encoder/api.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/encoder/api.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -598,6 +598,8 @@
> pic->quantOffsets = NULL;
> pic->userSEI.payloads = NULL;
> pic->userSEI.numPayloads = 0;
> + pic->rpu.payloadSize = 0;
> + pic->rpu.payload = NULL;
>
> if ((param->analysisSave || param->analysisLoad) || (param->bMVType
> == AVC_INFO))
> {
> @@ -612,6 +614,8 @@
>
> void x265_picture_free(x265_picture *p)
> {
> + if (p->rpu.payload)
> + X265_FREE(p->rpu.payload);
> return x265_free(p);
> }
>
> diff -r b748ee9f4465 -r e50f803e26fb source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/encoder/encoder.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -1075,6 +1075,14 @@
>
> copyUserSEIMessages(inFrame, pic_in);
>
> + /*Copy Dolby Vision RPU from pic_in to frame*/
> + if (pic_in->rpu.payloadSize)
> + {
> + inFrame->m_rpu.payloadSize = pic_in->rpu.payloadSize;
> + inFrame->m_rpu.payload = new uint8_t[pic_in->rpu.payloadSize];
> + memcpy(inFrame->m_rpu.payload, pic_in->rpu.payload,
> pic_in->rpu.payloadSize);
> + }
> +
> if (pic_in->quantOffsets != NULL)
> {
> int cuCount;
> @@ -2362,6 +2370,13 @@
> {
> sbacCoder.setBitstream(&bs);
>
> + if (m_param->dolbyProfile && !m_param->bRepeatHeaders)
> + {
> + bs.resetBits();
> + bs.write(0x10, 8);
> + list.serialize(NAL_UNIT_ACCESS_UNIT_DELIMITER, bs);
> + }
> +
> /* headers for start of bitstream */
> bs.resetBits();
> sbacCoder.codeVPS(m_vps);
> diff -r b748ee9f4465 -r e50f803e26fb source/encoder/frameencoder.cpp
> --- a/source/encoder/frameencoder.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/encoder/frameencoder.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -1063,6 +1063,14 @@
> m_accessUnitBits = bytes << 3;
> }
>
> + if (m_frame->m_rpu.payloadSize)
> + {
> + m_bs.resetBits();
> + for (int i = 0; i < m_frame->m_rpu.payloadSize; i++)
> + m_bs.write(m_frame->m_rpu.payload[i], 8);
> + m_nalList.serialize(NAL_UNIT_UNSPECIFIED, m_bs);
> + }
> +
> m_endCompressTime = x265_mdate();
>
> /* Decrement referenced frame reference counts, allow them to be
> recycled */
> diff -r b748ee9f4465 -r e50f803e26fb source/encoder/nal.cpp
> --- a/source/encoder/nal.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/encoder/nal.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -97,7 +97,7 @@
> /* Will write size later */
> bytes += 4;
> }
> - else if (!m_numNal || nalUnitType == NAL_UNIT_VPS || nalUnitType ==
> NAL_UNIT_SPS || nalUnitType == NAL_UNIT_PPS)
> + else if (!m_numNal || nalUnitType == NAL_UNIT_VPS || nalUnitType ==
> NAL_UNIT_SPS || nalUnitType == NAL_UNIT_PPS || nalUnitType ==
> NAL_UNIT_UNSPECIFIED)
> {
> memcpy(out, startCodePrefix, 4);
> bytes += 4;
> @@ -124,7 +124,7 @@
> * - 0x000002 */
> for (uint32_t i = 0; i < payloadSize; i++)
> {
> - if (i > 2 && !out[bytes - 2] && !out[bytes - 3] && out[bytes - 1]
> <= 0x03)
> + if (i > 2 && !out[bytes - 2] && !out[bytes - 3] && out[bytes - 1]
> <= 0x03 && nalUnitType != NAL_UNIT_UNSPECIFIED)
> {
> /* inject 0x03 to prevent emulating a start code */
> out[bytes] = out[bytes - 1];
> diff -r b748ee9f4465 -r e50f803e26fb source/encoder/sei.cpp
> --- a/source/encoder/sei.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/encoder/sei.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -66,7 +66,8 @@
>
> if (!isNested)
> {
> - bs.writeByteAlignment();
> + if (nalUnitType != NAL_UNIT_UNSPECIFIED)
> + bs.writeByteAlignment();
> list.serialize(nalUnitType, bs);
> }
> }
> diff -r b748ee9f4465 -r e50f803e26fb source/x265.cpp
> --- a/source/x265.cpp Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/x265.cpp Thu Sep 27 14:16:15 2018 +0530
> @@ -65,6 +65,8 @@
> {
> b_ctrl_c = 1;
> }
> +#define START_CODE 0x00000001
> +#define START_CODE_BYTES 4
>
> struct CLIOptions
> {
> @@ -72,6 +74,7 @@
> ReconFile* recon;
> OutputFile* output;
> FILE* qpfile;
> + FILE* dolbyVisionRpu; /* File containing Dolby Vision BL RPU
> metadata */
> const char* reconPlayCmd;
> const x265_api* api;
> x265_param* param;
> @@ -94,6 +97,7 @@
> recon = NULL;
> output = NULL;
> qpfile = NULL;
> + dolbyVisionRpu = NULL;
> reconPlayCmd = NULL;
> api = NULL;
> param = NULL;
> @@ -124,6 +128,9 @@
> if (qpfile)
> fclose(qpfile);
> qpfile = NULL;
> + if (dolbyVisionRpu)
> + fclose(dolbyVisionRpu);
> + dolbyVisionRpu = NULL;
> if (output)
> output->release();
> output = NULL;
> @@ -311,6 +318,15 @@
> if (!this->qpfile)
> x265_log_file(param, X265_LOG_ERROR, "%s qpfile not
> found or error in opening qp file\n", optarg);
> }
> + OPT("dolby-vision-rpu")
> + {
> + this->dolbyVisionRpu = x265_fopen(optarg, "rb");
> + if (!this->dolbyVisionRpu)
> + {
> + x265_log_file(param, X265_LOG_ERROR, "Dolby Vision
> RPU metadata file %s not found or error in opening file\n", optarg);
> + return true;
> + }
> + }
> OPT("fullhelp")
> {
> param->logLevel = X265_LOG_FULL;
> @@ -552,6 +568,59 @@
> }
> #endif
>
> +/* Parse the RPU file and extract the RPU corresponding to the current
> picture
> + * and fill the rpu field of the input picture */
> +static int rpuParser(x265_picture * pic, FILE * ptr)
> +{
> + uint8_t byte;
> + uint32_t code = 0;
> + int bytesRead = 0;
> + pic->rpu.payloadSize = 0;
> +
> + if (!pic->pts)
> + {
> + while (bytesRead++ < 4 && fread(&byte, sizeof(uint8_t), 1, ptr))
> + code = (code << 8) | byte;
> +
> + if (code != START_CODE)
> + {
> + x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU
> startcode in POC %d\n", pic->pts);
> + return 1;
> + }
> + }
> +
> + bytesRead = 0;
> + while (fread(&byte, sizeof(uint8_t), 1, ptr))
> + {
> + code = (code << 8) | byte;
> + if (bytesRead++ < 3)
> + continue;
> + if (bytesRead >= 1024)
> + {
> + x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU size
> in POC %d\n", pic->pts);
> + return 1;
> + }
> +
> + if (code != START_CODE)
> + pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8))
> & 0xFF;
> + else
> + return 0;
> + }
> +
> + int ShiftBytes = START_CODE_BYTES - (bytesRead -
> pic->rpu.payloadSize);
> + int bytesLeft = bytesRead - pic->rpu.payloadSize;
> + code = (code << ShiftBytes * 8);
> + for (int i = 0; i < bytesLeft; i++)
> + {
> + pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) &
> 0xFF;
> + code = (code << 8);
> + }
> + if (!pic->rpu.payloadSize)
> + x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU not found for
> POC %d\n", pic->pts);
> + return 0;
> +}
> +
> +
> /* CLI return codes:
> *
> * 0 - encode successful
> @@ -630,8 +699,10 @@
> x265_stats stats;
> uint32_t nal;
> int16_t *errorBuf = NULL;
> + bool bDolbyVisionRPU = false;
> int ret = 0;
>
> +
> if (!param->bRepeatHeaders)
> {
> if (api->encoder_headers(encoder, &p_nal, &nal) < 0)
> @@ -646,6 +717,13 @@
>
> api->picture_init(param, pic_in);
>
> + if (param->dolbyProfile && cliopt.dolbyVisionRpu)
> + {
> + pic_in->rpu.payload = X265_MALLOC(uint8_t, 1024);
> + if (pic_in->rpu.payload)
> + bDolbyVisionRPU = true;
> + }
> +
> if (cliopt.bDither)
> {
> errorBuf = X265_MALLOC(int16_t, param->sourceWidth + 1);
> @@ -685,8 +763,13 @@
> }
> /* Overwrite PTS */
> pic_in->pts = pic_in->poc;
> +
> + if (bDolbyVisionRPU)
> + {
> + if (rpuParser(pic_in, cliopt.dolbyVisionRpu) > 0)
> + goto fail;
> + }
> }
> -
> int numEncoded = api->encoder_encode(encoder, &p_nal, &nal,
> pic_in, pic_recon);
> if (numEncoded < 0)
> {
> @@ -749,6 +832,13 @@
> break;
> }
>
> + if (bDolbyVisionRPU)
> + {
> + if(fgetc(cliopt.dolbyVisionRpu) != EOF)
> + x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU count is
> greater than frame count\n");
> + x265_log(NULL, X265_LOG_INFO, "VES muxing with Dolby Vision RPU
> file successful\n");
> + }
> +
> /* clear progress report */
> if (cliopt.bProgress)
> fprintf(stderr, "%*s\r", 80, " ");
> diff -r b748ee9f4465 -r e50f803e26fb source/x265.h
> --- a/source/x265.h Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/x265.h Thu Sep 27 14:16:15 2018 +0530
> @@ -81,6 +81,7 @@
> NAL_UNIT_FILLER_DATA,
> NAL_UNIT_PREFIX_SEI,
> NAL_UNIT_SUFFIX_SEI,
> + NAL_UNIT_UNSPECIFIED = 62,
> NAL_UNIT_INVALID = 64,
> } NalUnitType;
>
> @@ -360,6 +361,12 @@
> x265_sei_payload *payloads;
> } x265_sei;
>
> +typedef struct x265_dolby_vision_rpu
> +{
> + int payloadSize;
> + uint8_t* payload;
> +}x265_dolby_vision_rpu;
> +
> /* Used to pass pictures into the encoder, and to get picture data back
> out of
> * the encoder. The input and output semantics are different */
> typedef struct x265_picture
> @@ -445,6 +452,9 @@
>
> // pts is reordered in the order of encoding.
> int64_t reorderedPts;
> +
> + //Dolby Vision RPU metadata
> + x265_dolby_vision_rpu rpu;
> } x265_picture;
>
> typedef enum
> diff -r b748ee9f4465 -r e50f803e26fb source/x265cli.h
> --- a/source/x265cli.h Fri Sep 28 10:45:23 2018 +0530
> +++ b/source/x265cli.h Thu Sep 27 14:16:15 2018 +0530
> @@ -306,6 +306,7 @@
> { "atc-sei", required_argument, NULL, 0 },
> { "pic-struct", required_argument, NULL, 0 },
> { "nalu-file", required_argument, NULL, 0 },
> + { "dolby-vision-rpu", required_argument, NULL, 0 },
> { 0, 0, 0, 0 },
> { 0, 0, 0, 0 },
> { 0, 0, 0, 0 },
> @@ -357,6 +358,8 @@
> H0(" --[no-]dhdr10-opt Insert tone mapping SEI only for
> IDR frames and when the tone mapping information changes. Default
> disabled\n");
> #endif
> H0(" --dolby-vision-profile <float|integer> Specifies Dolby Vision
> profile ID. Currently only profile 5 enabled. Specified as '5' or '50'.
> Default 0 (disabled).\n");
> + H0(" --dolby-vision-rpu <filename> File containing Dolby Vision RPU
> metadata.\n"
> + " If given, x265's Dolby Vision
> metadata parser will fill the RPU field of input pictures with the metadata
> read from the file. Default NULL(disabled).\n");
> H0(" --nalu-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");
>
> _______________________________________________
> 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/20181212/ca856206/attachment-0001.html>
More information about the x265-devel
mailing list