[x265] [PATCH MV-HEVC 09/10] Add support for parsing spatial video with side-by-side and top-bottom format

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Tue Aug 6 10:50:08 UTC 2024


>From c867087e91c890d96380b09b0033ab584a17f247 Mon Sep 17 00:00:00 2001
From: AnusuyaKumarasamy <anusuya.kumarasamy at multicorewareinc.com>
Date: Tue, 30 Jul 2024 15:29:14 +0530
Subject: [PATCH] Add support for parsing spatial video with side-by-side and
 top-bottom format

---
 source/abrEncApp.cpp       | 12 ++++++++----
 source/common/param.cpp    |  5 +++++
 source/common/picyuv.cpp   | 14 ++++++++++----
 source/encoder/encoder.cpp |  6 +-----
 source/input/input.cpp     |  4 ++--
 source/input/input.h       |  2 +-
 source/input/yuv.cpp       | 12 ++++++------
 source/input/yuv.h         |  2 +-
 source/x265.h              |  2 ++
 source/x265cli.cpp         | 16 +++++++++-------
 source/x265cli.h           |  1 +
 11 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp
index b14db5900..3460dfe78 100644
--- a/source/abrEncApp.cpp
+++ b/source/abrEncApp.cpp
@@ -558,6 +558,7 @@ ret:
             pic->planes[1] = srcPic->planes[1];
             pic->planes[2] = srcPic->planes[2];
             pic->planes[3] = srcPic->planes[3];
+            pic->format = srcPic->format;
             if (isAbrLoad)
                 pic->analysisData = *analysisData;
             return true;
@@ -1150,9 +1151,10 @@ ret:
                 read =
m_parentEnc->m_parent->m_picIdxReadCnt[m_id][writeIdx].waitForChange(read);
             }

-            for (int view = 0; view < m_parentEnc->m_param->numViews;
view++)
+            for (int view = 0; view < m_parentEnc->m_param->numViews -
!!m_parentEnc->m_param->format; view++)
             {
                 x265_picture* dest =
m_parentEnc->m_parent->m_inputPicBuffer[view][writeIdx];
+                src->format = m_parentEnc->m_param->format;
                 if (m_input[view]->readPicture(*src))
                 {
                     dest->poc = src->poc;
@@ -1169,20 +1171,22 @@ ret:
                     dest->stride[0] = src->stride[0];
                     dest->stride[1] = src->stride[1];
                     dest->stride[2] = src->stride[2];
+                    dest->format = src->format;

                     if (!dest->planes[0])
                         dest->planes[0] = X265_MALLOC(char,
dest->framesize);

                     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]);
+                    int height = (src->height * (src->format == 2 ? 2 :
1));
+                    dest->planes[1] = (char*)dest->planes[0] +
src->stride[0] * height;
+                    dest->planes[2] = (char*)dest->planes[1] +
src->stride[1] * (height >> x265_cli_csps[src->colorSpace].height[1]);
 #if ENABLE_ALPHA
                     if (m_parentEnc->m_param->numScalableLayers > 1)
                     {
                         dest->planes[3] = (char*)dest->planes[2] +
src->stride[2] * (src->height >> x265_cli_csps[src->colorSpace].height[2]);
                     }
 #endif
-                    if (view == m_parentEnc->m_param->numViews - 1)
+                    if (view == m_parentEnc->m_param->numViews - 1 -
!!m_parentEnc->m_param->format)
                         m_parentEnc->m_parent->m_picWriteCnt[m_id].incr();
                 }
                 else
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 8b7d268d2..c310a7b4c 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -406,6 +406,7 @@ void x265_param_default(x265_param* param)

     /* Multi-View Encoding*/
     param->numViews = 1;
+    param->format = 1;

     param->numLayers = 1;
 }
@@ -1464,6 +1465,8 @@ int x265_param_parse(x265_param* p, const char* name,
const char* value)
         }
 #endif
 #if ENABLE_MULTIVIEW
