[x265] [PATCH Alpha 02/10] Add support for parsing YUVA input

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Mon Aug 5 10:53:15 UTC 2024


>From bd724606c1d75491b9789aa77ba13b9c999a6c3c Mon Sep 17 00:00:00 2001
From: AnusuyaKumarasamy <anusuya.kumarasamy at multicorewareinc.com>
Date: Tue, 2 Jul 2024 14:47:32 +0530
Subject: [PATCH] Add support for parsing YUVA input

---
 source/abrEncApp.cpp       |  7 +++++
 source/common/picyuv.cpp   | 64 +++++++++++++++++++++++++++-----------
 source/common/picyuv.h     |  2 +-
 source/encoder/encoder.cpp |  4 ++-
 source/input/input.cpp     |  6 ++--
 source/input/input.h       |  2 +-
 source/input/y4m.cpp       | 10 ++++--
 source/input/y4m.h         |  4 ++-
 source/input/yuv.cpp       | 10 ++++--
 source/input/yuv.h         |  4 ++-
 source/x265.h              | 10 +++---
 source/x265cli.cpp         |  3 +-
 12 files changed, 90 insertions(+), 36 deletions(-)

diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp
index 94644a1c0..d8b9f8e3b 100644
--- a/source/abrEncApp.cpp
+++ b/source/abrEncApp.cpp
@@ -499,6 +499,7 @@ ret:
             pic->planes[0] = srcPic->planes[0];
             pic->planes[1] = srcPic->planes[1];
             pic->planes[2] = srcPic->planes[2];
+            pic->planes[3] = srcPic->planes[3];
             if (isAbrLoad)
                 pic->analysisData = *analysisData;
             return true;
@@ -1097,6 +1098,12 @@ ret:
                 memcpy(dest->planes[0], src->planes[0], src->framesize *
sizeof(char));
                 dest->planes[1] = (char*)dest->planes[0] + src->stride[0]
* src->height;
                 dest->planes[2] = (char*)dest->planes[1] + src->stride[1]
* (src->height >> x265_cli_csps[src->colorSpace].height[1]);
+
+                if (m_parentEnc->m_param->bEnableAlpha)
+                {
+                    dest->planes[3] = (char*)dest->planes[2] +
src->stride[2] * (src->height >> x265_cli_csps[src->colorSpace].height[2]);
+                }
+
                 m_parentEnc->m_parent->m_picWriteCnt[m_id].incr();
             }
             else
diff --git a/source/common/picyuv.cpp b/source/common/picyuv.cpp
index 58426a613..8e0b44455 100644
--- a/source/common/picyuv.cpp
+++ b/source/common/picyuv.cpp
@@ -258,7 +258,7 @@ void PicYuv::destroy()

 /* Copy pixels from an x265_picture into internal PicYuv instance.
  * Shift pixels as necessary, mask off bits above X265_DEPTH for safety. */
