changeset 11917:dd9772385d15

Add CLI option to enable or disable picture copy to internal frame buffer
author Kavitha Sampath <kavitha@multicorewareinc.com>
date Tue, 14 Nov 2017 11:00:09 +0530
parents 6ac1b12bcde9
children 8b12db6c5f6b
files doc/reST/cli.rst source/CMakeLists.txt source/common/frame.cpp source/common/param.cpp source/common/picyuv.cpp source/common/picyuv.h source/x265.h source/x265cli.h
diffstat 8 files changed, 81 insertions(+-), 45 deletions(-) [+]
line wrap: on
line diff
--- a/doc/reST/cli.rst	Fri Nov 10 19:02:48 2017 +0530
+++ b/doc/reST/cli.rst	Tue Nov 14 11:00:09 2017 +0530
@@ -399,6 +399,18 @@ Performance Options
 
 	Default: 1 slice per frame. **Experimental feature**
 
+.. option:: --copy-pic, --no-copy-pic
+
+	Allow encoder to copy input x265 pictures to internal frame buffers. When disabled,
+	x265 will not make an internal copy of the input picture and will work with the
+	application's buffers. While this allows for deeper integration, it is the responsbility
+	of the application to (a) ensure that the allocated picture has extra space for padding
+	that will be done by the library, and (b) the buffers aren't recycled until the library
+	has completed encoding this frame (which can be figured out by tracking NALs output by x265)
+
+	Default: enabled
+
+
 Input/Output File Options
 =========================
 
--- a/source/CMakeLists.txt	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/CMakeLists.txt	Tue Nov 14 11:00:09 2017 +0530
@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CP
 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 144)
+set(X265_BUILD 145)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
--- a/source/common/frame.cpp	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/common/frame.cpp	Tue Nov 14 11:00:09 2017 +0530
@@ -85,7 +85,7 @@ bool Frame::create(x265_param *param, fl
         m_analysis2Pass.analysisFramedata = NULL;
     }
 
