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

Steve Borho steve at borho.org
Tue Apr 28 22:40:00 CEST 2015


# 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);
 


More information about the x265-devel mailing list