[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