-void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param&
param, int padx, int pady)
+void PicYuv::copyFromPicture(const x265_picture& pic, const x265_param&
param, int padx, int pady, bool isBase)
 {
     /* m_picWidth is the width that is being encoded, padx indicates how
many
      * of those pixels are padding to reach multiple of MinCU(4) size.
@@ -321,34 +321,62 @@ void PicYuv::copyFromPicture(const x265_picture& pic,
const x265_param& param, i
 #else /* Case for (X265_DEPTH == 8) */
             // 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];
-
-            for (int r = 0; r < height; r++)
+            if (isBase)
             {
-                memcpy(yPixel, yChar, width * sizeof(pixel));
+                pixel *yPixel = m_picOrg[0];
+                uint8_t *yChar = (uint8_t*)pic.planes[0];

-                yPixel += m_stride;
-                yChar += pic.stride[0] / sizeof(*yChar);
-            }
+                for (int r = 0; r < height; r++)
+                {
+                    memcpy(yPixel, yChar, width * sizeof(pixel));

-            if (param.internalCsp != X265_CSP_I400)
+                    yPixel += m_stride;
+                    yChar += pic.stride[0] / sizeof(*yChar);
+                }
+
+                if (param.internalCsp != X265_CSP_I400)
+                {
+                    pixel *uPixel = m_picOrg[1];
+                    pixel *vPixel = m_picOrg[2];
+
+                    uint8_t *uChar = (uint8_t*)pic.planes[1];
+                    uint8_t *vChar = (uint8_t*)pic.planes[2];
+
+                    for (int r = 0; r < height >> m_vChromaShift; r++)
+                    {
+                        memcpy(uPixel, uChar, (width >> m_hChromaShift) *
sizeof(pixel));
+                        memcpy(vPixel, vChar, (width >> m_hChromaShift) *
sizeof(pixel));
+
+                        uPixel += m_strideC;
+                        vPixel += m_strideC;
+                        uChar += pic.stride[1] / sizeof(*uChar);
+                        vChar += pic.stride[2] / sizeof(*vChar);
+                    }
+                }
+            }
+            if (!isBase && param.bEnableAlpha)
             {
-                pixel *uPixel = m_picOrg[1];
-                pixel *vPixel = m_picOrg[2];
+                pixel* aPixel = m_picOrg[0];
+                uint8_t* aChar = (uint8_t*)pic.planes[3];

-                uint8_t *uChar = (uint8_t*)pic.planes[1];
-                uint8_t *vChar = (uint8_t*)pic.planes[2];
+                for (int r = 0; r < height; r++)
+                {
+                    memcpy(aPixel, aChar, width * sizeof(pixel));
+
+                    aPixel += m_stride;
+                    aChar += pic.stride[0] / sizeof(*aChar);
+                }
+
+                pixel* uPixel = m_picOrg[1];
+                pixel* vPixel = m_picOrg[2];

                 for (int r = 0; r < height >> m_vChromaShift; r++)
                 {
-                    memcpy(uPixel, uChar, (width >> m_hChromaShift) *
sizeof(pixel));
-                    memcpy(vPixel, vChar, (width >> m_hChromaShift) *
sizeof(pixel));
+                    memset(uPixel, 128, (width >> m_hChromaShift) *
sizeof(pixel));
+                    memset(vPixel, 128, (width >> m_hChromaShift) *
sizeof(pixel));

                     uPixel += m_strideC;
                     vPixel += m_strideC;
-                    uChar += pic.stride[1] / sizeof(*uChar);
-                    vChar += pic.stride[2] / sizeof(*vChar);
                 }
             }
         }
diff --git a/source/common/picyuv.h b/source/common/picyuv.h
index ba448567a..ec9ff69c2 100644
--- a/source/common/picyuv.h
+++ b/source/common/picyuv.h
@@ -83,7 +83,7 @@ public:
     void  destroy();
     int   getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t
picCsp);

-    void  copyFromPicture(const x265_picture&, const x265_param& param,
int padx, int pady);
+    void  copyFromPicture(const x265_picture&, const x265_param& param,
int padx, int pady, bool isBase);
     void  copyFromFrame(PicYuv* source);

     intptr_t getChromaAddrOffset(uint32_t ctuAddr, uint32_t absPartIdx)
const { return m_cuOffsetC[ctuAddr] + m_buOffsetC[absPartIdx]; }
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 0f188e626..dc09be6dc 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1359,6 +1359,8 @@ void Encoder::copyPicture(x265_picture *dest, const
x265_picture *src)
     memcpy(dest->planes[0], src->planes[0], src->framesize * sizeof(char));
     dest->planes[1] = (char*)dest->planes[0] + src->stride[0] *
src->height;
     dest->planes[2] = (char*)dest->planes[1] + src->stride[1] *
(src->height >> x265_cli_csps[src->colorSpace].height[1]);
+    if(m_param->bEnableAlpha)
+        dest->planes[3] = (char*)dest->planes[2] + src->stride[2] *
(src->height >> x265_cli_csps[src->colorSpace].height[2]);
 }

 bool Encoder::isFilterThisframe(uint8_t sliceTypeConfig, int curSliceType)
@@ -1642,7 +1644,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
         }

         /* Copy input picture into a Frame and PicYuv, send to lookahead */
