[x265] [PATCH MV-HEVC 01/10] Add compile time configuration and support for parsing multiview config file

Karam Singh karam.singh at multicorewareinc.com
Wed Aug 7 08:51:42 UTC 2024


  All the patches of MV-HEVC are pushed to the master branch.

*__________________________*
*Karam Singh*
*Ph.D. IIT Guwahati*
Senior Software (Video Coding) Engineer
Mobile: +91 8011279030
Block 9A, 6th floor, DLF Cyber City
Manapakkam, Chennai 600 089


On Tue, Aug 6, 2024 at 4:12 PM Anusuya Kumarasamy <
anusuya.kumarasamy at multicorewareinc.com> wrote:

> 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
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240807/7c785580/attachment-0001.htm>


More information about the x265-devel mailing list