[x265] [PATCH 1 of 2] zone: add support to parse zone files

Kalyan Goswami kalyan at multicorewareinc.com
Wed Dec 26 09:32:45 CET 2018


Pushed
Thanks,
Kalyan Goswami, PhD
Video Architect @ MulticoreWare
http: <http://www.multicorewareinc.com/>//www.multicorewareinc.com
<http://www.multicorewareinc.com/>
+91 9884989331


On Thu, Dec 20, 2018 at 4:33 PM <bhavna at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Bhavna Hariharan <bhavna at multicorewareinc.com>
> # Date 1544769275 -19800
> #      Fri Dec 14 12:04:35 2018 +0530
> # Node ID 592b83c9068d7f402c85394fcf113b767b58f08d
> # Parent  1f44f1f1623d677c80469e713ed642f6673af91d
> zone: add support to parse zone files
>
> diff -r 1f44f1f1623d -r 592b83c9068d doc/reST/cli.rst
> --- a/doc/reST/cli.rst  Mon Dec 17 16:49:08 2018 +0530
> +++ b/doc/reST/cli.rst  Fri Dec 14 12:04:35 2018 +0530
> @@ -1826,6 +1826,20 @@
>
>         If zones overlap, whichever comes later in the list takes
> precedence.
>         Default none
> +
> +
> +.. option:: --zonefile <filename>
> +
> +       Specify a text file which contains the boundaries of the zones
> where
> +       each of zones are configurable. The format of each line is:
> +
> +       <frame number> <options to be configured>
> +
> +       The frame number indicates the beginning of a zone. The options
> +       following this is applied until another zone begins. The
> reconfigurable
> +       options can be spcified as --<feature name> <feature value>
> +
> +       **CLI ONLY**
>
>  Quantization Options
>  ====================
> diff -r 1f44f1f1623d -r 592b83c9068d source/common/param.cpp
> --- a/source/common/param.cpp   Mon Dec 17 16:49:08 2018 +0530
> +++ b/source/common/param.cpp   Fri Dec 14 12:04:35 2018 +0530
> @@ -244,6 +244,7 @@
>      param->rc.complexityBlur = 20;
>      param->rc.qblur = 0.5;
>      param->rc.zoneCount = 0;
> +    param->rc.zonefileCount = 0;
>      param->rc.zones = NULL;
>      param->rc.bEnableSlowFirstPass = 1;
>      param->rc.bStrictCbr = 0;
> @@ -564,6 +565,104 @@
>
>      return x265_atoi(arg, bError);
>  }
> +/* internal versions of string-to-int with additional error checking */
> +#undef atoi
> +#undef atof
> +#define atoi(str) x265_atoi(str, bError)
> +#define atof(str) x265_atof(str, bError)
> +#define atobool(str) (x265_atobool(str, bError))
> +
> +int x265_zone_param_parse(x265_param* p, const char* name, const char*
> value)
> +{
> +    bool bError = false;
> +    char nameBuf[64];
> +
> +    if (!name)
> +        return X265_PARAM_BAD_NAME;
> +
> +    // skip -- prefix if provided
> +    if (name[0] == '-' && name[1] == '-')
> +        name += 2;
> +
> +    // s/_/-/g
> +    if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
> +    {
> +        char *c;
> +        strcpy(nameBuf, name);
> +        while ((c = strchr(nameBuf, '_')) != 0)
> +            *c = '-';
> +
> +        name = nameBuf;
> +    }
> +
> +    if (!strncmp(name, "no-", 3))
> +    {
> +        name += 3;
> +        value = !value || x265_atobool(value, bError) ? "false" : "true";
> +    }
> +    else if (!strncmp(name, "no", 2))
> +    {
> +        name += 2;
> +        value = !value || x265_atobool(value, bError) ? "false" : "true";
> +    }
> +    else if (!value)
> +        value = "true";
> +    else if (value[0] == '=')
> +        value++;
> +
> +#define OPT(STR) else if (!strcmp(name, STR))
> +#define OPT2(STR1, STR2) else if (!strcmp(name, STR1) || !strcmp(name,
> STR2))
> +
> +    if (0);
> +    OPT("ref") p->maxNumReferences = atoi(value);
> +    OPT("fast-intra") p->bEnableFastIntra = atobool(value);
> +    OPT("early-skip") p->bEnableEarlySkip = atobool(value);
> +    OPT("rskip") p->bEnableRecursionSkip = atobool(value);
> +    OPT("me")p->searchMethod = parseName(value, x265_motion_est_names,
> bError);
> +    OPT("subme") p->subpelRefine = atoi(value);
> +    OPT("merange") p->searchRange = atoi(value);
> +    OPT("rect") p->bEnableRectInter = atobool(value);
> +    OPT("amp") p->bEnableAMP = atobool(value);
> +    OPT("max-merge") p->maxNumMergeCand = (uint32_t)atoi(value);
> +    OPT("rd") p->rdLevel = atoi(value);
> +    OPT2("rdoq", "rdoq-level")
> +    {
> +        int bval = atobool(value);
> +        if (bError || bval)
> +        {
> +            bError = false;
> +            p->rdoqLevel = atoi(value);
> +        }
> +        else
> +            p->rdoqLevel = 0;
> +    }
> +    OPT("b-intra") p->bIntraInBFrames = atobool(value);
> +    OPT("scaling-list") p->scalingLists = strdup(value);
> +    OPT("aq-mode") p->rc.aqMode = atoi(value);
> +    OPT("aq-strength") p->rc.aqStrength = atof(value);
> +    OPT("nr-intra") p->noiseReductionIntra = atoi(value);
> +    OPT("nr-inter") p->noiseReductionInter = atoi(value);
> +    OPT("limit-modes") p->limitModes = atobool(value);
> +    OPT("splitrd-skip") p->bEnableSplitRdSkip = atobool(value);
> +    OPT("cu-lossless") p->bCULossless = atobool(value);
> +    OPT("rd-refine") p->bEnableRdRefine = atobool(value);
> +    OPT("limit-tu") p->limitTU = atoi(value);
> +    OPT("tskip") p->bEnableTransformSkip = atobool(value);
> +    OPT("tskip-fast") p->bEnableTSkipFast = atobool(value);
> +    OPT("rdpenalty") p->rdPenalty = atoi(value);
> +    OPT("dynamic-rd") p->dynamicRd = atof(value);
> +    else
> +        return X265_PARAM_BAD_NAME;
> +
> +#undef OPT
> +#undef OPT2
> +
> +    return bError ? X265_PARAM_BAD_VALUE : 0;
> +}
> +
> +#undef atobool
> +#undef atoi
> +#undef atof
>
>  /* internal versions of string-to-int with additional error checking */
>  #undef atoi
> diff -r 1f44f1f1623d -r 592b83c9068d source/common/param.h
> --- a/source/common/param.h     Mon Dec 17 16:49:08 2018 +0530
> +++ b/source/common/param.h     Fri Dec 14 12:04:35 2018 +0530
> @@ -51,6 +51,7 @@
>  int x265_param_default_preset(x265_param *, const char *preset, const
> char *tune);
>  int x265_param_apply_profile(x265_param *, const char *profile);
>  int x265_param_parse(x265_param *p, const char *name, const char *value);
> +int x265_zone_param_parse(x265_param* p, const char* name, const char*
> value);
>  #define PARAM_NS X265_NS
>  #endif
>  }
> diff -r 1f44f1f1623d -r 592b83c9068d source/encoder/api.cpp
> --- a/source/encoder/api.cpp    Mon Dec 17 16:49:08 2018 +0530
> +++ b/source/encoder/api.cpp    Fri Dec 14 12:04:35 2018 +0530
> @@ -674,9 +674,9 @@
>  #if ENABLE_LIBVMAF
>      &x265_calculate_vmafscore,
>      &x265_calculate_vmaf_framelevelscore,
> -    &x265_vmaf_encoder_log
> +    &x265_vmaf_encoder_log,
>  #endif
> -
> +    &PARAM_NS::x265_zone_param_parse
>  };
>
>  typedef const x265_api* (*api_get_func)(int bitDepth);
> diff -r 1f44f1f1623d -r 592b83c9068d source/x265.cpp
> --- a/source/x265.cpp   Mon Dec 17 16:49:08 2018 +0530
> +++ b/source/x265.cpp   Fri Dec 14 12:04:35 2018 +0530
> @@ -74,6 +74,7 @@
>      ReconFile* recon;
>      OutputFile* output;
>      FILE*       qpfile;
> +    FILE*       zoneFile;
>      FILE*    dolbyVisionRpu;    /* File containing Dolby Vision BL RPU
> metadata */
>      const char* reconPlayCmd;
>      const x265_api* api;
> @@ -97,6 +98,7 @@
>          recon = NULL;
>          output = NULL;
>          qpfile = NULL;
> +        zoneFile = NULL;
>          dolbyVisionRpu = NULL;
>          reconPlayCmd = NULL;
>          api = NULL;
> @@ -114,7 +116,9 @@
>      void destroy();
>      void printStatus(uint32_t frameNum);
>      bool parse(int argc, char **argv);
> +    bool parseZoneParam(int argc, char **argv, x265_param* globalParam,
> int zonefileCount);
>      bool parseQPFile(x265_picture &pic_org);
> +    bool parseZoneFile();
>  };
>
>  void CLIOptions::destroy()
> @@ -128,6 +132,9 @@
>      if (qpfile)
>          fclose(qpfile);
>      qpfile = NULL;
> +    if (zoneFile)
> +        fclose(zoneFile);
> +    zoneFile = NULL;
>      if (dolbyVisionRpu)
>          fclose(dolbyVisionRpu);
>      dolbyVisionRpu = NULL;
> @@ -163,6 +170,110 @@
>      prevUpdateTime = time;
>  }
>
> +bool CLIOptions::parseZoneParam(int argc, char **argv, x265_param*
> globalParam, int zonefileCount)
> +{
> +    bool bError = false;
> +    int bShowHelp = false;
> +    int outputBitDepth = 0;
> +    const char *profile = NULL;
> +
> +    /* Presets are applied before all other options. */
> +    for (optind = 0;;)
> +    {
> +        int c = getopt_long(argc, argv, short_options, long_options,
> NULL);
> +        if (c == -1)
> +            break;
> +        else if (c == 'D')
> +            outputBitDepth = atoi(optarg);
> +        else if (c == 'P')
> +            profile = optarg;
> +        else if (c == '?')
> +            bShowHelp = true;
> +    }
> +
> +    if (!outputBitDepth && profile)
> +    {
> +        /* try to derive the output bit depth from the requested profile
> */
> +        if (strstr(profile, "10"))
> +            outputBitDepth = 10;
> +        else if (strstr(profile, "12"))
> +            outputBitDepth = 12;
> +        else
> +            outputBitDepth = 8;
> +    }
> +
> +    api = x265_api_get(outputBitDepth);
> +    if (!api)
> +    {
> +        x265_log(NULL, X265_LOG_WARNING, "falling back to default
> bit-depth\n");
> +        api = x265_api_get(0);
> +    }
> +
> +    if (bShowHelp)
> +    {
> +        printVersion(globalParam, api);
> +        showHelp(globalParam);
> +    }
> +
> +    globalParam->rc.zones[zonefileCount].zoneParam = api->param_alloc();
> +    if (!globalParam->rc.zones[zonefileCount].zoneParam)
> +    {
> +        x265_log(NULL, X265_LOG_ERROR, "param alloc failed\n");
> +        return true;
> +    }
> +
> +    memcpy(globalParam->rc.zones[zonefileCount].zoneParam, globalParam,
> sizeof(x265_param));
> +
> +    for (optind = 0;;)
> +    {
> +        int long_options_index = -1;
> +        int c = getopt_long(argc, argv, 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);
> +                return true;
> +            }
> +        }
> +        if (long_options_index < 0)
> +        {
> +            x265_log(NULL, X265_LOG_WARNING, "short option '%c'
> unrecognized\n", c);
> +            return true;
> +        }
> +
> +        bError |=
> !!api->zone_param_parse(globalParam->rc.zones[zonefileCount].zoneParam,
> long_options[long_options_index].name, optarg);
> +
> +        if (bError)
> +        {
> +            const char *name = long_options_index > 0 ?
> long_options[long_options_index].name : argv[optind - 2];
> +            x265_log(NULL, X265_LOG_ERROR, "invalid argument: %s = %s\n",
> name, optarg);
> +            return true;
> +        }
> +    }
> +
> +    if (optind < argc)
> +    {
> +        x265_log(param, X265_LOG_WARNING, "extra unused command arguments
> given <%s>\n", argv[optind]);
> +        return true;
> +    }
> +    return false;
> +}
> +
>  bool CLIOptions::parse(int argc, char **argv)
>  {
>      bool bError = false;
> @@ -327,6 +438,12 @@
>                      return true;
>                  }
>              }
> +            OPT("zonefile")
> +            {
> +                this->zoneFile = x265_fopen(optarg, "rb");
> +                if (!this->zoneFile)
> +                    x265_log_file(param, X265_LOG_ERROR, "%s zone file
> not found or error in opening zone file\n", optarg);
> +            }
>              OPT("fullhelp")
>              {
>                  param->logLevel = X265_LOG_FULL;
> @@ -535,6 +652,59 @@
>      return 1;
>  }
>
> +bool CLIOptions::parseZoneFile()
> +{
> +    char line[256];
> +    char* argLine;
> +    param->rc.zonefileCount = 0;
> +
> +    while (fgets(line, sizeof(line), zoneFile))
> +    {
> +        if (!((*line == '#') || (strcmp(line, "\r\n") == 0)))
> +            param->rc.zonefileCount++;
> +    }
> +
> +    rewind(zoneFile);
> +    param->rc.zones = X265_MALLOC(x265_zone, param->rc.zonefileCount);
> +    for (int i = 0; i < param->rc.zonefileCount; i++)
> +    {
> +        while (fgets(line, sizeof(line), zoneFile))
> +        {
> +            if (*line == '#' || (strcmp(line, "\r\n") == 0))
> +                continue;
> +            param->rc.zones[i].zoneParam = X265_MALLOC(x265_param, 1);
> +            int index = (int)strcspn(line, "\r\n");
> +            line[index] = '\0';
> +            argLine = line;
> +            while (isspace((unsigned char)*argLine)) argLine++;
> +            char* start = strchr(argLine, ' ');
> +            start++;
> +            param->rc.zones[i].startFrame = atoi(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, " ");
> +            }
> +            args[argCount] = '\0';
> +            CLIOptions cliopt;
> +            if (cliopt.parseZoneParam(argCount, args,param, i))
> +            {
> +                cliopt.destroy();
> +                if (cliopt.api)
> +                    cliopt.api->param_free(cliopt.param);
> +                exit(1);
> +            }
> +            break;
> +        }
> +    }
> +    return 1;
> +}
> +
>  #ifdef _WIN32
>  /* Copy of x264 code, which allows for Unicode characters in the command
> line.
>   * Retrieve command line arguments as UTF-8. */
> @@ -667,6 +837,16 @@
>      if (cliopt.reconPlayCmd)
>          reconPlay = new ReconPlay(cliopt.reconPlayCmd, *param);
>
> +    if (cliopt.zoneFile)
> +    {
> +        if (!cliopt.parseZoneFile())
> +        {
> +            x265_log(NULL, X265_LOG_ERROR, "Unable to parse zonefile\n");
> +            fclose(cliopt.zoneFile);
> +            cliopt.zoneFile = NULL;
> +        }
> +    }
> +
>      /* note: we could try to acquire a different libx265 API here based on
>       * the profile found during option parsing, but it must be done before
>       * opening an encoder */
> diff -r 1f44f1f1623d -r 592b83c9068d source/x265.h
> --- a/source/x265.h     Mon Dec 17 16:49:08 2018 +0530
> +++ b/source/x265.h     Fri Dec 14 12:04:35 2018 +0530
> @@ -659,6 +659,8 @@
>  static const char * const x265_interlace_names[] = { "prog", "tff",
> "bff", 0 };
>  static const char * const x265_analysis_names[] = { "off", "save",
> "load", 0 };
>
> +struct x265_zone;
> +struct x265_param;
>  /* Zones: override ratecontrol for specific sections of the video.
>   * If zones overlap, whichever comes later in the list takes precedence.
> */
>  typedef struct x265_zone
> @@ -667,6 +669,7 @@
>      int   bForceQp;             /* whether to use qp vs bitrate factor */
>      int   qp;
>      float bitrateFactor;
> +    x265_param* zoneParam;
>  } x265_zone;
>
>  /* data to calculate aggregate VMAF score */
> @@ -1395,6 +1398,9 @@
>          int        zoneCount;
>          x265_zone* zones;
>
> +        /* number of zones in zone-file*/
> +        int        zonefileCount;
> +
>          /* specify a text file which contains MAX_MAX_QP + 1 floating
> point
>           * values to be copied into x265_lambda_tab and a second set of
>           * MAX_MAX_QP + 1 floating point values for x265_lambda2_tab. All
> values
> @@ -1773,6 +1779,8 @@
>  #define X265_PARAM_BAD_VALUE (-2)
>  int x265_param_parse(x265_param *p, const char *name, const char *value);
>
> +int x265_zone_param_parse(x265_param* p, const char* name, const char*
> value);
> +
>  static const char * const x265_profile_names[] = {
>      /* HEVC v1 */
>      "main", "main10", "mainstillpicture", /* alias */ "msp",
> @@ -2066,6 +2074,7 @@
>      double        (*calculate_vmaf_framelevelscore)(x265_vmaf_framedata
> *);
>      void          (*vmaf_encoder_log)(x265_encoder*, int, char**,
> x265_param *, x265_vmaf_data *);
>  #endif
> +    int           (*zone_param_parse)(x265_param*, const char*, const
> char*);
>      /* add new pointers to the end, or increment X265_MAJOR_VERSION */
>  } x265_api;
>
> diff -r 1f44f1f1623d -r 592b83c9068d source/x265cli.h
> --- a/source/x265cli.h  Mon Dec 17 16:49:08 2018 +0530
> +++ b/source/x265cli.h  Fri Dec 14 12:04:35 2018 +0530
> @@ -242,6 +242,7 @@
>      { "no-info",              no_argument, NULL, 0 },
>      { "zones",          required_argument, NULL, 0 },
>      { "qpfile",         required_argument, NULL, 0 },
> +    { "zonefile",       required_argument, NULL, 0 },
>      { "lambda-file",    required_argument, NULL, 0 },
>      { "b-intra",              no_argument, NULL, 0 },
>      { "no-b-intra",           no_argument, NULL, 0 },
> @@ -541,6 +542,7 @@
>      H1("                                   where <option> is either\n");
>      H1("                                       q=<integer> (force QP)\n");
>      H1("                                   or  b=<float> (bitrate
> multiplier)\n");
> +    H0("   --zonefile <filename>         Zone file containing the zone
> boundaries and the parameters to be reconfigured.\n");
>      H1("   --lambda-file <string>        Specify a file containing
> replacement values for the lambda tables\n");
>      H1("                                 MAX_MAX_QP+1 floats for lambda
> table, then again for lambda2 table\n");
>      H1("                                 Blank lines and lines starting
> with hash(#) are ignored\n");
> _______________________________________________
> 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/20181226/b9da2fb1/attachment-0001.html>


More information about the x265-devel mailing list