-        inFrame->m_fencPic->copyFromPicture(*inputPic, *m_param,
m_sps.conformanceWindow.rightOffset, m_sps.conformanceWindow.bottomOffset);
+        inFrame->m_fencPic->copyFromPicture(*inputPic, *m_param,
m_sps.conformanceWindow.rightOffset, m_sps.conformanceWindow.bottomOffset,
true);

         inFrame->m_poc       = ++m_pocLast;
         inFrame->m_userData  = inputPic->userData;
diff --git a/source/input/input.cpp b/source/input/input.cpp
index 32264212c..889c0ba5e 100644
--- a/source/input/input.cpp
+++ b/source/input/input.cpp
@@ -27,12 +27,12 @@

 using namespace X265_NS;

-InputFile* InputFile::open(InputFileInfo& info, bool bForceY4m)
+InputFile* InputFile::open(InputFileInfo& info, bool bForceY4m, bool alpha)
 {
     const char * s = strrchr(info.filename, '.');

     if (bForceY4m || (s && !strcmp(s, ".y4m")))
-        return new Y4MInput(info);
+        return new Y4MInput(info, alpha);
     else
-        return new YUVInput(info);
+        return new YUVInput(info, alpha);
 }
diff --git a/source/input/input.h b/source/input/input.h
index 7a001c9c5..96a5734c6 100644
--- a/source/input/input.h
+++ b/source/input/input.h
@@ -66,7 +66,7 @@ public:

     InputFile()           {}

-    static InputFile* open(InputFileInfo& info, bool bForceY4m);
+    static InputFile* open(InputFileInfo& info, bool bForceY4m, bool
alpha);

     virtual void startReader() = 0;

diff --git a/source/input/y4m.cpp b/source/input/y4m.cpp
index bb55b6417..eedbf991c 100644
--- a/source/input/y4m.cpp
+++ b/source/input/y4m.cpp
@@ -40,13 +40,14 @@
 using namespace X265_NS;
 using namespace std;
 static const char header[] = {'F','R','A','M','E'};
