<div dir="ltr">From b6c961f9f9fa7a6a24c955798485591102581c0a Mon Sep 17 00:00:00 2001<br>From: Kirithika <<a href="mailto:kirithika@multicorewareinc.com">kirithika@multicorewareinc.com</a>><br>Date: Tue, 2 Jul 2024 14:57:16 +0530<br>Subject: [PATCH] Add compile time conditions to enable Alpha Encode<br><br>---<br> source/CMakeLists.txt      |  5 +++<br> source/abrEncApp.cpp       |  4 +-<br> source/common/param.cpp    |  8 ++++<br> source/common/picyuv.cpp   | 90 ++++++++++++++++++++++++++++----------<br> source/encoder/encoder.cpp |  2 +<br> source/input/y4m.cpp       |  2 +<br> source/input/yuv.cpp       |  2 +<br> source/x265.h              |  4 ++<br> source/x265cli.cpp         |  2 +<br> source/x265cli.h           |  2 +<br> 10 files changed, 96 insertions(+), 25 deletions(-)<br><br>diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt<br>index 9a215cbbf..2dcac3dc6 100755<br>--- a/source/CMakeLists.txt<br>+++ b/source/CMakeLists.txt<br>@@ -595,6 +595,11 @@ if(DETAILED_CU_STATS)<br>     add_definitions(-DDETAILED_CU_STATS)<br> endif(DETAILED_CU_STATS)<br> <br>+option(ENABLE_ALPHA "Enable alpha encoding in x265" OFF)<br>+if(ENABLE_ALPHA)<br>+    add_definitions(-DENABLE_ALPHA)<br>+endif()<br>+<br> add_subdirectory(encoder)<br> add_subdirectory(common)<br> <br>diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp<br>index d8b9f8e3b..96c854de6 100644<br>--- a/source/abrEncApp.cpp<br>+++ b/source/abrEncApp.cpp<br>@@ -1098,12 +1098,12 @@ ret:<br>                 memcpy(dest->planes[0], src->planes[0], src->framesize * sizeof(char));<br>                 dest->planes[1] = (char*)dest->planes[0] + src->stride[0] * src->height;<br>                 dest->planes[2] = (char*)dest->planes[1] + src->stride[1] * (src->height >> x265_cli_csps[src->colorSpace].height[1]);<br>-<br>+#if ENABLE_ALPHA<br>                 if (m_parentEnc->m_param->bEnableAlpha)<br>                 {<br>                     dest->planes[3] = (char*)dest->planes[2] + src->stride[2] * (src->height >> x265_cli_csps[src->colorSpace].height[2]);<br>                 }<br>-<br>+#endif<br>                 m_parentEnc->m_parent->m_picWriteCnt[m_id].incr();<br>             }<br>             else<br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index e05e79eaf..01267b278 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -1448,6 +1448,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br>         OPT("film-grain") p->filmGrain = (char* )value;<br>         OPT("mcstf") p->bEnableTemporalFilter = atobool(value);<br>         OPT("sbrc") p->bEnableSBRC = atobool(value);<br>+#if ENABLE_ALPHA<br>         OPT("alpha")<br>         {<br>             if (atobool(value))<br>@@ -1456,6 +1457,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br>                 p->numScalableLayers = 2;<br>             }<br>         }<br>+#endif<br>         else<br>             return X265_PARAM_BAD_NAME;<br>     }<br>@@ -2091,7 +2093,9 @@ void x265_print_params(x265_param* param)<br>     TOOLOPT(param->rc.bStatWrite, "stats-write");<br>     TOOLOPT(param->rc.bStatRead,  "stats-read");<br>     TOOLOPT(param->bSingleSeiNal, "single-sei");<br>+#if ENABLE_ALPHA<br>     TOOLOPT(param->numScalableLayers > 1, "alpha");<br>+#endif<br> #if ENABLE_HDR10_PLUS<br>     TOOLOPT(param->toneMapFile != NULL, "dhdr10-info");<br> #endif<br>@@ -2356,7 +2360,9 @@ char *x265_param2string(x265_param* p, int padx, int pady)<br>     if (p->filmGrain)<br>         s += sprintf(s, " film-grain=%s", p->filmGrain); // Film grain characteristics model filename<br>     BOOL(p->bEnableTemporalFilter, "mcstf");<br>+#if ENABLE_ALPHA<br>     BOOL(p->bEnableAlpha, "alpha");<br>+#endif<br>     BOOL(p->bEnableSBRC, "sbrc");<br> #undef BOOL<br>     return buf;<br>@@ -2878,8 +2884,10 @@ void x265_copy_params(x265_param* dst, x265_param* src)<br>     dst->confWinRightOffset = src->confWinRightOffset;<br>     dst->confWinBottomOffset = src->confWinBottomOffset;<br>     dst->bliveVBV2pass = src->bliveVBV2pass;<br>+#if ENABLE_ALPHA<br>     dst->bEnableAlpha = src->bEnableAlpha;<br>     dst->numScalableLayers = src->numScalableLayers;<br>+#endif<br> <br>     if (src->videoSignalTypePreset) dst->videoSignalTypePreset = strdup(src->videoSignalTypePreset);<br>     else dst->videoSignalTypePreset = NULL;<br>diff --git a/source/common/picyuv.cpp b/source/common/picyuv.cpp<br>index 8e0b44455..bd5690d3e 100644<br>--- a/source/common/picyuv.cpp<br>+++ b/source/common/picyuv.cpp<br>@@ -354,6 +354,7 @@ void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param& param, i<br>                     }<br>                 }<br>             }<br>+#if ENABLE_ALPHA<br>             if (!isBase && param.bEnableAlpha)<br>             {<br>                 pixel* aPixel = m_picOrg[0];<br>@@ -379,48 +380,91 @@ void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param& param, i<br>                     vPixel += m_strideC;<br>                 }<br>             }<br>+#endif<br>         }<br> #endif /* (X265_DEPTH > 8) */<br>         }<br>         else /* pic.bitDepth > 8 */<br>         {<br>             /* defensive programming, mask off bits that are supposed to be zero */<br>-            uint16_t mask = (1 << X265_DEPTH) - 1;<br>-            int shift = abs(pic.bitDepth - X265_DEPTH);<br>-            pixel *yPixel = m_picOrg[0];<br>+            if (isBase)<br>+            {<br>+                uint16_t mask = (1 << X265_DEPTH) - 1;<br>+                int shift = abs(pic.bitDepth - X265_DEPTH);<br>+                pixel* yPixel = m_picOrg[0];<br> <br>-            uint16_t *yShort = (uint16_t*)pic.planes[0];<br>+                uint16_t* yShort = (uint16_t*)pic.planes[0];<br> <br>-            if (pic.bitDepth > X265_DEPTH)<br>-            {<br>-                /* shift right and mask pixels to final size */<br>-                primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>-            }<br>-            else /* Case for (pic.bitDepth <= X265_DEPTH) */<br>-            {<br>-                /* shift left and mask pixels to final size */<br>-                primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>-            }<br>+                if (pic.bitDepth > X265_DEPTH)<br>+                {<br>+                    /* shift right and mask pixels to final size */<br>+                    primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>+                }<br>+                else /* Case for (pic.bitDepth <= X265_DEPTH) */<br>+                {<br>+                    /* shift left and mask pixels to final size */<br>+                    primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>+                }<br> <br>-            if (param.internalCsp != X265_CSP_I400)<br>+                if (param.internalCsp != X265_CSP_I400)<br>+                {<br>+                    pixel* uPixel = m_picOrg[1];<br>+                    pixel* vPixel = m_picOrg[2];<br>+<br>+                    uint16_t* uShort = (uint16_t*)pic.planes[1];<br>+                    uint16_t* vShort = (uint16_t*)pic.planes[2];<br>+<br>+                    if (pic.bitDepth > X265_DEPTH)<br>+                    {<br>+                        primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>+                        primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>+                    }<br>+                    else /* Case for (pic.bitDepth <= X265_DEPTH) */<br>+                    {<br>+                        primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>+                        primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>+                    }<br>+                }<br>+            }<br>+#if ENABLE_ALPHA<br>+            if (!isBase && param.bEnableAlpha)<br>             {<br>-                pixel *uPixel = m_picOrg[1];<br>-                pixel *vPixel = m_picOrg[2];<br>+                /* defensive programming, mask off bits that are supposed to be zero */<br>+                uint16_t mask = (1 << X265_DEPTH) - 1;<br>+                int shift = abs(pic.bitDepth - X265_DEPTH);<br>+                pixel* yPixel = m_picOrg[0];<br> <br>-                uint16_t *uShort = (uint16_t*)pic.planes[1];<br>-                uint16_t *vShort = (uint16_t*)pic.planes[2];<br>+                uint16_t* yShort = (uint16_t*)pic.planes[3];<br> <br>                 if (pic.bitDepth > X265_DEPTH)<br>                 {<br>-                    primitives.planecopy_sp(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>-                    primitives.planecopy_sp(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>+                    /* shift right and mask pixels to final size */<br>+                    primitives.planecopy_sp(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>                 }<br>                 else /* Case for (pic.bitDepth <= X265_DEPTH) */<br>                 {<br>-                    primitives.planecopy_sp_shl(uShort, pic.stride[1] / sizeof(*uShort), uPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>-                    primitives.planecopy_sp_shl(vShort, pic.stride[2] / sizeof(*vShort), vPixel, m_strideC, width >> m_hChromaShift, height >> m_vChromaShift, shift, mask);<br>+                    /* shift left and mask pixels to final size */<br>+                    primitives.planecopy_sp_shl(yShort, pic.stride[0] / sizeof(*yShort), yPixel, m_stride, width, height, shift, mask);<br>+                }<br>+<br>+                if (param.internalCsp != X265_CSP_I400)<br>+                {<br>+                    pixel* uPixel = m_picOrg[1];<br>+                    pixel* vPixel = m_picOrg[2];<br>+<br>+                    for (int r = 0; r < height >> m_vChromaShift; r++)<br>+                    {<br>+                        for (int c = 0; c < (width >> m_hChromaShift); c++)<br>+                        {<br>+                            uPixel[c] = ((1 << X265_DEPTH) >> 1);<br>+                            vPixel[c] = ((1 << X265_DEPTH) >> 1);<br>+                        }<br>+                        uPixel += m_strideC;<br>+                        vPixel += m_strideC;<br>+                    }<br>                 }<br>             }<br>+#endif<br>         }<br>     }<br>     else<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index dc09be6dc..ef6c5f64a 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -1359,8 +1359,10 @@ void Encoder::copyPicture(x265_picture *dest, const x265_picture *src)<br>     memcpy(dest->planes[0], src->planes[0], src->framesize * sizeof(char));<br>     dest->planes[1] = (char*)dest->planes[0] + src->stride[0] * src->height;<br>     dest->planes[2] = (char*)dest->planes[1] + src->stride[1] * (src->height >> x265_cli_csps[src->colorSpace].height[1]);<br>+#if ENABLE_ALPHA<br>     if(m_param->bEnableAlpha)<br>         dest->planes[3] = (char*)dest->planes[2] + src->stride[2] * (src->height >> x265_cli_csps[src->colorSpace].height[2]);<br>+#endif<br> }<br> <br> bool Encoder::isFilterThisframe(uint8_t sliceTypeConfig, int curSliceType)<br>diff --git a/source/input/y4m.cpp b/source/input/y4m.cpp<br>index eedbf991c..0fe0cc43e 100644<br>--- a/source/input/y4m.cpp<br>+++ b/source/input/y4m.cpp<br>@@ -397,11 +397,13 @@ bool Y4MInput::readPicture(x265_picture& pic)<br>         pic.planes[0] = buf[read % QUEUE_SIZE];<br>         pic.planes[1] = (char*)pic.planes[0] + pic.stride[0] * height;<br>         pic.planes[2] = (char*)pic.planes[1] + pic.stride[1] * (height >> x265_cli_csps[colorSpace].height[1]);<br>+#if ENABLE_ALPHA<br>         if (alphaAvailable)<br>         {<br>             pic.stride[3] = pic.stride[0] >> x265_cli_csps[colorSpace].width[3];<br>             pic.planes[3] = (char*)pic.planes[2] + pic.stride[2] * (height >> x265_cli_csps[colorSpace].height[2]);<br>         }<br>+#endif<br>         readCount.incr();<br>         return true;<br>     }<br>diff --git a/source/input/yuv.cpp b/source/input/yuv.cpp<br>index 670dae1ab..878075ec8 100644<br>--- a/source/input/yuv.cpp<br>+++ b/source/input/yuv.cpp<br>@@ -212,11 +212,13 @@ bool YUVInput::readPicture(x265_picture& pic)<br>         pic.planes[0] = buf[read % QUEUE_SIZE];<br>         pic.planes[1] = (char*)pic.planes[0] + pic.stride[0] * height;<br>         pic.planes[2] = (char*)pic.planes[1] + pic.stride[1] * (height >> x265_cli_csps[colorSpace].height[1]);<br>+#if ENABLE_ALPHA<br>         if (alphaAvailable)<br>         {<br>             pic.stride[3] = pic.stride[0] >> x265_cli_csps[colorSpace].width[3];<br>             pic.planes[3] = (char*)pic.planes[2] + pic.stride[2] * (height >> x265_cli_csps[colorSpace].height[2]);<br>         }<br>+#endif<br>         readCount.incr();<br>         return true;<br>     }<br>diff --git a/source/x265.h b/source/x265.h<br>index 48ec30bc7..e994ea3e2 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -623,7 +623,11 @@ typedef enum<br> #define X265_MAX_GOP_LENGTH 16<br> #define MAX_T_LAYERS 7<br> <br>+#if ENABLE_ALPHA<br> #define MAX_SCALABLE_LAYERS     2<br>+#else<br>+#define MAX_SCALABLE_LAYERS     1<br>+#endif<br> <br> #define X265_IPRATIO_STRENGTH   1.43<br> <br>diff --git a/source/x265cli.cpp b/source/x265cli.cpp<br>index ce7af9533..070011cf0 100755<br>--- a/source/x265cli.cpp<br>+++ b/source/x265cli.cpp<br>@@ -374,7 +374,9 @@ namespace X265_NS {<br>         H0("   --[no-]frame-dup              Enable Frame duplication. Default %s\n", OPT(param->bEnableFrameDuplication));<br>         H0("   --dup-threshold <integer>     PSNR threshold for Frame duplication. Default %d\n", param->dupThreshold);<br>         H0("   --[no-]mcstf                  Enable GOP based temporal filter. Default %d\n", param->bEnableTemporalFilter);<br>+#if ENABLE_ALPHA<br>         H0("   --alpha                       Enable alpha channel support. Default %d\n", param->bEnableAlpha);<br>+#endif<br> #ifdef SVT_HEVC<br>         H0("   --[no]svt                     Enable SVT HEVC encoder %s\n", OPT(param->bEnableSvtHevc));<br>         H0("   --[no-]svt-hme                Enable Hierarchial motion estimation(HME) in SVT HEVC encoder \n");<br>diff --git a/source/x265cli.h b/source/x265cli.h<br>index b4e91a137..9bdaba0f3 100644<br>--- a/source/x265cli.h<br>+++ b/source/x265cli.h<br>@@ -358,7 +358,9 @@ static const struct option long_options[] =<br>     { "dup-threshold", required_argument, NULL, 0 },<br>     { "mcstf",                 no_argument, NULL, 0 },<br>     { "no-mcstf",              no_argument, NULL, 0 },<br>+#if ENABLE_ALPHA<br>     { "alpha",                 no_argument, NULL, 0 },<br>+#endif<br> #ifdef SVT_HEVC<br>     { "svt",     no_argument, NULL, 0 },<br>     { "no-svt",  no_argument, NULL, 0 },<br>-- <br>2.36.0.windows.1<br><br></div>