[x265] [PATCH MV-HEVC 01/10] Add compile time configuration and support for parsing multiview config file
Anusuya Kumarasamy
anusuya.kumarasamy at multicorewareinc.com
Tue Aug 6 10:42:11 UTC 2024
>From dba87b3da6bea98ce677bc7be006b928c9d7f8d0 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Wed, 10 Jul 2024 16:06:01 +0530
Subject: [PATCH] Add compile time configuration and support for parsing
multiview config file
---
doc/reST/cli.rst | 30 +++++++
source/CMakeLists.txt | 7 +-
source/common/param.cpp | 21 +++++
source/x265.h | 9 ++
source/x265cli.cpp | 176 ++++++++++++++++++++++++++++++++++++++--
source/x265cli.h | 13 +++
6 files changed, 249 insertions(+), 7 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index 4d5ac1a15..298ee334a 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2893,4 +2893,34 @@ Alpha Encode Options
**CLI_ONLY**
+Multiview Encode Options
+===================
+
+ Enable multiview encoding support in x265.This option can be enabled
+ only when ENABLE_MULTIVIEW is set during the make of x265.
+
+.. option:: --num-views <integer>
+ Specify the number of views in the multiview input video.
+
+.. option:: --format <integer>
+ Specify the format of the input video
+ 0 : Two separate input videos
+ 1 : One input video with both views in left and right format
+ 2 : One input video with both views in top and bottom format
+
+.. option:: --multiview-config <filename>
+ File containing the configurations to enable multiview encoding.
+
+ Sample config file::
+
+ --num-views 2
+ --format 0
+ --input multiview-input-01.yuv
+ --input multiview-input-02.yuv
+
+ Other input parameters such as input-csp/input-depth/input-res/fps must
be configured through
+ normal CLI and is expected to be same for all views
+
+**CLI_ONLY**
+
.. vim: noet
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 2dcac3dc6..f25bc8b84 100755
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -31,7 +31,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)
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 210)
+set(X265_BUILD 211)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
@@ -600,6 +600,11 @@ if(ENABLE_ALPHA)
add_definitions(-DENABLE_ALPHA)
endif()
+option(ENABLE_MULTIVIEW "Enable Multi-view encoding in HEVC" OFF)
+if(ENABLE_MULTIVIEW)
+ add_definitions(-DENABLE_MULTIVIEW)
+endif()
+
add_subdirectory(encoder)
add_subdirectory(common)
diff --git a/source/common/param.cpp b/source/common/param.cpp
index dec6ff6c9..c2efb11cf 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -403,6 +403,9 @@ void x265_param_default(x265_param* param)
/* Film grain characteristics model filename */
param->filmGrain = NULL;
param->bEnableSBRC = 0;
+
+ /* Multi-View Encoding*/
+ param->numViews = 1;
}
int x265_param_default_preset(x265_param* param, const char* preset, const
char* tune)
@@ -1457,6 +1460,12 @@ int x265_param_parse(x265_param* p, const char*
name, const char* value)
p->numScalableLayers = 2;
}
}
+#endif
+#if ENABLE_MULTIVIEW
+ OPT("num-views")
+ {
+ p->numViews = atoi(value);
+ }
#endif
else
return X265_PARAM_BAD_NAME;
@@ -1935,6 +1944,9 @@ int x265_check_params(x265_param* param)
CHECK((param->internalCsp != X265_CSP_I420), "Alpha encode
supported only with i420a colorspace");
CHECK((param->rc.rateControlMode != X265_RC_CQP), "Alpha encode
supported only with CQP mode");
}
+#endif
+#if ENABLE_MULTIVIEW
+ CHECK((param->numViews > 2), "Multi-View Encoding currently support
only 2 views");
#endif
return check_failed;
}
@@ -2103,6 +2115,9 @@ void x265_print_params(x265_param* param)
#if ENABLE_ALPHA
TOOLOPT(param->numScalableLayers > 1, "alpha");
#endif
+#if ENABLE_MULTIVIEW
+ TOOLOPT(param->numViews > 1, "multi-view");
+#endif
#if ENABLE_HDR10_PLUS
TOOLOPT(param->toneMapFile != NULL, "dhdr10-info");
#endif
@@ -2369,6 +2384,9 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
BOOL(p->bEnableTemporalFilter, "mcstf");
#if ENABLE_ALPHA
BOOL(p->bEnableAlpha, "alpha");
+#endif
+#if ENABLE_MULTIVIEW
+ s += sprintf(s, " num-views=%d", p->numViews);
#endif
BOOL(p->bEnableSBRC, "sbrc");
#undef BOOL
@@ -2895,6 +2913,9 @@ void x265_copy_params(x265_param* dst, x265_param*
src)
dst->bEnableAlpha = src->bEnableAlpha;
dst->numScalableLayers = src->numScalableLayers;
#endif
+#if ENABLE_MULTIVIEW
+ dst->numViews = src->numViews;
+#endif
if (src->videoSignalTypePreset) dst->videoSignalTypePreset =
strdup(src->videoSignalTypePreset);
else dst->videoSignalTypePreset = NULL;
diff --git a/source/x265.h b/source/x265.h
index 084f7cd64..baf18e4fc 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -626,6 +626,12 @@ typedef enum
#define X265_MAX_GOP_LENGTH 16
#define MAX_T_LAYERS 7
+#if ENABLE_MULTIVIEW
+#define MAX_VIEWS 2
+#else
+#define MAX_VIEWS 1
+#endif
+
#if ENABLE_ALPHA
#define MAX_SCALABLE_LAYERS 2
#define MAX_VPS_NUM_SCALABILITY_TYPES 16
@@ -2284,6 +2290,9 @@ typedef struct x265_param
/*Alpha channel encoding*/
int bEnableAlpha;
int numScalableLayers;
+
+ /*Multi View Encoding*/
+ int numViews;
} x265_param;
/* x265_param_alloc:
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 1ba0a5877..86e1d9bd8 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -377,6 +377,10 @@ namespace X265_NS {
#if ENABLE_ALPHA
H0(" --alpha Enable alpha channel support.
Default %d\n", param->bEnableAlpha);
#endif
+#if ENABLE_MULTIVIEW
+ H0(" --num-views Number of Views for Multiview
Encoding. Default %d\n", param->numViews);
+ H0(" --multiview-config Configuration file for
Multiview Encoding\n");
+#endif
#ifdef SVT_HEVC
H0(" --[no]svt Enable SVT HEVC encoder
%s\n", OPT(param->bEnableSvtHevc));
H0(" --[no-]svt-hme Enable Hierarchial motion
estimation(HME) in SVT HEVC encoder \n");
@@ -583,7 +587,11 @@ namespace X265_NS {
int inputBitDepth = 8;
int outputBitDepth = 0;
int reconFileBitDepth = 0;
- const char *inputfn = NULL;
+ char* inputfn[MAX_VIEWS] = { NULL };
+ for (int view = 0; view < MAX_VIEWS; view++)
+ {
+ inputfn[view] = X265_MALLOC(char, sizeof(char) * 1024);
+ }
const char* reconfn[MAX_SCALABLE_LAYERS] = { NULL };
const char *outputfn = NULL;
const char *preset = NULL;
@@ -723,7 +731,7 @@ namespace X265_NS {
OPT("frames") this->framesToBeEncoded =
(uint32_t)x265_atoi(optarg, bError);
OPT("no-progress") this->bProgress = false;
OPT("output") outputfn = optarg;
- OPT("input") inputfn = optarg;
+ OPT("input") inputfn[0] = optarg;
OPT("recon") reconfn[0] = optarg;
OPT("input-depth") inputBitDepth =
(uint32_t)x265_atoi(optarg, bError);
OPT("dither") this->bDither = true;
@@ -756,6 +764,14 @@ namespace X265_NS {
if (!this->scenecutAwareQpConfig)
x265_log_file(param, X265_LOG_ERROR, "%s scenecut
aware qp config file not found or error in opening config file\n", optarg);
}
+#if ENABLE_MULTIVIEW
+ OPT("multiview-config")
+ {
+ this->multiViewConfig = x265_fopen(optarg, "rb");
+ if (!this->multiViewConfig)
+ x265_log_file(param, X265_LOG_ERROR, "%s Multiview
config file not found or error in opening config file\n", optarg);
+ }
+#endif
OPT("zonefile")
{
this->zoneFile = x265_fopen(optarg, "rb");
@@ -782,8 +798,10 @@ namespace X265_NS {
}
}
- if (optind < argc && !inputfn)
- inputfn = argv[optind++];
+#if !ENABLE_MULTIVIEW
+ if (optind < argc && !inputfn[0])
+ inputfn[0] = argv[optind++];
+#endif
if (optind < argc && !outputfn)
outputfn = argv[optind++];
if (optind < argc)
@@ -799,7 +817,18 @@ namespace X265_NS {
showHelp(param);
}
- if (!inputfn || !outputfn)
+#if ENABLE_MULTIVIEW
+ if (this->multiViewConfig)
+ {
+ if (!this->parseMultiViewConfig(inputfn))
+ {
+ x265_log(NULL, X265_LOG_ERROR, "Unable to parse multiview
config file \n");
+ fclose(this->multiViewConfig);
+ this->multiViewConfig = NULL;
+ }
+ }
+#endif
+ if (!inputfn[0] || !outputfn)
{
x265_log(param, X265_LOG_ERROR, "input or output file not
specified, try --help for help\n");
return true;
@@ -824,7 +853,7 @@ namespace X265_NS {
#endif
InputFileInfo info;
- info.filename = inputfn;
+ info.filename = inputfn[0];
info.depth = inputBitDepth;
info.csp = param->internalCsp;
info.width = param->sourceWidth;
@@ -1250,6 +1279,141 @@ namespace X265_NS {
return false;
}
+#if ENABLE_MULTIVIEW
+ bool CLIOptions::parseMultiViewConfig(char** fn)
+ {
+ char line[256];
+ char* argLine;
+ rewind(multiViewConfig);
+ int linenum = 0;
+ int numInput = 0;
+ while (fgets(line, sizeof(line), multiViewConfig))
+ {
+ if (*line == '#' || (strcmp(line, "\r\n") == 0))
+ continue;
+ int index = (int)strcspn(line, "\r\n");
+ line[index] = '\0';
+ argLine = line;
+ while (isspace((unsigned char)*argLine)) argLine++;
+ char* start = strchr(argLine, '-');
+ int argCount = 0;
+ char** args = (char**)malloc(256 * sizeof(char*));
+ //Adding a dummy string to avoid file parsing error
+ args[argCount++] = (char*)"x265";
+ char* token = strtok(start, " ");
+ while (token)
+ {
+ args[argCount++] = token;
+ token = strtok(NULL, " ");
+ while (token && strchr(token, '"'))
+ {
+ token = strchr(token, '"');
+ token = strtok(token, "\"");
+ }
+ }
+ args[argCount] = NULL;
+ bool bError = false;
+ bool bInvalid = false;
+ for (optind = 0;;)
+ {
+ int long_options_index = -1;
+ int c = getopt_long(argCount, args, short_options,
long_options, &long_options_index);
+ if (c == -1)
+ break;
+ if (long_options_index < 0 && c > 0)
+ {
+ for (size_t i = 0; i < sizeof(long_options) /
sizeof(long_options[0]); i++)
+ {
+ if (long_options[i].val == c)
+ {
+ long_options_index = (int)i;
+ break;
+ }
+ }
+ if (long_options_index < 0)
+ {
+ /* getopt_long might have already printed an error
message */
+ if (c != 63)
+ x265_log(NULL, X265_LOG_WARNING, "internal
error: short option '%c' has no long option\n", c);
+ bInvalid = true;
+ break;
+ }
+ }
+ if (long_options_index < 0)
+ {
+ x265_log(NULL, X265_LOG_WARNING, "short option '%c'
unrecognized\n", c);
+ bInvalid = true;
+ break;
+ }
+ char nameBuf[64];
+ const char* name = long_options[long_options_index].name;
+ if (!name)
+ bError = true;
+ else
+ {
+ // skip -- prefix if provided
+ if (name[0] == '-' && name[1] == '-')
+ name += 2;
+ // s/_/-/g
+ if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name,
'_'))
+ {
+ char* ch;
+ strcpy(nameBuf, name);
+ while ((ch = strchr(nameBuf, '_')) != 0)
+ *ch = '-';
+ name = nameBuf;
+ }
+ if (!optarg)
+ optarg = "true";
+ else if (optarg[0] == '=')
+ optarg++;
+#define OPT(STR) else if (!strcmp(name, STR))
+ if (0);
+ OPT("num-views") param->numViews = x265_atoi(optarg,
bError);
+ if (param->numViews > 1)
+ {
+ if (0);
+ OPT("input")
+ {
+ strcpy(fn[numInput++], optarg);
+ }
+
+ }
+#undef OPT
+ }
+ if (bError)
+ {
+ const char* optname = long_options_index > 0 ?
long_options[long_options_index].name : args[optind - 2];
+ x265_log(NULL, X265_LOG_ERROR, "invalid argument: %s =
%s\n", optname, optarg);
+ bInvalid = true;
+ break;
+ }
+ }
+ if (optind < argCount)
+ {
+ x265_log(param, X265_LOG_WARNING, "extra unused command
arguments given <%s>\n", args[optind]);
+ bInvalid = true;
+ }
+ if (bInvalid)
+ {
+ if (api)
+ api->param_free(param);
+ exit(1);
+ }
+ linenum++;
+ }
+ if (numInput != param->numViews)
+ {
+ x265_log(NULL, X265_LOG_WARNING, "Input file missing for given
number of views<%d>\n", param->numViews);
+ if (api)
+ api->param_free(param);
+ exit(1);
+ }
+ return 1;
+ }
+
+#endif
+
#ifdef __cplusplus
}
#endif
\ No newline at end of file
diff --git a/source/x265cli.h b/source/x265cli.h
index 7abf91eb8..0fdad9cf3 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -361,6 +361,10 @@ static const struct option long_options[] =
#if ENABLE_ALPHA
{ "alpha", no_argument, NULL, 0 },
#endif
+#if ENABLE_MULTIVIEW
+ { "num-views", required_argument, NULL, 0 },
+ { "multiview-config", required_argument, NULL, 0 },
+#endif
#ifdef SVT_HEVC
{ "svt", no_argument, NULL, 0 },
{ "no-svt", no_argument, NULL, 0 },
@@ -403,6 +407,9 @@ static const struct option long_options[] =
FILE* zoneFile;
FILE* dolbyVisionRpu; /* File containing Dolby Vision BL RPU
metadata */
FILE* scenecutAwareQpConfig; /* File containing scenecut aware
frame quantization related CLI options */
+#if ENABLE_MULTIVIEW
+ FILE* multiViewConfig; /* File containing multi-view related CLI
options */
+#endif
const char* reconPlayCmd;
const x265_api* api;
x265_param* param;
@@ -442,6 +449,9 @@ static const struct option long_options[] =
zoneFile = NULL;
dolbyVisionRpu = NULL;
scenecutAwareQpConfig = NULL;
+#if ENABLE_MULTIVIEW
+ multiViewConfig = NULL;
+#endif
reconPlayCmd = NULL;
api = NULL;
param = NULL;
@@ -474,6 +484,9 @@ static const struct option long_options[] =
int rpuParser(x265_picture * pic);
bool parseScenecutAwareQpConfig();
bool parseScenecutAwareQpParam(int argc, char **argv, x265_param*
globalParam);
+#if ENABLE_MULTIVIEW
+ bool parseMultiViewConfig(char** fn);
+#endif
};
#ifdef __cplusplus
}
--
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/b682364c/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Add-compile-time-configuration-and-support-for-parsi.patch
Type: application/x-patch
Size: 16404 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/b682364c/attachment-0001.bin>
More information about the x265-devel
mailing list