-Y4MInput::Y4MInput(InputFileInfo& info)
+Y4MInput::Y4MInput(InputFileInfo& info, bool alpha)
 {
     for (int i = 0; i < QUEUE_SIZE; i++)
         buf[i] = NULL;

     threadActive = false;
     colorSpace = info.csp;
+    alphaAvailable = alpha;
     sarWidth = info.sarWidth;
     sarHeight = info.sarHeight;
     width = info.width;
@@ -69,7 +70,7 @@ Y4MInput::Y4MInput(InputFileInfo& info)
     if (ifs && !ferror(ifs) && parseHeader())
     {
         int pixelbytes = depth > 8 ? 2 : 1;
-        for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
+        for (int i = 0; i < x265_cli_csps[colorSpace].planes +
alphaAvailable; i++)
         {
             int stride = (width >> x265_cli_csps[colorSpace].width[i]) *
pixelbytes;
             framesize += (stride * (height >>
x265_cli_csps[colorSpace].height[i]));
@@ -396,6 +397,11 @@ bool Y4MInput::readPicture(x265_picture& pic)
         pic.planes[0] = buf[read % QUEUE_SIZE];
         pic.planes[1] = (char*)pic.planes[0] + pic.stride[0] * height;
         pic.planes[2] = (char*)pic.planes[1] + pic.stride[1] * (height >>
x265_cli_csps[colorSpace].height[1]);
+        if (alphaAvailable)
+        {
+            pic.stride[3] = pic.stride[0] >>
x265_cli_csps[colorSpace].width[3];
+            pic.planes[3] = (char*)pic.planes[2] + pic.stride[2] * (height
>> x265_cli_csps[colorSpace].height[2]);
+        }
         readCount.incr();
         return true;
     }
diff --git a/source/input/y4m.h b/source/input/y4m.h
index f22938fb6..37992bb66 100644
--- a/source/input/y4m.h
+++ b/source/input/y4m.h
@@ -55,6 +55,8 @@ protected:

     int colorSpace;

+    bool alphaAvailable;
+
     bool threadActive;

     ThreadSafeInteger readCount;
@@ -69,7 +71,7 @@ protected:

 public:

-    Y4MInput(InputFileInfo& info);
+    Y4MInput(InputFileInfo& info, bool alpha);

     virtual ~Y4MInput();
     void release();
diff --git a/source/input/yuv.cpp b/source/input/yuv.cpp
index 0856a7217..670dae1ab 100644
--- a/source/input/yuv.cpp
+++ b/source/input/yuv.cpp
@@ -40,7 +40,7 @@
 using namespace X265_NS;
 using namespace std;

-YUVInput::YUVInput(InputFileInfo& info)
+YUVInput::YUVInput(InputFileInfo& info, bool alpha)
 {
     for (int i = 0; i < QUEUE_SIZE; i++)
         buf[i] = NULL;
@@ -49,12 +49,13 @@ YUVInput::YUVInput(InputFileInfo& info)
     width = info.width;
     height = info.height;
     colorSpace = info.csp;
+    alphaAvailable = alpha;
     threadActive = false;
     ifs = NULL;

     uint32_t pixelbytes = depth > 8 ? 2 : 1;
     framesize = 0;
-    for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
+    for (int i = 0; i < x265_cli_csps[colorSpace].planes + alphaAvailable;
i++)
     {
         uint32_t w = width >> x265_cli_csps[colorSpace].width[i];
         uint32_t h = height >> x265_cli_csps[colorSpace].height[i];
@@ -211,6 +212,11 @@ bool YUVInput::readPicture(x265_picture& pic)
         pic.planes[0] = buf[read % QUEUE_SIZE];
         pic.planes[1] = (char*)pic.planes[0] + pic.stride[0] * height;
         pic.planes[2] = (char*)pic.planes[1] + pic.stride[1] * (height >>
x265_cli_csps[colorSpace].height[1]);
+        if (alphaAvailable)
+        {
+            pic.stride[3] = pic.stride[0] >>
x265_cli_csps[colorSpace].width[3];
+            pic.planes[3] = (char*)pic.planes[2] + pic.stride[2] * (height
>> x265_cli_csps[colorSpace].height[2]);
+        }
         readCount.incr();
         return true;
     }
diff --git a/source/input/yuv.h b/source/input/yuv.h
index c5e74f1e9..2c104a4cc 100644
--- a/source/input/yuv.h
+++ b/source/input/yuv.h
@@ -47,6 +47,8 @@ protected:

     uint32_t framesize;

+    bool alphaAvailable;
+
     bool threadActive;

     ThreadSafeInteger readCount;
@@ -61,7 +63,7 @@ protected:

 public:

-    YUVInput(InputFileInfo& info);
+    YUVInput(InputFileInfo& info, bool alpha);

     virtual ~YUVInput();
     void release();
diff --git a/source/x265.h b/source/x265.h
index b6e410435..48ec30bc7 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -410,10 +410,10 @@ typedef struct x265_picture

     /* Must be specified on input pictures, the number of planes is
determined
      * by the colorSpace value */
-    void*   planes[3];
+    void*   planes[4];

     /* Stride is the number of bytes between row starts */
-    int     stride[3];
+    int     stride[4];

     /* Must be specified on input pictures. x265_picture_init() will set
it to
      * the encoder's internal bit depth, but this field must describe the
depth
@@ -623,13 +623,15 @@ typedef enum
 #define X265_MAX_GOP_LENGTH 16
 #define MAX_T_LAYERS 7

+#define MAX_SCALABLE_LAYERS     2
+
 #define X265_IPRATIO_STRENGTH   1.43

 typedef struct x265_cli_csp
 {
     int planes;
-    int width[3];
-    int height[3];
+    int width[4];
+    int height[4];
 } x265_cli_csp;

 static const x265_cli_csp x265_cli_csps[] =
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 2f8a150d4..ce7af9533 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -832,8 +832,7 @@ namespace X265_NS {
         info.frameCount = 0;
         getParamAspectRatio(param, info.sarWidth, info.sarHeight);

-
-        this->input = InputFile::open(info, this->bForceY4m);
+        this->input = InputFile::open(info, this->bForceY4m,
param->bEnableAlpha);
         if (!this->input || this->input->isFail())
         {
             x265_log_file(param, X265_LOG_ERROR, "unable to open input
file <%s>\n", inputfn);
-- 
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240805/c9365d68/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-Add-support-for-parsing-YUVA-input.patch
Type: application/octet-stream
Size: 14714 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240805/c9365d68/attachment-0001.obj>


More information about the x265-devel mailing list