+        OPT("format")
+            p->format = atoi(value);
         OPT("num-views")
         {
             p->numViews = atoi(value);
@@ -2389,6 +2392,7 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
 #endif
 #if ENABLE_MULTIVIEW
     s += sprintf(s, " num-views=%d", p->numViews);
+    s += sprintf(s, " format=%d", p->format);
 #endif
     BOOL(p->bEnableSBRC, "sbrc");
 #undef BOOL
@@ -2917,6 +2921,7 @@ void x265_copy_params(x265_param* dst, x265_param*
src)
 #endif
 #if ENABLE_MULTIVIEW
     dst->numViews = src->numViews;
+    dst->format = src->format;
 #endif
     dst->numLayers = src->numLayers;

diff --git a/source/common/picyuv.cpp b/source/common/picyuv.cpp
index bd5690d3e..e4911b19a 100644
--- a/source/common/picyuv.cpp
+++ b/source/common/picyuv.cpp
@@ -321,10 +321,13 @@ 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
         {
-            if (isBase)
+            if (isBase || param.numViews > 1)
             {
+                int offsetX, offsetY;
+                offsetX = (!isBase && pic.format == 1 ? width : 0);
+                offsetY = (!isBase && pic.format == 2 ? width * height :
0);
                 pixel *yPixel = m_picOrg[0];
-                uint8_t *yChar = (uint8_t*)pic.planes[0];
+                uint8_t* yChar = (uint8_t*)pic.planes[0] + offsetX +
offsetY;

                 for (int r = 0; r < height; r++)
                 {
@@ -336,11 +339,14 @@ void PicYuv::copyFromPicture(const x265_picture& pic,
const x265_param& param, i

                 if (param.internalCsp != X265_CSP_I400)
                 {
+                    offsetX = offsetX >> m_hChromaShift;
+                    offsetY = offsetY >> (m_hChromaShift * 2);
+
                     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];
+                    uint8_t* uChar = (uint8_t*)pic.planes[1] + offsetX +
offsetY;
+                    uint8_t* vChar = (uint8_t*)pic.planes[2] + offsetX +
offsetY;

                     for (int r = 0; r < height >> m_vChromaShift; r++)
                     {
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 7f4e4b3eb..5fb822c8a 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1701,11 +1701,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
             }

             /* Copy input picture into a Frame and PicYuv, send to
lookahead */
-#if ENABLE_ALPHA
-            inFrame[layer]->m_fencPic->copyFromPicture(*inputPic[layer],
*m_param, m_sps.conformanceWindow.rightOffset,
m_sps.conformanceWindow.bottomOffset, !layer);
-#else
-            inFrame[layer]->m_fencPic->copyFromPicture(*inputPic[layer],
*m_param, m_sps.conformanceWindow.rightOffset,
m_sps.conformanceWindow.bottomOffset);
-#endif
+
 inFrame[layer]->m_fencPic->copyFromPicture(*inputPic[!m_param->format ?
layer : 0], *m_param, m_sps.conformanceWindow.rightOffset,
m_sps.conformanceWindow.bottomOffset, !layer);

             inFrame[layer]->m_poc = (!layer) ? (++m_pocLast) : m_pocLast;
             inFrame[layer]->m_userData = inputPic[0]->userData;
diff --git a/source/input/input.cpp b/source/input/input.cpp
index 889c0ba5e..43734c978 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, bool alpha)
+InputFile* InputFile::open(InputFileInfo& info, bool bForceY4m, bool
alpha, int format)
 {
     const char * s = strrchr(info.filename, '.');

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

     InputFile()           {}

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

     virtual void startReader() = 0;

diff --git a/source/input/yuv.cpp b/source/input/yuv.cpp
index 878075ec8..65d696c48 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, bool alpha)
+YUVInput::YUVInput(InputFileInfo& info, bool alpha, int format)
 {
     for (int i = 0; i < QUEUE_SIZE; i++)
         buf[i] = NULL;
@@ -57,8 +57,8 @@ YUVInput::YUVInput(InputFileInfo& info, bool alpha)
     framesize = 0;
     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];
+        int32_t w = (width * (format == 1 ? 2 : 1)) >>
x265_cli_csps[colorSpace].width[i];
+        uint32_t h = (height * (format == 2 ? 2 : 1)) >>
x265_cli_csps[colorSpace].height[i];
         framesize += w * h * pixelbytes;
     }

@@ -206,12 +206,12 @@ bool YUVInput::readPicture(x265_picture& pic)
         pic.framesize = framesize;
         pic.height = height;
         pic.width = width;
-        pic.stride[0] = width * pixelbytes;
+        pic.stride[0] = width * pixelbytes * (pic.format == 1 ? 2 : 1);
         pic.stride[1] = pic.stride[0] >>
x265_cli_csps[colorSpace].width[1];
         pic.stride[2] = pic.stride[0] >>
x265_cli_csps[colorSpace].width[2];
         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]);
+        pic.planes[1] = (char*)pic.planes[0] + pic.stride[0] * (height *
(pic.format == 2 ? 2 : 1));
+        pic.planes[2] = (char*)pic.planes[1] + pic.stride[1] * ((height *
(pic.format == 2 ? 2 : 1)) >> x265_cli_csps[colorSpace].height[1]);
 #if ENABLE_ALPHA
         if (alphaAvailable)
         {
diff --git a/source/input/yuv.h b/source/input/yuv.h
index 2c104a4cc..8cab97d74 100644
--- a/source/input/yuv.h
+++ b/source/input/yuv.h
@@ -63,7 +63,7 @@ protected:

 public:

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

     virtual ~YUVInput();
     void release();
diff --git a/source/x265.h b/source/x265.h
index 1b685e3c1..fb06372af 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -494,6 +494,7 @@ typedef struct x265_picture
     int    width;

     int   layerID;
+    int    format;
 } x265_picture;

 typedef enum
@@ -2304,6 +2305,7 @@ typedef struct x265_param

     /*Multi View Encoding*/
     int      numViews;
+    int      format;

     int      numLayers;
 } x265_param;
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index cd42a3bfa..c0c70b78b 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -379,6 +379,7 @@ namespace X265_NS {
 #endif
 #if ENABLE_MULTIVIEW
         H0("   --num-views                   Number of Views for Multiview
Encoding. Default %d\n", param->numViews);
+        H0("   --format                      Format of the input video 0 :
normal, 1 : side-by-side, 2 : over-under  Default %d\n", param->format);
         H0("   --multiview-config            Configuration file for
Multiview Encoding\n");
 #endif
 #ifdef SVT_HEVC
@@ -864,7 +865,7 @@ namespace X265_NS {
         }
 #endif
         InputFileInfo info[MAX_VIEWS];
-        for (int i = 0; i < param->numViews; i++)
+        for (int i = 0; i < param->numViews - !!param->format; i++)
         {
             info[i].filename = inputfn[i];
             info[i].depth = inputBitDepth;
@@ -879,7 +880,7 @@ namespace X265_NS {
             info[i].frameCount = 0;
             getParamAspectRatio(param, info[i].sarWidth,
info[i].sarHeight);

-            this->input[i] = InputFile::open(info[i], this->bForceY4m,
param->numScalableLayers > 1);
+            this->input[i] = InputFile::open(info[i], this->bForceY4m,
param->numScalableLayers > 1, param->format);
             if (!this->input[i] || this->input[i]->isFail())
             {
                 x265_log_file(param, X265_LOG_ERROR, "unable to open input
file <%s>\n", inputfn[i]);
@@ -957,11 +958,11 @@ namespace X265_NS {
             else
                 sprintf(buf + p, " frames %u - %d of %d", this->seek,
this->seek + this->framesToBeEncoded - 1, info[0].frameCount);

-            for (int view = 0; view < param->numViews; view++)
+            for (int view = 0; view < param->numViews - !!param->format;
view++)
                 general_log(param, input[view]->getName(), X265_LOG_INFO,
"%s\n", buf);
         }

-        for (int view = 0; view < param->numViews; view++)
+        for (int view = 0; view < param->numViews - !!param->format;
view++)
             this->input[view]->startReader();

         if (reconfn[0])
@@ -982,7 +983,7 @@ namespace X265_NS {
                 }
             }
 #endif
-            for (int i = 0; i < param->numLayers; i++)
+            for (int i = 0; i < param->numLayers - !!param->format; i++)
             {
                 this->recon[i] = ReconFile::open(reconfn[i],
param->sourceWidth, param->sourceHeight, reconFileBitDepth,
                     param->fpsNum, param->fpsDenom, param->internalCsp,
param->sourceBitDepth);
@@ -1387,6 +1388,7 @@ namespace X265_NS {
 #define OPT(STR) else if (!strcmp(name, STR))
                     if (0);
                     OPT("num-views") param->numViews = x265_atoi(optarg,
bError);
+                    OPT("format") param->format = x265_atoi(optarg,
bError);
                     if (param->numViews > 1)
                     {
                         if (0);
@@ -1419,9 +1421,9 @@ namespace X265_NS {
             }
             linenum++;
         }
-        if (numInput != param->numViews)
+        if (numInput != (param->format ? 1 : param->numViews))
         {
-            x265_log(NULL, X265_LOG_WARNING, "Input file missing for given
number of views<%d>\n", param->numViews);
+            x265_log(NULL, X265_LOG_WARNING, "Number of Input files does
not match with the given format <%d>\n", param->format);
             if (api)
                 api->param_free(param);
             exit(1);
diff --git a/source/x265cli.h b/source/x265cli.h
index 49a88d084..7ae9877d7 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -364,6 +364,7 @@ static const struct option long_options[] =
 #if ENABLE_MULTIVIEW
     { "num-views", required_argument, NULL, 0 },
     { "multiview-config", required_argument, NULL, 0 },
+    { "format", required_argument, NULL, 0 },
 #endif
 #ifdef SVT_HEVC
     { "svt",     no_argument, NULL, 0 },
-- 
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/96af8d92/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0009-Add-support-for-parsing-spatial-video-with-side-by-s.patch
Type: application/x-patch
Size: 14996 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/96af8d92/attachment-0001.bin>


More information about the x265-devel mailing list