<div dir="ltr">From bd724606c1d75491b9789aa77ba13b9c999a6c3c Mon Sep 17 00:00:00 2001<br>From: AnusuyaKumarasamy <<a href="mailto:anusuya.kumarasamy@multicorewareinc.com">anusuya.kumarasamy@multicorewareinc.com</a>><br>Date: Tue, 2 Jul 2024 14:47:32 +0530<br>Subject: [PATCH] Add support for parsing YUVA input<br><br>---<br> source/abrEncApp.cpp       |  7 +++++<br> source/common/picyuv.cpp   | 64 +++++++++++++++++++++++++++-----------<br> source/common/picyuv.h     |  2 +-<br> source/encoder/encoder.cpp |  4 ++-<br> source/input/input.cpp     |  6 ++--<br> source/input/input.h       |  2 +-<br> source/input/y4m.cpp       | 10 ++++--<br> source/input/y4m.h         |  4 ++-<br> source/input/yuv.cpp       | 10 ++++--<br> source/input/yuv.h         |  4 ++-<br> source/x265.h              | 10 +++---<br> source/x265cli.cpp         |  3 +-<br> 12 files changed, 90 insertions(+), 36 deletions(-)<br><br>diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp<br>index 94644a1c0..d8b9f8e3b 100644<br>--- a/source/abrEncApp.cpp<br>+++ b/source/abrEncApp.cpp<br>@@ -499,6 +499,7 @@ ret:<br>             pic->planes[0] = srcPic->planes[0];<br>             pic->planes[1] = srcPic->planes[1];<br>             pic->planes[2] = srcPic->planes[2];<br>+            pic->planes[3] = srcPic->planes[3];<br>             if (isAbrLoad)<br>                 pic->analysisData = *analysisData;<br>             return true;<br>@@ -1097,6 +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 (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>                 m_parentEnc->m_parent->m_picWriteCnt[m_id].incr();<br>             }<br>             else<br>diff --git a/source/common/picyuv.cpp b/source/common/picyuv.cpp<br>index 58426a613..8e0b44455 100644<br>--- a/source/common/picyuv.cpp<br>+++ b/source/common/picyuv.cpp<br>@@ -258,7 +258,7 @@ void PicYuv::destroy()<br> <br> /* Copy pixels from an x265_picture into internal PicYuv instance.<br>  * Shift pixels as necessary, mask off bits above X265_DEPTH for safety. */<br>-void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param& param, int padx, int pady)<br>+void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param& param, int padx, int pady, bool isBase)<br> {<br>     /* m_picWidth is the width that is being encoded, padx indicates how many<br>      * of those pixels are padding to reach multiple of MinCU(4) size.<br>@@ -321,34 +321,62 @@ void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param& param, i<br> #else /* Case for (X265_DEPTH == 8) */<br>             // TODO: Does we need this path? may merge into above in future<br>         {<br>-            pixel *yPixel = m_picOrg[0];<br>-            uint8_t *yChar = (uint8_t*)pic.planes[0];<br>-<br>-            for (int r = 0; r < height; r++)<br>+            if (isBase)<br>             {<br>-                memcpy(yPixel, yChar, width * sizeof(pixel));<br>+                pixel *yPixel = m_picOrg[0];<br>+                uint8_t *yChar = (uint8_t*)pic.planes[0];<br> <br>-                yPixel += m_stride;<br>-                yChar += pic.stride[0] / sizeof(*yChar);<br>-            }<br>+                for (int r = 0; r < height; r++)<br>+                {<br>+                    memcpy(yPixel, yChar, width * sizeof(pixel));<br> <br>-            if (param.internalCsp != X265_CSP_I400)<br>+                    yPixel += m_stride;<br>+                    yChar += pic.stride[0] / sizeof(*yChar);<br>+                }<br>+<br>+                if (param.internalCsp != X265_CSP_I400)<br>+                {<br>+                    pixel *uPixel = m_picOrg[1];<br>+                    pixel *vPixel = m_picOrg[2];<br>+<br>+                    uint8_t *uChar = (uint8_t*)pic.planes[1];<br>+                    uint8_t *vChar = (uint8_t*)pic.planes[2];<br>+<br>+                    for (int r = 0; r < height >> m_vChromaShift; r++)<br>+                    {<br>+                        memcpy(uPixel, uChar, (width >> m_hChromaShift) * sizeof(pixel));<br>+                        memcpy(vPixel, vChar, (width >> m_hChromaShift) * sizeof(pixel));<br>+<br>+                        uPixel += m_strideC;<br>+                        vPixel += m_strideC;<br>+                        uChar += pic.stride[1] / sizeof(*uChar);<br>+                        vChar += pic.stride[2] / sizeof(*vChar);<br>+                    }<br>+                }<br>+            }<br>+            if (!isBase && param.bEnableAlpha)<br>             {<br>-                pixel *uPixel = m_picOrg[1];<br>-                pixel *vPixel = m_picOrg[2];<br>+                pixel* aPixel = m_picOrg[0];<br>+                uint8_t* aChar = (uint8_t*)pic.planes[3];<br> <br>-                uint8_t *uChar = (uint8_t*)pic.planes[1];<br>-                uint8_t *vChar = (uint8_t*)pic.planes[2];<br>+                for (int r = 0; r < height; r++)<br>+                {<br>+                    memcpy(aPixel, aChar, width * sizeof(pixel));<br>+<br>+                    aPixel += m_stride;<br>+                    aChar += pic.stride[0] / sizeof(*aChar);<br>+                }<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>-                    memcpy(uPixel, uChar, (width >> m_hChromaShift) * sizeof(pixel));<br>-                    memcpy(vPixel, vChar, (width >> m_hChromaShift) * sizeof(pixel));<br>+                    memset(uPixel, 128, (width >> m_hChromaShift) * sizeof(pixel));<br>+                    memset(vPixel, 128, (width >> m_hChromaShift) * sizeof(pixel));<br> <br>                     uPixel += m_strideC;<br>                     vPixel += m_strideC;<br>-                    uChar += pic.stride[1] / sizeof(*uChar);<br>-                    vChar += pic.stride[2] / sizeof(*vChar);<br>                 }<br>             }<br>         }<br>diff --git a/source/common/picyuv.h b/source/common/picyuv.h<br>index ba448567a..ec9ff69c2 100644<br>--- a/source/common/picyuv.h<br>+++ b/source/common/picyuv.h<br>@@ -83,7 +83,7 @@ public:<br>     void  destroy();<br>     int   getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t picCsp);<br> <br>-    void  copyFromPicture(const x265_picture&, const x265_param& param, int padx, int pady);<br>+    void  copyFromPicture(const x265_picture&, const x265_param& param, int padx, int pady, bool isBase);<br>     void  copyFromFrame(PicYuv* source);<br> <br>     intptr_t getChromaAddrOffset(uint32_t ctuAddr, uint32_t absPartIdx) const { return m_cuOffsetC[ctuAddr] + m_buOffsetC[absPartIdx]; }<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 0f188e626..dc09be6dc 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -1359,6 +1359,8 @@ 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(m_param->bEnableAlpha)<br>+        dest->planes[3] = (char*)dest->planes[2] + src->stride[2] * (src->height >> x265_cli_csps[src->colorSpace].height[2]);<br> }<br> <br> bool Encoder::isFilterThisframe(uint8_t sliceTypeConfig, int curSliceType)<br>@@ -1642,7 +1644,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>         }<br> <br>         /* Copy input picture into a Frame and PicYuv, send to lookahead */<br>-        inFrame->m_fencPic->copyFromPicture(*inputPic, *m_param, m_sps.conformanceWindow.rightOffset, m_sps.conformanceWindow.bottomOffset);<br>+        inFrame->m_fencPic->copyFromPicture(*inputPic, *m_param, m_sps.conformanceWindow.rightOffset, m_sps.conformanceWindow.bottomOffset, true);<br> <br>         inFrame->m_poc       = ++m_pocLast;<br>         inFrame->m_userData  = inputPic->userData;<br>diff --git a/source/input/input.cpp b/source/input/input.cpp<br>index 32264212c..889c0ba5e 100644<br>--- a/source/input/input.cpp<br>+++ b/source/input/input.cpp<br>@@ -27,12 +27,12 @@<br> <br> using namespace X265_NS;<br> <br>-InputFile* InputFile::open(InputFileInfo& info, bool bForceY4m)<br>+InputFile* InputFile::open(InputFileInfo& info, bool bForceY4m, bool alpha)<br> {<br>     const char * s = strrchr(info.filename, '.');<br> <br>     if (bForceY4m || (s && !strcmp(s, ".y4m")))<br>-        return new Y4MInput(info);<br>+        return new Y4MInput(info, alpha);<br>     else<br>-        return new YUVInput(info);<br>+        return new YUVInput(info, alpha);<br> }<br>diff --git a/source/input/input.h b/source/input/input.h<br>index 7a001c9c5..96a5734c6 100644<br>--- a/source/input/input.h<br>+++ b/source/input/input.h<br>@@ -66,7 +66,7 @@ public:<br> <br>     InputFile()           {}<br> <br>-    static InputFile* open(InputFileInfo& info, bool bForceY4m);<br>+    static InputFile* open(InputFileInfo& info, bool bForceY4m, bool alpha);<br> <br>     virtual void startReader() = 0;<br> <br>diff --git a/source/input/y4m.cpp b/source/input/y4m.cpp<br>index bb55b6417..eedbf991c 100644<br>--- a/source/input/y4m.cpp<br>+++ b/source/input/y4m.cpp<br>@@ -40,13 +40,14 @@<br> using namespace X265_NS;<br> using namespace std;<br> static const char header[] = {'F','R','A','M','E'};<br>-Y4MInput::Y4MInput(InputFileInfo& info)<br>+Y4MInput::Y4MInput(InputFileInfo& info, bool alpha)<br> {<br>     for (int i = 0; i < QUEUE_SIZE; i++)<br>         buf[i] = NULL;<br> <br>     threadActive = false;<br>     colorSpace = info.csp;<br>+    alphaAvailable = alpha;<br>     sarWidth = info.sarWidth;<br>     sarHeight = info.sarHeight;<br>     width = info.width;<br>@@ -69,7 +70,7 @@ Y4MInput::Y4MInput(InputFileInfo& info)<br>     if (ifs && !ferror(ifs) && parseHeader())<br>     {<br>         int pixelbytes = depth > 8 ? 2 : 1;<br>-        for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)<br>+        for (int i = 0; i < x265_cli_csps[colorSpace].planes + alphaAvailable; i++)<br>         {<br>             int stride = (width >> x265_cli_csps[colorSpace].width[i]) * pixelbytes;<br>             framesize += (stride * (height >> x265_cli_csps[colorSpace].height[i]));<br>@@ -396,6 +397,11 @@ 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 (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>         readCount.incr();<br>         return true;<br>     }<br>diff --git a/source/input/y4m.h b/source/input/y4m.h<br>index f22938fb6..37992bb66 100644<br>--- a/source/input/y4m.h<br>+++ b/source/input/y4m.h<br>@@ -55,6 +55,8 @@ protected:<br> <br>     int colorSpace;<br> <br>+    bool alphaAvailable;<br>+<br>     bool threadActive;<br> <br>     ThreadSafeInteger readCount;<br>@@ -69,7 +71,7 @@ protected:<br> <br> public:<br> <br>-    Y4MInput(InputFileInfo& info);<br>+    Y4MInput(InputFileInfo& info, bool alpha);<br> <br>     virtual ~Y4MInput();<br>     void release();<br>diff --git a/source/input/yuv.cpp b/source/input/yuv.cpp<br>index 0856a7217..670dae1ab 100644<br>--- a/source/input/yuv.cpp<br>+++ b/source/input/yuv.cpp<br>@@ -40,7 +40,7 @@<br> using namespace X265_NS;<br> using namespace std;<br> <br>-YUVInput::YUVInput(InputFileInfo& info)<br>+YUVInput::YUVInput(InputFileInfo& info, bool alpha)<br> {<br>     for (int i = 0; i < QUEUE_SIZE; i++)<br>         buf[i] = NULL;<br>@@ -49,12 +49,13 @@ YUVInput::YUVInput(InputFileInfo& info)<br>     width = info.width;<br>     height = info.height;<br>     colorSpace = info.csp;<br>+    alphaAvailable = alpha;<br>     threadActive = false;<br>     ifs = NULL;<br> <br>     uint32_t pixelbytes = depth > 8 ? 2 : 1;<br>     framesize = 0;<br>-    for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)<br>+    for (int i = 0; i < x265_cli_csps[colorSpace].planes + alphaAvailable; i++)<br>     {<br>         uint32_t w = width >> x265_cli_csps[colorSpace].width[i];<br>         uint32_t h = height >> x265_cli_csps[colorSpace].height[i];<br>@@ -211,6 +212,11 @@ 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 (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>         readCount.incr();<br>         return true;<br>     }<br>diff --git a/source/input/yuv.h b/source/input/yuv.h<br>index c5e74f1e9..2c104a4cc 100644<br>--- a/source/input/yuv.h<br>+++ b/source/input/yuv.h<br>@@ -47,6 +47,8 @@ protected:<br> <br>     uint32_t framesize;<br> <br>+    bool alphaAvailable;<br>+<br>     bool threadActive;<br> <br>     ThreadSafeInteger readCount;<br>@@ -61,7 +63,7 @@ protected:<br> <br> public:<br> <br>-    YUVInput(InputFileInfo& info);<br>+    YUVInput(InputFileInfo& info, bool alpha);<br> <br>     virtual ~YUVInput();<br>     void release();<br>diff --git a/source/x265.h b/source/x265.h<br>index b6e410435..48ec30bc7 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -410,10 +410,10 @@ typedef struct x265_picture<br> <br>     /* Must be specified on input pictures, the number of planes is determined<br>      * by the colorSpace value */<br>-    void*   planes[3];<br>+    void*   planes[4];<br> <br>     /* Stride is the number of bytes between row starts */<br>-    int     stride[3];<br>+    int     stride[4];<br> <br>     /* Must be specified on input pictures. x265_picture_init() will set it to<br>      * the encoder's internal bit depth, but this field must describe the depth<br>@@ -623,13 +623,15 @@ typedef enum<br> #define X265_MAX_GOP_LENGTH 16<br> #define MAX_T_LAYERS 7<br> <br>+#define MAX_SCALABLE_LAYERS     2<br>+<br> #define X265_IPRATIO_STRENGTH   1.43<br> <br> typedef struct x265_cli_csp<br> {<br>     int planes;<br>-    int width[3];<br>-    int height[3];<br>+    int width[4];<br>+    int height[4];<br> } x265_cli_csp;<br> <br> static const x265_cli_csp x265_cli_csps[] =<br>diff --git a/source/x265cli.cpp b/source/x265cli.cpp<br>index 2f8a150d4..ce7af9533 100755<br>--- a/source/x265cli.cpp<br>+++ b/source/x265cli.cpp<br>@@ -832,8 +832,7 @@ namespace X265_NS {<br>         info.frameCount = 0;<br>         getParamAspectRatio(param, info.sarWidth, info.sarHeight);<br> <br>-<br>-        this->input = InputFile::open(info, this->bForceY4m);<br>+        this->input = InputFile::open(info, this->bForceY4m, param->bEnableAlpha);<br>         if (!this->input || this->input->isFail())<br>         {<br>             x265_log_file(param, X265_LOG_ERROR, "unable to open input file <%s>\n", inputfn);<br>-- <br>2.36.0.windows.1<br><br></div>