[x265] [PATCH 3 of 4] cli: allow -P/--profile to influence requested API bit-depth

Xinyue Lu maillist at 7086.in
Wed Apr 29 01:37:24 CEST 2015


How about using --output-depth instead of --profile?

Profile is the "up-limit" of the stream. For example in x264 world,
it's possible that a stream of yuv420p8 avc is marked as High 444
Profile. This may not make much sense in real world encoding though.

So I'd propose the following code logic.

param->output_depth = 0
param->profile = 0

OPT(output-depth)
..param->output_depth = value
OPT(profile)
..param->profile = value

if param->output_depth && !param->profile
..param->profile = param->output_depth.to_profile
else if !param->output_depth && param->profile
..param->output_depth = param->profile.to_depth
else
..param->output_depth = x265_depth
..param->profile = x265_depth.to_profile
end

if param->profile < param->output_depth.to_profile
..alert(Invalid profile)
end

That is, unless user specify both depth and profile, either option
will take effects.

And IMHO --output-depth 10 makes more sense than using --profile
Main10. You'll probably have --output-csp 422/444 soon as well, as
Main422-10 or Main444 is required for i422p8.

On Tue, Apr 28, 2015 at 1:40 PM, Steve Borho <steve at borho.org> wrote:
> # HG changeset patch
> # User Steve Borho <steve at borho.org>
> # Date 1430249504 18000
> #      Tue Apr 28 14:31:44 2015 -0500
> # Node ID 41f1bb787a740001e6605eeee0eb26645bd2b256
> # Parent  2184362dd1cb6c13adf6c6ff93db2ea2f22645f0
> cli: allow -P/--profile to influence requested API bit-depth
>
> This allows our x265 CLI to be linked (statically or dynamically) to a build of
> libx265 with one bit-depth, and then use another shared libx265 of another
> bit-depth to perform the actual encode.
>
> The bulk of the changes in this commit were necessary to move x265_api_get()
> in between the initial argument parsing and x265_param_default_preset()
>
> diff -r 2184362dd1cb -r 41f1bb787a74 source/x265.cpp
> --- a/source/x265.cpp   Tue Apr 28 14:18:13 2015 -0500
> +++ b/source/x265.cpp   Tue Apr 28 14:31:44 2015 -0500
> @@ -75,14 +75,18 @@
>      OutputFile* output;
>      FILE*       qpfile;
>      const char* reconPlayCmd;
> -    bool bProgress;
> -    bool bForceY4m;
> -    bool bDither;
> +    const x265_api* api;
> +
> +    bool     bProgress;
> +    bool     bForceY4m;
> +    bool     bDither;
> +
>      uint32_t seek;              // number of frames to skip from the beginning
>      uint32_t framesToBeEncoded; // number of frames to encode
> +
>      uint64_t totalbytes;
> -    int64_t startTime;
> -    int64_t prevUpdateTime;
> +    int64_t  startTime;
> +    int64_t  prevUpdateTime;
>
>      /* in microseconds */
>      static const int UPDATE_INTERVAL = 250000;
> @@ -92,6 +96,9 @@
>          input = NULL;
>          recon = NULL;
>          output = NULL;
> +        qpfile = NULL;
> +        reconPlayCmd = NULL;
> +        api = NULL;
>          framesToBeEncoded = seek = 0;
>          totalbytes = 0;
>          bProgress = true;
> @@ -99,13 +106,12 @@
>          startTime = x265_mdate();
>          prevUpdateTime = 0;
>          bDither = false;
> -        qpfile = NULL;
> -        reconPlayCmd = NULL;
>      }
>
> +    x265_param* parse(int argc, char** argv);
> +
>      void destroy();
> -    void printStatus(uint32_t frameNum, x265_param *param);
> -    bool parse(int argc, char **argv, x265_param* param);
> +    void printStatus(uint32_t frameNum, x265_param* param);
>      bool parseQPFile(x265_picture &pic_org);
>      bool validateFanout(x265_param*);
>  };
> @@ -153,9 +159,10 @@
>      prevUpdateTime = time;
>  }
>
> -bool CLIOptions::parse(int argc, char **argv, x265_param* param)
> +x265_param* CLIOptions::parse(int argc, char **argv)
>  {
> -    bool bError = 0;
> +    bool bError = false;
> +    bool bShowHelp = false;
>      int help = 0;
>      int inputBitDepth = 8;
>      int reconFileBitDepth = 0;
> @@ -169,7 +176,7 @@
>      if (argc <= 1)
>      {
>          x265_log(NULL, X265_LOG_ERROR, "No input file. Run x265 --help for a list of options.\n");
> -        return true;
> +        return NULL;
>      }
>
>      /* Presets are applied before all other options. */
> @@ -180,18 +187,40 @@
>              break;
>          if (c == 'p')
>              preset = optarg;
> -        if (c == 't')
> +        else if (c == 't')
>              tune = optarg;
> +        else if (c == 'P')
> +            profile = optarg;
>          else if (c == '?')
> -            showHelp(param);
> +            bShowHelp = true;
>      }
>
> -    if (x265_param_default_preset(param, preset, tune) < 0)
> +    api = NULL;
> +    if (profile)
> +    {
> +        /* Try to respect the user's wishes, as specified by --profile */
> +        if (!strcmp(profile, "main") || !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp") || !strcmp(profile, "main444-8"))
> +            api = x265_api_get(8);
> +        else if (!strcmp(profile, "main10") || !strcmp(profile, "main422-10") || !strcmp(profile, "main444-10"))
> +            api = x265_api_get(10);
> +    }
> +    if (!api)
> +        api = x265_api_get(X265_DEPTH); /* prefer what the cli was compiled against */
> +    if (!api)
> +        api = x265_api_get(0);          /* prefer what we link against */
> +
> +    x265_param* param = api->param_alloc();
> +
> +    if (api->param_default_preset(param, preset, tune) < 0)
>      {
>          x265_log(NULL, X265_LOG_ERROR, "preset or tune unrecognized\n");
> -        return true;
> +        api->param_free(param);
> +        return NULL;
>      }
>
> +    if (bShowHelp)
> +        showHelp(param);
> +
>      for (optind = 0;; )
>      {
>          int long_options_index = -1;
> @@ -227,13 +256,15 @@
>                      /* 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;
> +                    api->param_free(param);
> +                    return NULL;
>                  }
>              }
>              if (long_options_index < 0)
>              {
>                  x265_log(NULL, X265_LOG_WARNING, "short option '%c' unrecognized\n", c);
> -                return true;
> +                api->param_free(param);
> +                return NULL;
>              }
>  #define OPT(longname) \
>      else if (!strcmp(long_options[long_options_index].name, longname))
> @@ -252,7 +283,7 @@
>              OPT("dither") this->bDither = true;
>              OPT("recon-depth") reconFileBitDepth = (uint32_t)x265_atoi(optarg, bError);
>              OPT("y4m") this->bForceY4m = true;
> -            OPT("profile") profile = optarg; /* handled last */
> +            OPT("profile") /* handled above (and below) */;
>              OPT("preset") /* handled above */;
>              OPT("tune")   /* handled above */;
>              OPT("recon-y4m-exec") reconPlayCmd = optarg;
> @@ -262,17 +293,19 @@
>                  if (!this->qpfile)
>                  {
>                      x265_log(param, X265_LOG_ERROR, "%s qpfile not found or error in opening qp file\n", optarg);
> -                    return false;
> +                    api->param_free(param);
> +                    return NULL;
>                  }
>              }
>              else
> -                bError |= !!x265_param_parse(param, long_options[long_options_index].name, optarg);
> +                bError |= !!api->param_parse(param, 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;
> +                api->param_free(param);
> +                return NULL;
>              }
>  #undef OPT
>          }
> @@ -285,7 +318,8 @@
>      if (optind < argc)
>      {
>          x265_log(param, X265_LOG_WARNING, "extra unused command arguments given <%s>\n", argv[optind]);
> -        return true;
> +        api->param_free(param);
> +        return NULL;
>      }
>
>      if (argc <= 1 || help)
> @@ -294,13 +328,15 @@
>      if (inputfn == NULL || outputfn == NULL)
>      {
>          x265_log(param, X265_LOG_ERROR, "input or output file not specified, try -V for help\n");
> -        return true;
> +        api->param_free(param);
> +        return NULL;
>      }
>
> -    if (param->internalBitDepth != x265_max_bit_depth)
> +    if (param->internalBitDepth != api->max_bit_depth)
>      {
> -        x265_log(param, X265_LOG_ERROR, "Only bit depths of %d are supported in this build\n", x265_max_bit_depth);
> -        return true;
> +        x265_log(param, X265_LOG_ERROR, "Only bit depths of %d are supported in this build\n", api->max_bit_depth);
> +        api->param_free(param);
> +        return NULL;
>      }
>
>      InputFileInfo info;
> @@ -321,13 +357,15 @@
>      if (!this->input || this->input->isFail())
>      {
>          x265_log(param, X265_LOG_ERROR, "unable to open input file <%s>\n", inputfn);
> -        return true;
> +        api->param_free(param);
> +        return NULL;
>      }
>
>      if (info.depth < 8 || info.depth > 16)
>      {
>          x265_log(param, X265_LOG_ERROR, "Input bit depth (%d) must be between 8 and 16\n", inputBitDepth);
> -        return true;
> +        api->param_free(param);
> +        return NULL;
>      }
>
>      /* Unconditionally accept height/width/csp from file info */
> @@ -351,8 +389,11 @@
>      info.timebaseNum = param->fpsDenom;
>      info.timebaseDenom = param->fpsNum;
>
> -    if (x265_param_apply_profile(param, profile))
> -        return true;
> +    if (api->param_apply_profile(param, profile))
> +    {
> +        api->param_free(param);
> +        return NULL;
> +    }
>
>      if (param->logLevel >= X265_LOG_INFO)
>      {
> @@ -398,10 +439,11 @@
>      if (this->output->isFail())
>      {
>          x265_log(param, X265_LOG_ERROR, "failed to open output file <%s> for writing\n", outputfn);
> -        return true;
> +        api->param_free(param);
> +        return NULL;
>      }
>      general_log(param, this->output->getName(), X265_LOG_INFO, "output file: %s\n", outputfn);
> -    return false;
> +    return param;
>  }
>
>  bool CLIOptions::parseQPFile(x265_picture &pic_org)
> @@ -458,21 +500,18 @@
>      GetConsoleTitle(orgConsoleTitle, CONSOLE_TITLE_SIZE);
>      SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED);
>
> -    const x265_api* api = x265_api_get(X265_DEPTH); /* prefer what the cli was compiled against */
> -    if (!api)
> -        api = x265_api_get(0);
> -
>      ReconPlay* reconPlay = NULL;
> -    x265_param* param = api->param_alloc();
>      CLIOptions cliopt;
>
> -    if (cliopt.parse(argc, argv, param))
> +    x265_param* param = cliopt.parse(argc, argv);
> +    if (!param)
>      {
>          cliopt.destroy();
> -        api->param_free(param);
>          exit(1);
>      }
>
> +    const x265_api* api = cliopt.api;
> +
>      /* This allow muxers to modify bitstream format */
>      cliopt.output->setParam(param);
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel


More information about the x265-devel mailing list