-    if (m_fencPic->create(param) && m_lowres.create(m_fencPic, param->bframes, !!param->rc.aqMode || !!param->bAQMotion, param->rc.qgSize))
+    if (m_fencPic->create(param, !!m_param->bCopyPicToFrame) && m_lowres.create(m_fencPic, param->bframes, !!param->rc.aqMode || !!param->bAQMotion, param->rc.qgSize))
     {
         X265_CHECK((m_reconColCount == NULL), "m_reconColCount was initialized");
         m_numRows = (m_fencPic->m_picHeight + param->maxCUSize - 1)  / param->maxCUSize;
@@ -158,7 +158,8 @@ void Frame::destroy()
 
     if (m_fencPic)
     {
-        m_fencPic->destroy();
+        if (m_param->bCopyPicToFrame)
+            m_fencPic->destroy();
         delete m_fencPic;
         m_fencPic = NULL;
     }
--- a/source/common/param.cpp	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/common/param.cpp	Tue Nov 14 11:00:09 2017 +0530
@@ -290,6 +290,7 @@ void x265_param_default(x265_param* para
     param->csvfpt = NULL;
     param->forceFlush = 0;
     param->bDisableLookahead = 0;
+    param->bCopyPicToFrame = 1;
 
     /* DCT Approximations */
     param->bLowPassDct = 0;
@@ -987,6 +988,7 @@ int x265_param_parse(x265_param* p, cons
 		OPT("lowpass-dct") p->bLowPassDct = atobool(value);
         OPT("vbv-end") p->vbvBufferEnd = atof(value);
         OPT("vbv-end-fr-adj") p->vbvEndFrameAdjust = atof(value);
+        OPT("copy-pic") p->bCopyPicToFrame = atobool(value);
         OPT("refine-mv-type")
         {
             if (strcmp(strdup(value), "avc") == 0)
@@ -1718,6 +1720,7 @@ char *x265_param2string(x265_param* p, i
     s += sprintf(s, " ctu-info=%d", p->bCTUInfo);
     BOOL(p->bLowPassDct, "lowpass-dct");
     s += sprintf(s, " refine-mv-type=%d", p->bMVType);
+    s += sprintf(s, " copy-pic=%d", p->bCopyPicToFrame);
 #undef BOOL
     return buf;
 }
--- a/source/common/picyuv.cpp	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/common/picyuv.cpp	Tue Nov 14 11:00:09 2017 +0530
@@ -69,7 +69,7 @@ PicYuv::PicYuv()
     m_vChromaShift = 0;
 }
 
-bool PicYuv::create(x265_param* param, pixel *pixelbuf)
+bool PicYuv::create(x265_param* param, bool picAlloc, pixel *pixelbuf)
 {
     m_param = param;
     uint32_t picWidth = m_param->sourceWidth;
@@ -93,8 +93,11 @@ bool PicYuv::create(x265_param* param, p
         m_picOrg[0] = pixelbuf;
     else
     {
-        CHECKED_MALLOC(m_picBuf[0], pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
-        m_picOrg[0] = m_picBuf[0] + m_lumaMarginY * m_stride + m_lumaMarginX;
+        if (picAlloc)
+        {
+            CHECKED_MALLOC(m_picBuf[0], pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));
+            m_picOrg[0] = m_picBuf[0] + m_lumaMarginY * m_stride + m_lumaMarginX;
+        }
     }
 
     if (picCsp != X265_CSP_I400)
@@ -102,12 +105,14 @@ bool PicYuv::create(x265_param* param, p
         m_chromaMarginX = m_lumaMarginX;  // keep 16-byte alignment for chroma CTUs
         m_chromaMarginY = m_lumaMarginY >> m_vChromaShift;
         m_strideC = ((numCuInWidth * m_param->maxCUSize) >> m_hChromaShift) + (m_chromaMarginX * 2);
+        if (picAlloc)
+        {
+            CHECKED_MALLOC(m_picBuf[1], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));
+            CHECKED_MALLOC(m_picBuf[2], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));
 
-        CHECKED_MALLOC(m_picBuf[1], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));
-        CHECKED_MALLOC(m_picBuf[2], pixel, m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));
-
-        m_picOrg[1] = m_picBuf[1] + m_chromaMarginY * m_strideC + m_chromaMarginX;
-        m_picOrg[2] = m_picBuf[2] + m_chromaMarginY * m_strideC + m_chromaMarginX;
+            m_picOrg[1] = m_picBuf[1] + m_chromaMarginY * m_strideC + m_chromaMarginX;
+            m_picOrg[2] = m_picBuf[2] + m_chromaMarginY * m_strideC + m_chromaMarginX;
+        }
     }
     else
     {
@@ -236,8 +241,10 @@ void PicYuv::copyFromPicture(const x265_
     uint64_t crSum;
     lumaSum = cbSum = crSum = 0;
 
-    if (pic.bitDepth == 8)
+    if (m_param->bCopyPicToFrame)
     {
+        if (pic.bitDepth == 8)
+        {
 #if (X265_DEPTH > 8)
         {
             pixel *yPixel = m_picOrg[0];
@@ -260,7 +267,7 @@ void PicYuv::copyFromPicture(const x265_
             }
         }
 #else /* Case for (X265_DEPTH == 8) */
-        // TODO: Does we need this path? may merge into above in future
+            // TODO: Does we need this path? may merge into above in future
         {
             pixel *yPixel = m_picOrg[0];
             uint8_t *yChar = (uint8_t*)pic.planes[0];
@@ -294,47 +301,54 @@ void PicYuv::copyFromPicture(const x265_
             }
         }
 #endif /* (X265_DEPTH > 8) */
-    }
-    else /* pic.bitDepth > 8 */
-    {
-        /* defensive programming, mask off bits that are supposed to be zero */
-        uint16_t mask = (1 << X265_DEPTH) - 1;
-        int shift = abs(pic.bitDepth - X265_DEPTH);
-        pixel *yPixel = m_picOrg[0];
+        }
+        else /* pic.bitDepth > 8 */
+        {
+            /* defensive programming, mask off bits that are supposed to be zero */
+            uint16_t mask = (1 << X265_DEPTH) - 1;
+            int shift = abs(pic.bitDepth - X265_DEPTH);
+            pixel *yPixel = m_picOrg[0];
 
-        uint16_t *yShort = (uint16_t*)pic.planes[0];
-
-        if (pic.bitDepth > X265_DEPTH)
-        {
-            /* shift right and mask pixels to final size */
-            primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);
-        }
-        else /* Case for (pic.bitDepth <= X265_DEPTH) */
-        {
-            /* shift left and mask pixels to final size */
-            primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);
-        }
-
-        if (param.internalCsp != X265_CSP_I400)
-        {
-            pixel *uPixel = m_picOrg[1];
-            pixel *vPixel = m_picOrg[2];
-
-            uint16_t *uShort = (uint16_t*)pic.planes[1];
-            uint16_t *vShort = (uint16_t*)pic.planes[2];
+            uint16_t *yShort = (uint16_t*)pic.planes[0];
 
             if (pic.bitDepth > X265_DEPTH)
             {
-                primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
-                primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
+                /* shift right and mask pixels to final size */
+                primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);
             }
             else /* Case for (pic.bitDepth <= X265_DEPTH) */
             {
-                primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
-                primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
+                /* shift left and mask pixels to final size */
+                primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);
+            }
+
+            if (param.internalCsp != X265_CSP_I400)
+            {
+                pixel *uPixel = m_picOrg[1];
+                pixel *vPixel = m_picOrg[2];
+
+                uint16_t *uShort = (uint16_t*)pic.planes[1];
+                uint16_t *vShort = (uint16_t*)pic.planes[2];
+
+                if (pic.bitDepth > X265_DEPTH)
+                {
+                    primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
+                    primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
+                }
+                else /* Case for (pic.bitDepth <= X265_DEPTH) */
+                {
+                    primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
+                    primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);
+                }
             }
         }
     }
