[x265] [PATCH] encoder:auto-padding to min CU size and set conformance window

Steve Borho steve at borho.org
Mon Oct 21 20:20:09 CEST 2013


On Mon, Oct 21, 2013 at 3:42 AM, Gopu Govindaswamy <
gopu at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Gopu Govindaswamy <gopu at multicorewareinc.com>
> # Date 1382344931 -19800
> # Node ID 7171863830432dbdbfaab8e9803a7526c3500088
> # Parent  ff8860e0b3082cbb1848e0f5c89e73dc1d7aa87e
> encoder:auto-padding to min CU size and set conformance window
>
> diff -r ff8860e0b308 -r 717186383043 source/Lib/TLibCommon/TComPicYuv.cpp
> --- a/source/Lib/TLibCommon/TComPicYuv.cpp      Mon Oct 21 13:16:44 2013
> +0530
> +++ b/source/Lib/TLibCommon/TComPicYuv.cpp      Mon Oct 21 14:12:11 2013
> +0530
> @@ -357,7 +357,7 @@
>   * Upscale pixels from 8bits to 16 bits when required, but do not modify
> pixels.
>   * This new routine is GPL
>   */
> -void TComPicYuv::copyFromPicture(const x265_picture_t& pic)
> +void TComPicYuv::copyFromPicture(const x265_picture_t& pic, int *pad)
>  {
>      Pel *Y = getLumaAddr();
>      Pel *U = getCbAddr();
> @@ -367,15 +367,22 @@
>      uint8_t *u = (uint8_t*)pic.planes[1];
>      uint8_t *v = (uint8_t*)pic.planes[2];
>
> +    int padx = pad[0];
> +    int pady = pad[1];
> +
>  #if HIGH_BIT_DEPTH
>      if (sizeof(Pel) * 8 > pic.bitDepth)
>      {
>          assert(pic.bitDepth == 8);
>
> +        /* width and height - without padsize */
> +        int width = m_picWidth - padx;
> +        int height = m_picHeight - pady;
> +
>          // Manually copy pixels to up-size them
> -        for (int r = 0; r < m_picHeight; r++)
> +        for (int r = 0; r < height; r++)
>          {
> -            for (int c = 0; c < m_picWidth; c++)
> +            for (int c = 0; c < width; c++)
>              {
>                  Y[c] = (Pel)y[c];
>              }
> @@ -384,9 +391,9 @@
>              y += pic.stride[0];
>          }
>
> -        for (int r = 0; r < m_picHeight >> 1; r++)
> +        for (int r = 0; r < height >> 1; r++)
>          {
> -            for (int c = 0; c < m_picWidth >> 1; c++)
> +            for (int c = 0; c < width >> 1; c++)
>              {
>                  U[c] = (Pel)u[c];
>                  V[c] = (Pel)v[c];
> @@ -397,30 +404,105 @@
>              u += pic.stride[1];
>              v += pic.stride[2];
>          }
> +
> +        /* Extend the right if width is not multiple of minimum CU size */
> +        Y = getLumaAddr();
> +        U = getCbAddr();
> +        V = getCrAddr();
> +
> +        if (padx)
> +        {
> +            for (int r = 0; r < height; r++)
> +            {
> +                for (int x = 0; x < padx; x++)
> +                    Y[width + x] = Y[width - 1];
> +                Y += getStride();
> +            }
> +
> +            for (int r = 0; r < height >> 1; r++)
> +            {
> +                for (int x = 0; x < padx >> 1; x++)
> +                {
> +                    U[(width >> 1) + x] = U[(width >> 1) - 1];
> +                    V[(width >> 1) + x] = V[(width >> 1) - 1];
> +                }
> +                U += getCStride();
> +                V += getCStride();
> +            }
> +        }
> +
> +        /* extend the top if height is not multiple of the minimum CU
> size */
>

height extension should be on the bottom; it is much more efficient that way


> +        if (pady)
> +        {
> +            Y = getLumaAddr();
> +            U = getCbAddr();
> +            V = getCrAddr();
> +
> +            for (uint32_t i = 0; i < pady; i++)
> +                memcpy(Y - (i + 1) * getStride(), Y, getStride() *
> sizeof(Pel));
> +
> +            for (uint32_t y = 0; y < pady; y++)
> +            {
> +                memcpy(U - (y + 1) * getCStride(), U, getCStride() *
> sizeof(Pel));
> +                memcpy(V - (y + 1) * getCStride(), V, getCStride() *
> sizeof(Pel));
> +            }
> +        }
>      }
>      else
>  #endif // if HIGH_BIT_DEPTH
>      {
> -        int width = m_picWidth * (pic.bitDepth > 8 ? 2 : 1);
> +
> +        /* width and height - without padsize */
> +        int width = (m_picWidth * (pic.bitDepth > 8 ? 2 : 1)) - padx;
> +        int height = m_picHeight - pady;
>
>          // copy pixels by row into encoder's buffer
> -        for (int r = 0; r < m_picHeight; r++)
> +        for (int r = 0; r < height; r++)
>          {
>              memcpy(Y, y, width);
>
> +            /* extend the right if width is not multiple of the minimum
> CU size */
> +            if (padx)
> +                ::memset(Y + width, Y[width - 1], padx);
> +
>              Y += getStride();
>              y += pic.stride[0];
> +
>          }
>
> -        for (int r = 0; r < m_picHeight >> 1; r++)
> +        for (int r = 0; r < height >> 1; r++)
>          {
>              memcpy(U, u, width >> 1);
>              memcpy(V, v, width >> 1);
>
> +            /* extend the right if width is not multiple of the minimum
> CU size */
> +            if (padx)
> +            {
> +                ::memset(U + (width >> 1), U[(width >> 1) - 1], padx >>
> 1);
> +                ::memset(V + (width >> 1), V[(width >> 1) - 1], padx >>
> 1);
> +            }
> +
>              U += getCStride();
>              V += getCStride();
>              u += pic.stride[1];
>              v += pic.stride[2];
>          }
> +
> +        /* extend the top if height is not multiple of the minimum CU
> size */
>

same here


> +        if (pady)
> +        {
> +            Y = getLumaAddr();
> +            U = getCbAddr();
> +            V = getCrAddr();
> +
> +            for (uint32_t i = 0; i < pady; i++)
> +                memcpy(Y - (i + 1) * getStride(), Y, getStride() *
> sizeof(pixel));
> +
> +            for (uint32_t y = 0; y < pady; y++)
> +            {
> +                memcpy(U - (y + 1) * getCStride(), U, getCStride() *
> sizeof(pixel));
> +                memcpy(V - (y + 1) * getCStride(), V, getCStride() *
> sizeof(pixel));
> +            }
> +        }
>      }
>  }
> diff -r ff8860e0b308 -r 717186383043 source/Lib/TLibCommon/TComPicYuv.h
> --- a/source/Lib/TLibCommon/TComPicYuv.h        Mon Oct 21 13:16:44 2013
> +0530
> +++ b/source/Lib/TLibCommon/TComPicYuv.h        Mon Oct 21 14:12:11 2013
> +0530
> @@ -178,7 +178,7 @@
>      void  copyToPicLuma(TComPicYuv* destYuv);
>      void  copyToPicCb(TComPicYuv* destYuv);
>      void  copyToPicCr(TComPicYuv* destYuv);
> -    void  copyFromPicture(const x265_picture_t&);
> +    void  copyFromPicture(const x265_picture_t&, int *pad);
>
>      MotionReference* generateMotionReference(wpScalingParam *w);
>
> diff -r ff8860e0b308 -r 717186383043 source/Lib/TLibCommon/TComSlice.h
> --- a/source/Lib/TLibCommon/TComSlice.h Mon Oct 21 13:16:44 2013 +0530
> +++ b/source/Lib/TLibCommon/TComSlice.h Mon Oct 21 14:12:11 2013 +0530
> @@ -558,7 +558,7 @@
>
>  class Window
>  {
> -private:
> +public:
>
>      bool          m_enabledFlag;
>      int           m_winLeftOffset;
> @@ -566,8 +566,6 @@
>      int           m_winTopOffset;
>      int           m_winBottomOffset;
>
> -public:
> -
>      Window()
>          : m_enabledFlag(false)
>          , m_winLeftOffset(0)
> diff -r ff8860e0b308 -r 717186383043 source/common/common.cpp
> --- a/source/common/common.cpp  Mon Oct 21 13:16:44 2013 +0530
> +++ b/source/common/common.cpp  Mon Oct 21 14:12:11 2013 +0530
> @@ -250,10 +250,6 @@
>            "Minimum partition width size should be larger than or equal to
> 8");
>      CHECK(param->maxCUSize < 16,
>            "Maximum partition width size should be larger than or equal to
> 16");
> -    CHECK((param->sourceWidth  % (param->maxCUSize >> (maxCUDepth - 1)))
> != 0,
> -          "Resulting coded frame width must be a multiple of the minimum
> CU size");
> -    CHECK((param->sourceHeight % (param->maxCUSize >> (maxCUDepth - 1)))
> != 0,
> -          "Resulting coded frame height must be a multiple of the minimum
> CU size");
>
>      CHECK((1u << tuQTMaxLog2Size) > param->maxCUSize,
>            "QuadtreeTULog2MaxSize must be log2(maxCUSize) or smaller.");
> diff -r ff8860e0b308 -r 717186383043 source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp        Mon Oct 21 13:16:44 2013 +0530
> +++ b/source/encoder/encoder.cpp        Mon Oct 21 14:12:11 2013 +0530
> @@ -180,7 +180,7 @@
>
>          /* Copy input picture into a TComPic, send to lookahead */
>          pic->getSlice()->setPOC(++m_pocLast);
> -        pic->getPicYuvOrg()->copyFromPicture(*pic_in);
> +        pic->getPicYuvOrg()->copyFromPicture(*pic_in, m_pad);
>          pic->m_userData = pic_in->userData;
>          pic->m_pts = pic_in->pts;
>
> @@ -972,9 +972,36 @@
>      m_maxCuDQPDepth = 0;
>      m_maxNumOffsetsPerPic = 2048;
>      m_log2ParallelMergeLevelMinus2 = 0;
> -    m_conformanceWindow.setWindow(0, 0, 0, 0);
> -    int nullpad[2] = { 0, 0 };
> -    setPad(nullpad);
> +    m_pad[0] = m_pad[1] = 0;
> +
> +    //======== set pad size if width is not multiple of the minimum CU
> size =========
> +    uint32_t maxCUDepth = (uint32_t)g_convertToBit[_param->maxCUSize];
> +    uint32_t minCUDepth = (_param->maxCUSize >> (maxCUDepth - 1));
> +    if ((_param->sourceWidth % minCUDepth) != 0)
> +    {
> +        uint32_t padsize = 0;
> +        uint32_t rem = _param->sourceWidth % (_param->maxCUSize >>
> (maxCUDepth - 1));
>

use minCUDepth in these expressions

+        padsize = (_param->maxCUSize >> (maxCUDepth - 1)) - rem;
> +        _param->sourceWidth += padsize;
> +        m_pad[0] = padsize; //pad width
> +    }
> +
> +    //======== set pad size if height is not multiple of the minimum CU
> size =========
> +    if ((_param->sourceHeight % minCUDepth) != 0)
> +    {
> +        uint32_t padsize = 0;
> +        uint32_t rem = _param->sourceHeight % (_param->maxCUSize >>
> (maxCUDepth - 1));
>

and here


> +        padsize = (_param->maxCUSize >> (maxCUDepth - 1)) - rem;
> +        _param->sourceHeight += padsize;
> +        m_pad[1] = padsize; //pad height
> +    }
> +
> +    //======== set the confirmation window
> ========================================
> +    m_conformanceWindow.m_enabledFlag = true;
> +    m_conformanceWindow.m_winRightOffset = m_pad[0];
> +    m_conformanceWindow.m_winTopOffset = m_pad[1];
> +    m_conformanceWindow.m_winBottomOffset = 0;
> +    m_conformanceWindow.m_winLeftOffset = 0;
>
>      m_progressiveSourceFlag = true;
>      m_interlacedSourceFlag = false;
>


Do the pictures padded this way pass MD5 hash validation?  We may need to
modify the code which calculates the MD5 hash to ignore the right and
bottom padding.  Same goes for PSNR; we should not be including the padded
pixels in those calculations - and this will have to be done carefully
everywhere it calculates the number of pixels.

-- 
Steve Borho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20131021/18c74809/attachment-0001.html>


More information about the x265-devel mailing list