[x265] [PATCH] Add support for Dolby Vision RPU muxing
Aruna Matheswaran
aruna at multicorewareinc.com
Mon Dec 10 10:59:35 CET 2018
# 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");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20181210/8ffec319/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265_clone_12437.patch
Type: application/octet-stream
Size: 13545 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20181210/8ffec319/attachment-0001.obj>
More information about the x265-devel
mailing list