+    else
+    {
+        m_picOrg[0] = (pixel*)pic.planes[0];
+        m_picOrg[1] = (pixel*)pic.planes[1];
+        m_picOrg[2] = (pixel*)pic.planes[2];
+    }
 
     pixel *Y = m_picOrg[0];
     pixel *U = m_picOrg[1];
--- a/source/common/picyuv.h	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/common/picyuv.h	Tue Nov 14 11:00:09 2017 +0530
@@ -76,7 +76,7 @@ public:
 
     PicYuv();
 
-    bool  create(x265_param* param, pixel *pixelbuf = NULL);
+    bool  create(x265_param* param, bool picAlloc = true, pixel *pixelbuf = NULL);
     bool  createOffsets(const SPS& sps);
     void  destroy();
     int   getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t picCsp);
--- a/source/x265.h	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/x265.h	Tue Nov 14 11:00:09 2017 +0530
@@ -1531,6 +1531,9 @@ typedef struct x265_param
 
     /* Reuse MV information obtained through API */
     int       bMVType;
+
+    /* Allow the encoder to have a copy of the planes of x265_picture in Frame */
+    int       bCopyPicToFrame;
 } x265_param;
 
 /* x265_param_alloc:
--- a/source/x265cli.h	Fri Nov 10 19:02:48 2017 +0530
+++ b/source/x265cli.h	Tue Nov 14 11:00:09 2017 +0530
@@ -286,6 +286,8 @@ static const struct option long_options[
     { "no-splitrd-skip",      no_argument, NULL, 0 },
     { "lowpass-dct",          no_argument, NULL, 0 },
     { "refine-mv-type", required_argument, NULL, 0 },
+    { "copy-pic",             no_argument, NULL, 0 },
+    { "no-copy-pic",          no_argument, NULL, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
@@ -339,6 +341,7 @@ static void showHelp(x265_param *param)
     H0("   --seek <integer>              First frame to encode\n");
     H1("   --[no-]interlace <bff|tff>    Indicate input pictures are interlace fields in temporal order. Default progressive\n");
     H1("   --dither                      Enable dither if downscaling to 8 bit pixels. Default disabled\n");
+    H0("   --[no-]copy-pic               Copy buffers of input picture in frame. Default %s\n", OPT(param->bCopyPicToFrame));
     H0("\nQuality reporting metrics:\n");
     H0("   --[no-]ssim                   Enable reporting SSIM metric scores. Default %s\n", OPT(param->bEnableSsim));
     H0("   --[no-]psnr                   Enable reporting PSNR metric scores. Default %s\n", OPT(param->bEnablePsnr));