[x265] [PATCH] Add API to read CTU Information

Pradeep Ramachandran pradeep at multicorewareinc.com
Wed May 10 08:56:11 CEST 2017


On Tue, May 9, 2017 at 5:57 PM, <vignesh at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Santhoshini Sekar
> # Date 1493009037 -19800
> #      Mon Apr 24 10:13:57 2017 +0530
> # Node ID 6a9eb27b2b0d1a716911bf19136ceb653a51270b
> # Parent  7ecd263f6d43966df308d53029a67cfda03bb185
> Add API to read CTU Information
>

Pushed this and related patches to default branch.


>
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d doc/reST/api.rst
> --- a/doc/reST/api.rst  Tue May 09 12:43:04 2017 +0530
> +++ b/doc/reST/api.rst  Mon Apr 24 10:13:57 2017 +0530
> @@ -192,6 +192,12 @@
>          *      presets is not recommended without a more fine-grained
> breakdown of
>          *      parameters to take this into account. */
>         int x265_encoder_reconfig(x265_encoder *, x265_param *);
> +**x265_encoder_ctu_info**
> +       /* x265_encoder_ctu_info:
> +        *    Copy CTU information such as ctu address and ctu partition
> structure of all
> +        *    CTUs in each frame. The function is invoked only if
> "--ctu-info" is enabled and
> +        *    the encoder will wait for this copy to complete if enabled.
> +        */
>
>  Pictures
>  ========
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d doc/reST/cli.rst
> --- a/doc/reST/cli.rst  Tue May 09 12:43:04 2017 +0530
> +++ b/doc/reST/cli.rst  Mon Apr 24 10:13:57 2017 +0530
> @@ -1221,7 +1221,16 @@
>         intra cost of a frame used in scenecut detection. For example, a
> value of 5 indicates,
>         if the inter cost of a frame is greater than or equal to 95
> percent of the intra cost of the frame,
>         then detect this frame as scenecut. Values between 5 and 15 are
> recommended. Default 5.
> -
> +
> +.. option:: --ctu-info <0, 1, 2, 4, 6>
> +
> +   This value enables receiving CTU information asynchronously and
> determine reaction to the CTU information. Default 0.
> +   1: force the partitions if CTU information is present.
> +   2: functionality of (1) and reduce qp if CTU information has changed.
> +   4: functionality of (1) and force Inter modes when CTU Information has
> changed, merge/skip otherwise.
> +   This option should be enabled only when planning to invoke the API
> function x265_encoder_ctu_info to copy ctu-info asynchronously.
> +   If enabled without calling the API function, the encoder will wait
> indefinitely.
> +
>  .. option:: --intra-refresh
>
>         Enables Periodic Intra Refresh(PIR) instead of keyframe insertion.
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/CMakeLists.txt
> --- a/source/CMakeLists.txt     Tue May 09 12:43:04 2017 +0530
> +++ b/source/CMakeLists.txt     Mon Apr 24 10:13:57 2017 +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 116)
> +set(X265_BUILD 117)
>  configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
>                 "${PROJECT_BINARY_DIR}/x265.def")
>  configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/common/frame.cpp
> --- a/source/common/frame.cpp   Tue May 09 12:43:04 2017 +0530
> +++ b/source/common/frame.cpp   Mon Apr 24 10:13:57 2017 +0530
> @@ -48,6 +48,8 @@
>      m_rcData = NULL;
>      m_encodeStartTime = 0;
>      m_reconfigureRc = false;
> +    m_ctuInfo = NULL;
> +    m_prevCtuInfoChange = NULL;
>  }
>
>  bool Frame::create(x265_param *param, float* quantOffsets)
> @@ -166,6 +168,23 @@
>          delete[] m_userSEI.payloads;
>      }
>
> +    if (m_ctuInfo)
> +    {
> +        uint32_t widthInCU = (m_param->sourceWidth + g_maxCUSize - 1) >>
> g_maxLog2CUSize;
> +        uint32_t heightInCU = (m_param->sourceHeight + g_maxCUSize - 1)
> >> g_maxLog2CUSize;
> +        uint32_t numCUsInFrame = widthInCU * heightInCU;
> +        for (uint32_t i = 0; i < numCUsInFrame; i++)
> +        {
> +            X265_FREE((*m_ctuInfo + i)->ctuInfo);
> +            (*m_ctuInfo + i)->ctuInfo = NULL;
> +        }
> +        X265_FREE(*m_ctuInfo);
> +        *m_ctuInfo = NULL;
> +        X265_FREE(m_ctuInfo);
> +        m_ctuInfo = NULL;
> +        X265_FREE(m_prevCtuInfoChange);
> +        m_prevCtuInfoChange = NULL;
> +    }
>      m_lowres.destroy();
>      X265_FREE(m_rcData);
>  }
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/common/frame.h
> --- a/source/common/frame.h     Tue May 09 12:43:04 2017 +0530
> +++ b/source/common/frame.h     Mon Apr 24 10:13:57 2017 +0530
> @@ -108,6 +108,9 @@
>      x265_analysis_2Pass    m_analysis2Pass;
>      RcStats*               m_rcData;
>
> +    x265_ctu_info_t**      m_ctuInfo;
> +    Event                  m_copied;
> +    int*                   m_prevCtuInfoChange;
>      int64_t                m_encodeStartTime;
>      Frame();
>
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/common/param.cpp
> --- a/source/common/param.cpp   Tue May 09 12:43:04 2017 +0530
> +++ b/source/common/param.cpp   Mon Apr 24 10:13:57 2017 +0530
> @@ -275,6 +275,7 @@
>
>      param->toneMapFile = NULL;
>      param->bDhdr10opt = 0;
> +    param->bCTUInfo = 0;
>  }
>
>  int x265_param_default_preset(x265_param* param, const char* preset,
> const char* tune)
> @@ -954,6 +955,7 @@
>          OPT("limit-sao") p->bLimitSAO = atobool(value);
>          OPT("dhdr10-info") p->toneMapFile = strdup(value);
>          OPT("dhdr10-opt") p->bDhdr10opt = atobool(value);
> +        OPT("ctu-info") p->bCTUInfo = atoi(value);
>          else
>              return X265_PARAM_BAD_NAME;
>      }
> @@ -1294,6 +1296,8 @@
>          "qpmin exceeds supported range (0 to 69)");
>      CHECK(param->log2MaxPocLsb < 4 || param->log2MaxPocLsb > 16,
>          "Supported range for log2MaxPocLsb is 4 to 16");
> +    CHECK(param->bCTUInfo < 0 || (param->bCTUInfo != 0 && param->bCTUInfo
> != 1 && param->bCTUInfo != 2 && param->bCTUInfo != 4 && param->bCTUInfo !=
> 6) || param->bCTUInfo > 6,
> +        "Supported values for bCTUInfo are 0, 1, 2, 4, 6");
>  #if !X86_64
>      CHECK(param->searchMethod == X265_SEA && (param->sourceWidth > 840 ||
> param->sourceHeight > 480),
>          "SEA motion search does not support resolutions greater than 480p
> in 32 bit build");
> @@ -1457,6 +1461,7 @@
>      TOOLOPT(param->bEnableStrongIntraSmoothing,
> "strong-intra-smoothing");
>      TOOLVAL(param->lookaheadSlices, "lslices=%d");
>      TOOLVAL(param->lookaheadThreads, "lthreads=%d")
> +    TOOLVAL(param->bCTUInfo, "ctu-info=%d");
>      if (param->maxSlices > 1)
>          TOOLVAL(param->maxSlices, "slices=%d");
>      if (param->bEnableLoopFilter)
> @@ -1670,6 +1675,7 @@
>      BOOL(p->bDhdr10opt, "dhdr10-opt");
>      s += sprintf(s, " refine-level=%d", p->analysisRefineLevel);
>      BOOL(p->bLimitSAO, "limit-sao");
> +    s += sprintf(s, " ctu-info=%d", p->bCTUInfo);
>  #undef BOOL
>      return buf;
>  }
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/encoder/api.cpp
> --- a/source/encoder/api.cpp    Tue May 09 12:43:04 2017 +0530
> +++ b/source/encoder/api.cpp    Mon Apr 24 10:13:57 2017 +0530
> @@ -295,6 +295,14 @@
>      encoder->m_bQueuedIntraRefresh = 1;
>      return 0;
>  }
> +int x265_encoder_ctu_info(x265_encoder *enc, int poc, x265_ctu_info_t**
> ctu)
> +{
> +    if (!ctu || !enc)
> +        return -1;
> +    Encoder* encoder = static_cast<Encoder*>(enc);
> +    encoder->copyCtuInfo(ctu, poc);
> +    return 0;
> +}
>
>  void x265_cleanup(void)
>  {
> @@ -372,6 +380,7 @@
>
>      sizeof(x265_frame_stats),
>      &x265_encoder_intra_refresh,
> +    &x265_encoder_ctu_info,
>  };
>
>  typedef const x265_api* (*api_get_func)(int bitDepth);
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/encoder/dpb.cpp
> --- a/source/encoder/dpb.cpp    Tue May 09 12:43:04 2017 +0530
> +++ b/source/encoder/dpb.cpp    Mon Apr 24 10:13:57 2017 +0530
> @@ -105,6 +105,23 @@
>                  }
>              }
>
> +            if (curFrame->m_ctuInfo != NULL)
> +            {
> +                uint32_t widthInCU = (curFrame->m_param->sourceWidth +
> g_maxCUSize - 1) >> g_maxLog2CUSize;
> +                uint32_t heightInCU = (curFrame->m_param->sourceHeight +
> g_maxCUSize - 1) >> g_maxLog2CUSize;
> +                uint32_t numCUsInFrame = widthInCU * heightInCU;
> +                for (uint32_t i = 0; i < numCUsInFrame; i++)
> +                {
> +                    X265_FREE((*curFrame->m_ctuInfo + i)->ctuInfo);
> +                    (*curFrame->m_ctuInfo + i)->ctuInfo = NULL;
> +                }
> +                X265_FREE(*curFrame->m_ctuInfo);
> +                *(curFrame->m_ctuInfo) = NULL;
> +                X265_FREE(curFrame->m_ctuInfo);
> +                curFrame->m_ctuInfo = NULL;
> +                X265_FREE(curFrame->m_prevCtuInfoChange);
> +                curFrame->m_prevCtuInfoChange = NULL;
> +            }
>              curFrame->m_encData = NULL;
>              curFrame->m_reconPic = NULL;
>          }
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp        Tue May 09 12:43:04 2017 +0530
> +++ b/source/encoder/encoder.cpp        Mon Apr 24 10:13:57 2017 +0530
> @@ -1157,6 +1157,120 @@
>      return x265_check_params(encParam);
>  }
>
> +void Encoder::copyCtuInfo(x265_ctu_info_t** frameCtuInfo, int poc)
> +{
> +    uint32_t widthInCU = (m_param->sourceWidth + g_maxCUSize - 1) >>
> g_maxLog2CUSize;
> +    uint32_t heightInCU = (m_param->sourceHeight + g_maxCUSize - 1) >>
> g_maxLog2CUSize;
> +    Frame* curFrame;
> +    Frame* prevFrame = NULL;
> +    int32_t* frameCTU;
> +    uint32_t numCUsInFrame = widthInCU * heightInCU;
> +    uint32_t maxNum8x8Partitions = 64;
> +    bool copied = false;
> +    do
> +    {
> +        curFrame = m_lookahead->m_inputQueue.getPOC(poc);
> +        if (!curFrame)
> +            curFrame = m_lookahead->m_outputQueue.getPOC(poc);
> +
> +        if (poc > 0)
> +        {
> +            prevFrame = m_lookahead->m_inputQueue.getPOC(poc - 1);
> +            if (!prevFrame)
> +                prevFrame = m_lookahead->m_outputQueue.getPOC(poc - 1);
> +            if (!prevFrame)
> +            {
> +                FrameEncoder* prevEncoder;
> +                for (int i = 0; i < m_param->frameNumThreads; i++)
> +                {
> +                    prevEncoder = m_frameEncoder[i];
> +                    prevFrame = prevEncoder->m_frame;
> +                    if (prevFrame && (prevEncoder->m_frame->m_poc == poc
> - 1))
> +                    {
> +                        prevFrame = prevEncoder->m_frame;
> +                        break;
> +                    }
> +                }
> +            }
> +        }
> +        x265_ctu_info_t* ctuTemp, *prevCtuTemp;
> +        if (curFrame)
> +        {
> +            if (!curFrame->m_ctuInfo)
> +                CHECKED_MALLOC(curFrame->m_ctuInfo, x265_ctu_info_t*, 1);
> +            CHECKED_MALLOC(*curFrame->m_ctuInfo, x265_ctu_info_t,
> numCUsInFrame);
> +            CHECKED_MALLOC_ZERO(curFrame->m_prevCtuInfoChange, int,
> numCUsInFrame * maxNum8x8Partitions);
> +            for (uint32_t i = 0; i < numCUsInFrame; i++)
> +            {
> +                ctuTemp = *curFrame->m_ctuInfo + i;
> +                CHECKED_MALLOC(frameCTU, int32_t, maxNum8x8Partitions);
> +                ctuTemp->ctuInfo = (int32_t*)frameCTU;
> +                ctuTemp->ctuAddress = frameCtuInfo[i]->ctuAddress;
> +                memcpy(ctuTemp->ctuPartitions, frameCtuInfo[i]->ctuPartitions,
> sizeof(int32_t) * maxNum8x8Partitions);
> +                memcpy(ctuTemp->ctuInfo, frameCtuInfo[i]->ctuInfo,
> sizeof(int32_t) * maxNum8x8Partitions);
> +                if (prevFrame && curFrame->m_poc > 1)
> +                {
> +                    prevCtuTemp = *prevFrame->m_ctuInfo + i;
> +                    for (uint32_t j = 0; j < maxNum8x8Partitions; j++)
> +                        curFrame->m_prevCtuInfoChange[i *
> maxNum8x8Partitions + j] = (*((int32_t *)prevCtuTemp->ctuInfo + j) == 2) ?
> (poc - 1) : prevFrame->m_prevCtuInfoChange[i * maxNum8x8Partitions + j];
> +                }
> +            }
> +            copied = true;
> +            curFrame->m_copied.trigger();
> +        }
> +        else
> +        {
> +            FrameEncoder* curEncoder;
> +            for (int i = 0; i < m_param->frameNumThreads; i++)
> +            {
> +                curEncoder = m_frameEncoder[i];
> +                curFrame = curEncoder->m_frame;
> +                if (curFrame)
> +                {
> +                    if (poc == curFrame->m_poc)
> +                    {
> +                        if (!curFrame->m_ctuInfo)
> +                            CHECKED_MALLOC(curFrame->m_ctuInfo,
> x265_ctu_info_t*, 1);
> +                        CHECKED_MALLOC(*curFrame->m_ctuInfo,
> x265_ctu_info_t, numCUsInFrame);
> +                        CHECKED_MALLOC_ZERO(curFrame->m_prevCtuInfoChange,
> int, numCUsInFrame * maxNum8x8Partitions);
> +                        for (uint32_t l = 0; l < numCUsInFrame; l++)
> +                        {
> +                            ctuTemp = *curFrame->m_ctuInfo + l;
> +                            CHECKED_MALLOC(frameCTU, int32_t,
> maxNum8x8Partitions);
> +                            ctuTemp->ctuInfo = (int32_t*)frameCTU;
> +                            ctuTemp->ctuAddress =
> frameCtuInfo[l]->ctuAddress;
> +                            memcpy(ctuTemp->ctuPartitions,
> frameCtuInfo[l]->ctuPartitions, sizeof(int32_t) * maxNum8x8Partitions);
> +                            memcpy(ctuTemp->ctuInfo,
> frameCtuInfo[l]->ctuInfo, sizeof(int32_t) * maxNum8x8Partitions);
> +                            if (prevFrame && curFrame->m_poc > 1)
> +                            {
> +                                prevCtuTemp = *prevFrame->m_ctuInfo + l;
> +                                for (uint32_t j = 0; j <
> maxNum8x8Partitions; j++)
> +                                    curFrame->m_prevCtuInfoChange[l *
> maxNum8x8Partitions + j] = (*((int32_t *)prevCtuTemp->ctuInfo + j) ==
> CTU_INFO_CHANGE) ? (poc - 1) : prevFrame->m_prevCtuInfoChange[l *
> maxNum8x8Partitions + j];
> +                            }
> +                        }
> +                        copied = true;
> +                        curFrame->m_copied.trigger();
> +                        break;
> +                    }
> +                }
> +            }
> +        }
> +    } while (!copied);
> +    return;
> +fail:
> +    for (uint32_t i = 0; i < numCUsInFrame; i++)
> +    {
> +        X265_FREE((*curFrame->m_ctuInfo + i)->ctuInfo);
> +        (*curFrame->m_ctuInfo + i)->ctuInfo = NULL;
> +    }
> +    X265_FREE(*curFrame->m_ctuInfo);
> +    *(curFrame->m_ctuInfo) = NULL;
> +    X265_FREE(curFrame->m_ctuInfo);
> +    curFrame->m_ctuInfo = NULL;
> +    X265_FREE(curFrame->m_prevCtuInfoChange);
> +    curFrame->m_prevCtuInfoChange = NULL;
> +}
> +
>  void EncStats::addPsnr(double psnrY, double psnrU, double psnrV)
>  {
>      m_psnrSumY += psnrY;
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/encoder/encoder.h
> --- a/source/encoder/encoder.h  Tue May 09 12:43:04 2017 +0530
> +++ b/source/encoder/encoder.h  Mon Apr 24 10:13:57 2017 +0530
> @@ -199,6 +199,8 @@
>
>      int reconfigureParam(x265_param* encParam, x265_param* param);
>
> +    void copyCtuInfo(x265_ctu_info_t** frameCtuInfo, int poc);
> +
>      void getStreamHeaders(NALList& list, Entropy& sbacCoder, Bitstream&
> bs);
>
>      void fetchStats(x265_stats* stats, size_t statsSizeBytes);
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/encoder/frameencoder.cpp
> --- a/source/encoder/frameencoder.cpp   Tue May 09 12:43:04 2017 +0530
> +++ b/source/encoder/frameencoder.cpp   Mon Apr 24 10:13:57 2017 +0530
> @@ -295,6 +295,11 @@
>
>      while (m_threadActive)
>      {
> +        if (m_param->bCTUInfo)
> +        {
> +            while (!m_frame->m_ctuInfo)
> +                m_frame->m_copied.wait();
> +        }
>          compressFrame();
>          m_done.trigger(); /* FrameEncoder::getEncodedPicture() blocks
> for this event */
>          m_enable.wait();
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/x265.h
> --- a/source/x265.h     Tue May 09 12:43:04 2017 +0530
> +++ b/source/x265.h     Mon Apr 24 10:13:57 2017 +0530
> @@ -160,6 +160,20 @@
>      x265_cu_stats    cuStats;
>      double           totalFrameTime;
>  } x265_frame_stats;
> +typedef struct x265_ctu_info_t
> +{
> +    int32_t ctuAddress;
> +    int32_t ctuPartitions[64];
> +    void*    ctuInfo;
> +} x265_ctu_info_t;
> +
> +typedef enum
> +{
> +    NO_CTU_INFO = 0,
> +    HAS_CTU_INFO = 1,
> +    CTU_INFO_CHANGE = 2,
> +}CTUInfo;
> +
>
>  /* Arbitrary User SEI
>   * Payload size is in bytes and the payload pointer must be non-NULL.
> @@ -1391,6 +1405,9 @@
>      /* Insert tone mapping information only for IDR frames and when the
>       * tone mapping information changes. */
>      int       bDhdr10opt;
> +
> +    /* Determine how x265 react to the content information recieved
> through the API */
> +    int       bCTUInfo;
>  } x265_param;
>  /* x265_param_alloc:
>   *  Allocates an x265_param instance. The returned param structure is not
> @@ -1581,6 +1598,12 @@
>
>  int x265_encoder_intra_refresh(x265_encoder *);
>
> +/* x265_encoder_ctu_info:
> + *    Copy CTU information such as ctu address and ctu partition
> structure of all
> + *    CTUs in each frame. The function is invoked only if "--ctu-info" is
> enabled and
> + *    the encoder will wait for this copy to complete if enabled.
> + */
> +int x265_encoder_ctu_info(x265_encoder *, int poc, x265_ctu_info_t**
> ctu);
>  /* x265_cleanup:
>   *       release library static allocations, reset configured CTU size */
>  void x265_cleanup(void);
> @@ -1629,6 +1652,7 @@
>
>      int           sizeof_frame_stats;   /* sizeof(x265_frame_stats) */
>      int           (*encoder_intra_refresh)(x265_encoder*);
> +    int           (*encoder_ctu_info)(x265_encoder*, int,
> x265_ctu_info_t**);
>      /* add new pointers to the end, or increment X265_MAJOR_VERSION */
>  } x265_api;
>
> diff -r 7ecd263f6d43 -r 6a9eb27b2b0d source/x265cli.h
> --- a/source/x265cli.h  Tue May 09 12:43:04 2017 +0530
> +++ b/source/x265cli.h  Mon Apr 24 10:13:57 2017 +0530
> @@ -122,6 +122,7 @@
>      { "scenecut",       required_argument, NULL, 0 },
>      { "no-scenecut",          no_argument, NULL, 0 },
>      { "scenecut-bias",  required_argument, NULL, 0 },
> +    { "ctu-info",       required_argument, NULL, 0 },
>      { "intra-refresh",        no_argument, NULL, 0 },
>      { "rc-lookahead",   required_argument, NULL, 0 },
>      { "lookahead-slices", required_argument, NULL, 0 },
> @@ -367,6 +368,11 @@
>      H1("   --[no-]tskip-fast             Enable fast intra transform
> skipping. Default %s\n", OPT(param->bEnableTSkipFast));
>      H1("   --nr-intra <integer>          An integer value in range of 0
> to 2000, which denotes strength of noise reduction in intra CUs. Default
> 0\n");
>      H1("   --nr-inter <integer>          An integer value in range of 0
> to 2000, which denotes strength of noise reduction in inter CUs. Default
> 0\n");
> +    H0("   --ctu-info <integer>          Enable receiving ctu information
> asynchronously and determine reaction to the CTU information (0, 1, 2, 4,
> 6) Default 0\n"
> +       "                                    - 1: force the partitions if
> CTU information is present\n"
> +       "                                    - 2: functionality of (1) and
> reduce qp if CTU information has changed\n"
> +       "                                    - 4: functionality of (1) and
> force Inter modes when CTU Information has changed, merge/skip otherwise\n"
> +       "                                    Enable this option only when
> planning to invoke the API function x265_encoder_ctu_info to copy ctu-info
> asynchronously\n");
>      H0("\nCoding tools:\n");
>      H0("-w/--[no-]weightp                Enable weighted prediction in P
> slices. Default %s\n", OPT(param->bEnableWeightedPred));
>      H0("   --[no-]weightb                Enable weighted prediction in B
> slices. Default %s\n", OPT(param->bEnableWeightedBiPred));
> _______________________________________________
> 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/20170510/067d5af8/attachment-0001.html>


More information about the x265-devel mailing list