| 1 | /***************************************************************************** |
| 2 | * Copyright (C) 2013 x265 project |
| 3 | * |
| 4 | * Authors: Deepthi Nandakumar <deepthi@multicorewareinc.com> |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. |
| 19 | * |
| 20 | * This program is also available under a commercial proprietary license. |
| 21 | * For more information, contact us at license @ x265.com. |
| 22 | *****************************************************************************/ |
| 23 | |
| 24 | #include "common.h" |
| 25 | #include "slice.h" |
| 26 | #include "threading.h" |
| 27 | #include "param.h" |
| 28 | #include "cpu.h" |
| 29 | #include "x265.h" |
| 30 | |
| 31 | #if _MSC_VER |
| 32 | #pragma warning(disable: 4996) // POSIX functions are just fine, thanks |
| 33 | #pragma warning(disable: 4706) // assignment within conditional |
| 34 | #pragma warning(disable: 4127) // conditional expression is constant |
| 35 | #endif |
| 36 | |
| 37 | #if _WIN32 |
| 38 | #define strcasecmp _stricmp |
| 39 | #endif |
| 40 | |
| 41 | #if !defined(HAVE_STRTOK_R) |
| 42 | |
| 43 | /* |
| 44 | * adapted from public domain strtok_r() by Charlie Gordon |
| 45 | * |
| 46 | * from comp.lang.c 9/14/2007 |
| 47 | * |
| 48 | * http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684 |
| 49 | * |
| 50 | * (Declaration that it's public domain): |
| 51 | * http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c |
| 52 | */ |
| 53 | |
| 54 | #undef strtok_r |
| 55 | char* strtok_r(char * str, |
| 56 | const char *delim, |
| 57 | char ** nextp) |
| 58 | { |
| 59 | if (!str) |
| 60 | str = *nextp; |
| 61 | |
| 62 | str += strspn(str, delim); |
| 63 | |
| 64 | if (!*str) |
| 65 | return NULL; |
| 66 | |
| 67 | char *ret = str; |
| 68 | |
| 69 | str += strcspn(str, delim); |
| 70 | |
| 71 | if (*str) |
| 72 | *str++ = '\0'; |
| 73 | |
| 74 | *nextp = str; |
| 75 | |
| 76 | return ret; |
| 77 | } |
| 78 | |
| 79 | #endif // if !defined(HAVE_STRTOK_R) |
| 80 | |
| 81 | using namespace x265; |
| 82 | |
| 83 | extern "C" |
| 84 | x265_param *x265_param_alloc() |
| 85 | { |
| 86 | return (x265_param*)x265_malloc(sizeof(x265_param)); |
| 87 | } |
| 88 | |
| 89 | extern "C" |
| 90 | void x265_param_free(x265_param *p) |
| 91 | { |
| 92 | return x265_free(p); |
| 93 | } |
| 94 | |
| 95 | extern "C" |
| 96 | void x265_param_default(x265_param *param) |
| 97 | { |
| 98 | memset(param, 0, sizeof(x265_param)); |
| 99 | |
| 100 | /* Applying default values to all elements in the param structure */ |
| 101 | param->cpuid = x265::cpu_detect(); |
| 102 | param->bEnableWavefront = 1; |
| 103 | param->poolNumThreads = 0; |
| 104 | param->frameNumThreads = 0; |
| 105 | |
| 106 | param->logLevel = X265_LOG_INFO; |
| 107 | param->csvfn = NULL; |
| 108 | param->rc.lambdaFileName = NULL; |
| 109 | param->bLogCuStats = 0; |
| 110 | param->decodedPictureHashSEI = 0; |
| 111 | |
| 112 | /* Quality Measurement Metrics */ |
| 113 | param->bEnablePsnr = 0; |
| 114 | param->bEnableSsim = 0; |
| 115 | |
| 116 | /* Source specifications */ |
| 117 | param->internalBitDepth = x265_max_bit_depth; |
| 118 | param->internalCsp = X265_CSP_I420; |
| 119 | |
| 120 | param->levelIdc = 0; |
| 121 | param->bHighTier = 0; |
| 122 | param->interlaceMode = 0; |
| 123 | param->bRepeatHeaders = 0; |
| 124 | param->bEnableAccessUnitDelimiters = 0; |
| 125 | param->bEmitHRDSEI = 0; |
| 126 | param->bEmitInfoSEI = 1; |
| 127 | |
| 128 | /* CU definitions */ |
| 129 | param->maxCUSize = 64; |
| 130 | param->tuQTMaxInterDepth = 1; |
| 131 | param->tuQTMaxIntraDepth = 1; |
| 132 | |
| 133 | /* Coding Structure */ |
| 134 | param->keyframeMin = 0; |
| 135 | param->keyframeMax = 250; |
| 136 | param->bOpenGOP = 1; |
| 137 | param->bframes = 4; |
| 138 | param->lookaheadDepth = 20; |
| 139 | param->bFrameAdaptive = X265_B_ADAPT_TRELLIS; |
| 140 | param->bBPyramid = 1; |
| 141 | param->scenecutThreshold = 40; /* Magic number pulled in from x264 */ |
| 142 | |
| 143 | /* Intra Coding Tools */ |
| 144 | param->bEnableConstrainedIntra = 0; |
| 145 | param->bEnableStrongIntraSmoothing = 1; |
| 146 | param->bEnableFastIntra = 0; |
| 147 | |
| 148 | /* Inter Coding tools */ |
| 149 | param->searchMethod = X265_HEX_SEARCH; |
| 150 | param->subpelRefine = 2; |
| 151 | param->searchRange = 57; |
| 152 | param->maxNumMergeCand = 2; |
| 153 | param->bEnableWeightedPred = 1; |
| 154 | param->bEnableWeightedBiPred = 0; |
| 155 | param->bEnableEarlySkip = 0; |
| 156 | param->bEnableCbfFastMode = 0; |
| 157 | param->bEnableAMP = 0; |
| 158 | param->bEnableRectInter = 0; |
| 159 | param->rdLevel = 3; |
| 160 | param->bEnableSignHiding = 1; |
| 161 | param->bEnableTransformSkip = 0; |
| 162 | param->bEnableTSkipFast = 0; |
| 163 | param->maxNumReferences = 3; |
| 164 | param->bEnableTemporalMvp = 1; |
| 165 | |
| 166 | /* Loop Filter */ |
| 167 | param->bEnableLoopFilter = 1; |
| 168 | |
| 169 | /* SAO Loop Filter */ |
| 170 | param->bEnableSAO = 1; |
| 171 | param->bSaoNonDeblocked = 0; |
| 172 | |
| 173 | /* Coding Quality */ |
| 174 | param->cbQpOffset = 0; |
| 175 | param->crQpOffset = 0; |
| 176 | param->rdPenalty = 0; |
| 177 | param->psyRd = 0.0; |
| 178 | param->psyRdoq = 0.0; |
| 179 | param->bIntraInBFrames = 0; |
| 180 | param->bLossless = 0; |
| 181 | param->bCULossless = 0; |
| 182 | |
| 183 | /* Rate control options */ |
| 184 | param->rc.vbvMaxBitrate = 0; |
| 185 | param->rc.vbvBufferSize = 0; |
| 186 | param->rc.vbvBufferInit = 0.9; |
| 187 | param->rc.rfConstant = 28; |
| 188 | param->rc.bitrate = 0; |
| 189 | param->rc.rateTolerance = 1.0; |
| 190 | param->rc.qCompress = 0.6; |
| 191 | param->rc.ipFactor = 1.4f; |
| 192 | param->rc.pbFactor = 1.3f; |
| 193 | param->rc.qpStep = 4; |
| 194 | param->rc.rateControlMode = X265_RC_CRF; |
| 195 | param->rc.qp = 32; |
| 196 | param->rc.aqMode = X265_AQ_AUTO_VARIANCE; |
| 197 | param->rc.aqStrength = 1.0; |
| 198 | param->rc.cuTree = 1; |
| 199 | param->rc.rfConstantMax = 0; |
| 200 | param->rc.rfConstantMin = 0; |
| 201 | param->rc.bStatRead = 0; |
| 202 | param->rc.bStatWrite = 0; |
| 203 | param->rc.statFileName = NULL; |
| 204 | param->rc.complexityBlur = 20; |
| 205 | param->rc.qblur = 0.5; |
| 206 | param->rc.bEnableSlowFirstPass = 0; |
| 207 | |
| 208 | /* Video Usability Information (VUI) */ |
| 209 | param->vui.aspectRatioIdc = 0; |
| 210 | param->vui.sarWidth = 0; |
| 211 | param->vui.sarHeight = 0; |
| 212 | param->vui.bEnableOverscanAppropriateFlag = 0; |
| 213 | param->vui.bEnableVideoSignalTypePresentFlag = 0; |
| 214 | param->vui.videoFormat = 5; |
| 215 | param->vui.bEnableVideoFullRangeFlag = 0; |
| 216 | param->vui.bEnableColorDescriptionPresentFlag = 0; |
| 217 | param->vui.colorPrimaries = 2; |
| 218 | param->vui.transferCharacteristics = 2; |
| 219 | param->vui.matrixCoeffs = 2; |
| 220 | param->vui.bEnableChromaLocInfoPresentFlag = 0; |
| 221 | param->vui.chromaSampleLocTypeTopField = 0; |
| 222 | param->vui.chromaSampleLocTypeBottomField = 0; |
| 223 | param->vui.bEnableDefaultDisplayWindowFlag = 0; |
| 224 | param->vui.defDispWinLeftOffset = 0; |
| 225 | param->vui.defDispWinRightOffset = 0; |
| 226 | param->vui.defDispWinTopOffset = 0; |
| 227 | param->vui.defDispWinBottomOffset = 0; |
| 228 | } |
| 229 | |
| 230 | extern "C" |
| 231 | int x265_param_default_preset(x265_param *param, const char *preset, const char *tune) |
| 232 | { |
| 233 | x265_param_default(param); |
| 234 | |
| 235 | if (preset) |
| 236 | { |
| 237 | char *end; |
| 238 | int i = strtol(preset, &end, 10); |
| 239 | if (*end == 0 && i >= 0 && i < (int)(sizeof(x265_preset_names) / sizeof(*x265_preset_names) - 1)) |
| 240 | preset = x265_preset_names[i]; |
| 241 | |
| 242 | if (!strcmp(preset, "ultrafast")) |
| 243 | { |
| 244 | param->lookaheadDepth = 10; |
| 245 | param->scenecutThreshold = 0; // disable lookahead |
| 246 | param->maxCUSize = 32; |
| 247 | param->searchRange = 25; |
| 248 | param->bFrameAdaptive = 0; |
| 249 | param->subpelRefine = 0; |
| 250 | param->searchMethod = X265_DIA_SEARCH; |
| 251 | param->bEnableEarlySkip = 1; |
| 252 | param->bEnableSAO = 0; |
| 253 | param->bEnableSignHiding = 0; |
| 254 | param->bEnableWeightedPred = 0; |
| 255 | param->rdLevel = 2; |
| 256 | param->maxNumReferences = 1; |
| 257 | param->bEnableLoopFilter = 0; |
| 258 | param->rc.aqStrength = 0.0; |
| 259 | param->rc.aqMode = X265_AQ_NONE; |
| 260 | param->rc.cuTree = 0; |
| 261 | param->bEnableFastIntra = 1; |
| 262 | } |
| 263 | else if (!strcmp(preset, "superfast")) |
| 264 | { |
| 265 | param->lookaheadDepth = 10; |
| 266 | param->maxCUSize = 32; |
| 267 | param->searchRange = 44; |
| 268 | param->bFrameAdaptive = 0; |
| 269 | param->subpelRefine = 1; |
| 270 | param->bEnableEarlySkip = 1; |
| 271 | param->bEnableWeightedPred = 0; |
| 272 | param->rdLevel = 2; |
| 273 | param->maxNumReferences = 1; |
| 274 | param->rc.aqStrength = 0.0; |
| 275 | param->rc.aqMode = X265_AQ_NONE; |
| 276 | param->rc.cuTree = 0; |
| 277 | param->bEnableSAO = 0; |
| 278 | param->bEnableFastIntra = 1; |
| 279 | } |
| 280 | else if (!strcmp(preset, "veryfast")) |
| 281 | { |
| 282 | param->lookaheadDepth = 15; |
| 283 | param->maxCUSize = 32; |
| 284 | param->bFrameAdaptive = 0; |
| 285 | param->subpelRefine = 1; |
| 286 | param->bEnableEarlySkip = 1; |
| 287 | param->rdLevel = 2; |
| 288 | param->maxNumReferences = 1; |
| 289 | param->rc.cuTree = 0; |
| 290 | param->bEnableFastIntra = 1; |
| 291 | } |
| 292 | else if (!strcmp(preset, "faster")) |
| 293 | { |
| 294 | param->lookaheadDepth = 15; |
| 295 | param->bFrameAdaptive = 0; |
| 296 | param->bEnableEarlySkip = 1; |
| 297 | param->rdLevel = 2; |
| 298 | param->maxNumReferences = 1; |
| 299 | param->rc.cuTree = 0; |
| 300 | param->bEnableFastIntra = 1; |
| 301 | } |
| 302 | else if (!strcmp(preset, "fast")) |
| 303 | { |
| 304 | param->lookaheadDepth = 15; |
| 305 | param->bFrameAdaptive = 0; |
| 306 | param->rdLevel = 2; |
| 307 | param->maxNumReferences = 2; |
| 308 | param->bEnableFastIntra = 1; |
| 309 | } |
| 310 | else if (!strcmp(preset, "medium")) |
| 311 | { |
| 312 | /* defaults */ |
| 313 | } |
| 314 | else if (!strcmp(preset, "slow")) |
| 315 | { |
| 316 | param->bEnableRectInter = 1; |
| 317 | param->lookaheadDepth = 25; |
| 318 | param->rdLevel = 4; |
| 319 | param->subpelRefine = 3; |
| 320 | param->maxNumMergeCand = 3; |
| 321 | param->searchMethod = X265_STAR_SEARCH; |
| 322 | } |
| 323 | else if (!strcmp(preset, "slower")) |
| 324 | { |
| 325 | param->bEnableWeightedBiPred = 1; |
| 326 | param->bEnableAMP = 1; |
| 327 | param->bEnableRectInter = 1; |
| 328 | param->lookaheadDepth = 30; |
| 329 | param->bframes = 8; |
| 330 | param->tuQTMaxInterDepth = 2; |
| 331 | param->tuQTMaxIntraDepth = 2; |
| 332 | param->rdLevel = 6; |
| 333 | param->subpelRefine = 3; |
| 334 | param->maxNumMergeCand = 3; |
| 335 | param->searchMethod = X265_STAR_SEARCH; |
| 336 | param->bIntraInBFrames = 1; |
| 337 | } |
| 338 | else if (!strcmp(preset, "veryslow")) |
| 339 | { |
| 340 | param->bEnableWeightedBiPred = 1; |
| 341 | param->bEnableAMP = 1; |
| 342 | param->bEnableRectInter = 1; |
| 343 | param->lookaheadDepth = 40; |
| 344 | param->bframes = 8; |
| 345 | param->tuQTMaxInterDepth = 3; |
| 346 | param->tuQTMaxIntraDepth = 3; |
| 347 | param->rdLevel = 6; |
| 348 | param->subpelRefine = 4; |
| 349 | param->maxNumMergeCand = 4; |
| 350 | param->searchMethod = X265_STAR_SEARCH; |
| 351 | param->maxNumReferences = 5; |
| 352 | param->bIntraInBFrames = 1; |
| 353 | } |
| 354 | else if (!strcmp(preset, "placebo")) |
| 355 | { |
| 356 | param->bEnableWeightedBiPred = 1; |
| 357 | param->bEnableAMP = 1; |
| 358 | param->bEnableRectInter = 1; |
| 359 | param->lookaheadDepth = 60; |
| 360 | param->searchRange = 92; |
| 361 | param->bframes = 8; |
| 362 | param->tuQTMaxInterDepth = 4; |
| 363 | param->tuQTMaxIntraDepth = 4; |
| 364 | param->rdLevel = 6; |
| 365 | param->subpelRefine = 5; |
| 366 | param->maxNumMergeCand = 5; |
| 367 | param->searchMethod = X265_STAR_SEARCH; |
| 368 | param->bEnableTransformSkip = 1; |
| 369 | param->maxNumReferences = 5; |
| 370 | param->rc.bEnableSlowFirstPass = 1; |
| 371 | param->bIntraInBFrames = 1; |
| 372 | // TODO: optimized esa |
| 373 | } |
| 374 | else |
| 375 | return -1; |
| 376 | } |
| 377 | if (tune) |
| 378 | { |
| 379 | if (!strcmp(tune, "psnr")) |
| 380 | { |
| 381 | param->rc.aqStrength = 0.0; |
| 382 | param->psyRd = 0.0; |
| 383 | param->psyRdoq = 0.0; |
| 384 | } |
| 385 | else if (!strcmp(tune, "ssim")) |
| 386 | { |
| 387 | param->rc.aqMode = X265_AQ_AUTO_VARIANCE; |
| 388 | param->psyRd = 0.0; |
| 389 | param->psyRdoq = 0.0; |
| 390 | } |
| 391 | else if (!strcmp(tune, "fastdecode") || |
| 392 | !strcmp(tune, "fast-decode")) |
| 393 | { |
| 394 | param->bEnableLoopFilter = 0; |
| 395 | param->bEnableSAO = 0; |
| 396 | param->bEnableWeightedPred = 0; |
| 397 | param->bEnableWeightedBiPred = 0; |
| 398 | param->bIntraInBFrames = 0; |
| 399 | } |
| 400 | else if (!strcmp(tune, "zerolatency") || |
| 401 | !strcmp(tune, "zero-latency")) |
| 402 | { |
| 403 | param->bFrameAdaptive = 0; |
| 404 | param->bframes = 0; |
| 405 | param->lookaheadDepth = 0; |
| 406 | param->scenecutThreshold = 0; |
| 407 | param->rc.cuTree = 0; |
| 408 | } |
| 409 | else |
| 410 | return -1; |
| 411 | } |
| 412 | |
| 413 | return 0; |
| 414 | } |
| 415 | |
| 416 | static int x265_atobool(const char *str, bool& bError) |
| 417 | { |
| 418 | if (!strcmp(str, "1") || |
| 419 | !strcmp(str, "true") || |
| 420 | !strcmp(str, "yes")) |
| 421 | return 1; |
| 422 | if (!strcmp(str, "0") || |
| 423 | !strcmp(str, "false") || |
| 424 | !strcmp(str, "no")) |
| 425 | return 0; |
| 426 | bError = true; |
| 427 | return 0; |
| 428 | } |
| 429 | |
| 430 | static double x265_atof(const char *str, bool& bError) |
| 431 | { |
| 432 | char *end; |
| 433 | double v = strtod(str, &end); |
| 434 | |
| 435 | if (end == str || *end != '\0') |
| 436 | bError = true; |
| 437 | return v; |
| 438 | } |
| 439 | |
| 440 | static int parseName(const char *arg, const char * const * names, bool& bError) |
| 441 | { |
| 442 | for (int i = 0; names[i]; i++) |
| 443 | { |
| 444 | if (!strcmp(arg, names[i])) |
| 445 | { |
| 446 | return i; |
| 447 | } |
| 448 | } |
| 449 | |
| 450 | return x265_atoi(arg, bError); |
| 451 | } |
| 452 | |
| 453 | /* internal versions of string-to-int with additional error checking */ |
| 454 | #undef atoi |
| 455 | #undef atof |
| 456 | #define atoi(str) x265_atoi(str, bError) |
| 457 | #define atof(str) x265_atof(str, bError) |
| 458 | #define atobool(str) (bNameWasBool = true, x265_atobool(str, bError)) |
| 459 | |
| 460 | extern "C" |
| 461 | int x265_param_parse(x265_param *p, const char *name, const char *value) |
| 462 | { |
| 463 | bool bError = false; |
| 464 | bool bNameWasBool = false; |
| 465 | bool bValueWasNull = !value; |
| 466 | char nameBuf[64]; |
| 467 | |
| 468 | if (!name) |
| 469 | return X265_PARAM_BAD_NAME; |
| 470 | |
| 471 | // skip -- prefix if provided |
| 472 | if (name[0] == '-' && name[1] == '-') |
| 473 | name += 2; |
| 474 | |
| 475 | // s/_/-/g |
| 476 | if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_')) |
| 477 | { |
| 478 | char *c; |
| 479 | strcpy(nameBuf, name); |
| 480 | while ((c = strchr(nameBuf, '_')) != 0) |
| 481 | { |
| 482 | *c = '-'; |
| 483 | } |
| 484 | |
| 485 | name = nameBuf; |
| 486 | } |
| 487 | |
| 488 | if (!strncmp(name, "no-", 3)) |
| 489 | { |
| 490 | name += 3; |
| 491 | value = !value || x265_atobool(value, bError) ? "false" : "true"; |
| 492 | } |
| 493 | else if (!strncmp(name, "no", 2)) |
| 494 | { |
| 495 | name += 2; |
| 496 | value = !value || x265_atobool(value, bError) ? "false" : "true"; |
| 497 | } |
| 498 | else if (!value) |
| 499 | value = "true"; |
| 500 | else if (value[0] == '=') |
| 501 | value++; |
| 502 | |
| 503 | #if defined(_MSC_VER) |
| 504 | #pragma warning(disable: 4127) // conditional expression is constant |
| 505 | #endif |
| 506 | #define OPT(STR) else if (!strcmp(name, STR)) |
| 507 | #define OPT2(STR1, STR2) else if (!strcmp(name, STR1) || !strcmp(name, STR2)) |
| 508 | if (0) ; |
| 509 | OPT("asm") |
| 510 | { |
| 511 | if (bValueWasNull) |
| 512 | p->cpuid = atobool(value); |
| 513 | else |
| 514 | p->cpuid = parseCpuName(value, bError); |
| 515 | } |
| 516 | OPT("fps") |
| 517 | { |
| 518 | if (sscanf(value, "%u/%u", &p->fpsNum, &p->fpsDenom) == 2) |
| 519 | ; |
| 520 | else |
| 521 | { |
| 522 | float fps = (float)atof(value); |
| 523 | if (fps > 0 && fps <= INT_MAX / 1000) |
| 524 | { |
| 525 | p->fpsNum = (int)(fps * 1000 + .5); |
| 526 | p->fpsDenom = 1000; |
| 527 | } |
| 528 | else |
| 529 | { |
| 530 | p->fpsNum = atoi(value); |
| 531 | p->fpsDenom = 1; |
| 532 | } |
| 533 | } |
| 534 | } |
| 535 | OPT("csv") p->csvfn = value; |
| 536 | OPT("scaling-list") p->scalingLists = value; |
| 537 | OPT("lambda-file") p->rc.lambdaFileName = value; |
| 538 | OPT("threads") p->poolNumThreads = atoi(value); |
| 539 | OPT("frame-threads") p->frameNumThreads = atoi(value); |
| 540 | OPT("pmode") p->bDistributeModeAnalysis = atobool(value); |
| 541 | OPT("pme") p->bDistributeMotionEstimation = atobool(value); |
| 542 | OPT2("level-idc", "level") |
| 543 | { |
| 544 | /* allow "5.1" or "51", both converted to integer 51 */ |
| 545 | if (atof(value) < 7) |
| 546 | p->levelIdc = (int)(10 * atof(value) + .5); |
| 547 | else |
| 548 | p->levelIdc = atoi(value); |
| 549 | } |
| 550 | OPT("high-tier") p->bHighTier = atobool(value); |
| 551 | OPT2("log-level", "log") |
| 552 | { |
| 553 | p->logLevel = atoi(value); |
| 554 | if (bError) |
| 555 | { |
| 556 | bError = false; |
| 557 | p->logLevel = parseName(value, logLevelNames, bError) - 1; |
| 558 | } |
| 559 | } |
| 560 | OPT("cu-stats") p->bLogCuStats = atobool(value); |
| 561 | OPT("repeat-headers") p->bRepeatHeaders = atobool(value); |
| 562 | OPT("wpp") p->bEnableWavefront = atobool(value); |
| 563 | OPT("ctu") p->maxCUSize = (uint32_t)atoi(value); |
| 564 | OPT("tu-intra-depth") p->tuQTMaxIntraDepth = (uint32_t)atoi(value); |
| 565 | OPT("tu-inter-depth") p->tuQTMaxInterDepth = (uint32_t)atoi(value); |
| 566 | OPT("subme") p->subpelRefine = atoi(value); |
| 567 | OPT("merange") p->searchRange = atoi(value); |
| 568 | OPT("rect") p->bEnableRectInter = atobool(value); |
| 569 | OPT("amp") p->bEnableAMP = atobool(value); |
| 570 | OPT("max-merge") p->maxNumMergeCand = (uint32_t)atoi(value); |
| 571 | OPT("temporal-mvp") p->bEnableTemporalMvp = atobool(value); |
| 572 | OPT("early-skip") p->bEnableEarlySkip = atobool(value); |
| 573 | OPT("fast-cbf") p->bEnableCbfFastMode = atobool(value); |
| 574 | OPT("rdpenalty") p->rdPenalty = atoi(value); |
| 575 | OPT("tskip") p->bEnableTransformSkip = atobool(value); |
| 576 | OPT("no-tskip-fast") p->bEnableTSkipFast = atobool(value); |
| 577 | OPT("tskip-fast") p->bEnableTSkipFast = atobool(value); |
| 578 | OPT("strong-intra-smoothing") p->bEnableStrongIntraSmoothing = atobool(value); |
| 579 | OPT("lossless") p->bLossless = atobool(value); |
| 580 | OPT("cu-lossless") p->bCULossless = atobool(value); |
| 581 | OPT("constrained-intra") p->bEnableConstrainedIntra = atobool(value); |
| 582 | OPT("fast-intra") p->bEnableFastIntra = atobool(value); |
| 583 | OPT("open-gop") p->bOpenGOP = atobool(value); |
| 584 | OPT("scenecut") |
| 585 | { |
| 586 | p->scenecutThreshold = atobool(value); |
| 587 | if (bError || p->scenecutThreshold) |
| 588 | { |
| 589 | bError = false; |
| 590 | p->scenecutThreshold = atoi(value); |
| 591 | } |
| 592 | } |
| 593 | OPT("keyint") p->keyframeMax = atoi(value); |
| 594 | OPT("min-keyint") p->keyframeMin = atoi(value); |
| 595 | OPT("rc-lookahead") p->lookaheadDepth = atoi(value); |
| 596 | OPT("bframes") p->bframes = atoi(value); |
| 597 | OPT("bframe-bias") p->bFrameBias = atoi(value); |
| 598 | OPT("b-adapt") |
| 599 | { |
| 600 | p->bFrameAdaptive = atobool(value); |
| 601 | if (bError || p->bFrameAdaptive) |
| 602 | { |
| 603 | bError = false; |
| 604 | p->bFrameAdaptive = atoi(value); |
| 605 | } |
| 606 | } |
| 607 | OPT("interlace") |
| 608 | { |
| 609 | p->interlaceMode = atobool(value); |
| 610 | if (bError || p->interlaceMode) |
| 611 | { |
| 612 | bError = false; |
| 613 | p->interlaceMode = parseName(value, x265_interlace_names, bError); |
| 614 | } |
| 615 | } |
| 616 | OPT("ref") p->maxNumReferences = atoi(value); |
| 617 | OPT("weightp") p->bEnableWeightedPred = atobool(value); |
| 618 | OPT("weightb") p->bEnableWeightedBiPred = atobool(value); |
| 619 | OPT("cbqpoffs") p->cbQpOffset = atoi(value); |
| 620 | OPT("crqpoffs") p->crQpOffset = atoi(value); |
| 621 | OPT("rd") p->rdLevel = atoi(value); |
| 622 | OPT("psy-rd") p->psyRd = atof(value); |
| 623 | OPT("psy-rdoq") p->psyRdoq = atof(value); |
| 624 | OPT("signhide") p->bEnableSignHiding = atobool(value); |
| 625 | OPT("b-intra") p->bIntraInBFrames = atobool(value); |
| 626 | OPT("lft") p->bEnableLoopFilter = atobool(value); |
| 627 | OPT("sao") p->bEnableSAO = atobool(value); |
| 628 | OPT("sao-non-deblock") p->bSaoNonDeblocked = atobool(value); |
| 629 | OPT("ssim") p->bEnableSsim = atobool(value); |
| 630 | OPT("psnr") p->bEnablePsnr = atobool(value); |
| 631 | OPT("hash") p->decodedPictureHashSEI = atoi(value); |
| 632 | OPT("aud") p->bEnableAccessUnitDelimiters = atobool(value); |
| 633 | OPT("info") p->bEmitInfoSEI = atobool(value); |
| 634 | OPT("b-pyramid") p->bBPyramid = atobool(value); |
| 635 | OPT("hrd") p->bEmitHRDSEI = atobool(value); |
| 636 | OPT2("ipratio", "ip-factor") p->rc.ipFactor = atof(value); |
| 637 | OPT2("pbratio", "pb-factor") p->rc.pbFactor = atof(value); |
| 638 | OPT("aq-mode") p->rc.aqMode = atoi(value); |
| 639 | OPT("aq-strength") p->rc.aqStrength = atof(value); |
| 640 | OPT("vbv-maxrate") p->rc.vbvMaxBitrate = atoi(value); |
| 641 | OPT("vbv-bufsize") p->rc.vbvBufferSize = atoi(value); |
| 642 | OPT("vbv-init") p->rc.vbvBufferInit = atof(value); |
| 643 | OPT("crf-max") p->rc.rfConstantMax = atof(value); |
| 644 | OPT("crf-min") p->rc.rfConstantMin = atof(value); |
| 645 | OPT("crf") |
| 646 | { |
| 647 | p->rc.rfConstant = atof(value); |
| 648 | p->rc.rateControlMode = X265_RC_CRF; |
| 649 | } |
| 650 | OPT("bitrate") |
| 651 | { |
| 652 | p->rc.bitrate = atoi(value); |
| 653 | p->rc.rateControlMode = X265_RC_ABR; |
| 654 | } |
| 655 | OPT("qp") |
| 656 | { |
| 657 | p->rc.qp = atoi(value); |
| 658 | p->rc.rateControlMode = X265_RC_CQP; |
| 659 | } |
| 660 | OPT("input-res") bError |= sscanf(value, "%dx%d", &p->sourceWidth, &p->sourceHeight) != 2; |
| 661 | OPT("input-csp") p->internalCsp = parseName(value, x265_source_csp_names, bError); |
| 662 | OPT("me") p->searchMethod = parseName(value, x265_motion_est_names, bError); |
| 663 | OPT("cutree") p->rc.cuTree = atobool(value); |
| 664 | OPT("slow-firstpass") p->rc.bEnableSlowFirstPass = atobool(value); |
| 665 | OPT("analysis-mode") p->analysisMode = parseName(value, x265_analysis_names, bError); |
| 666 | OPT("sar") |
| 667 | { |
| 668 | p->vui.aspectRatioIdc = parseName(value, x265_sar_names, bError); |
| 669 | if (bError) |
| 670 | { |
| 671 | p->vui.aspectRatioIdc = X265_EXTENDED_SAR; |
| 672 | bError = sscanf(value, "%d:%d", &p->vui.sarWidth, &p->vui.sarHeight) != 2; |
| 673 | } |
| 674 | } |
| 675 | OPT("overscan") |
| 676 | { |
| 677 | if (!strcmp(value, "show")) |
| 678 | p->vui.bEnableOverscanInfoPresentFlag = 1; |
| 679 | else if (!strcmp(value, "crop")) |
| 680 | { |
| 681 | p->vui.bEnableOverscanInfoPresentFlag = 1; |
| 682 | p->vui.bEnableOverscanAppropriateFlag = 1; |
| 683 | } |
| 684 | else if (!strcmp(value, "undef")) |
| 685 | p->vui.bEnableOverscanInfoPresentFlag = 0; |
| 686 | else |
| 687 | bError = true; |
| 688 | } |
| 689 | OPT("videoformat") |
| 690 | { |
| 691 | p->vui.bEnableVideoSignalTypePresentFlag = 1; |
| 692 | p->vui.videoFormat = parseName(value, x265_video_format_names, bError); |
| 693 | } |
| 694 | OPT("range") |
| 695 | { |
| 696 | p->vui.bEnableVideoSignalTypePresentFlag = 1; |
| 697 | p->vui.bEnableVideoFullRangeFlag = parseName(value, x265_fullrange_names, bError); |
| 698 | } |
| 699 | OPT("colorprim") |
| 700 | { |
| 701 | p->vui.bEnableVideoSignalTypePresentFlag = 1; |
| 702 | p->vui.bEnableColorDescriptionPresentFlag = 1; |
| 703 | p->vui.colorPrimaries = parseName(value, x265_colorprim_names, bError); |
| 704 | } |
| 705 | OPT("transfer") |
| 706 | { |
| 707 | p->vui.bEnableVideoSignalTypePresentFlag = 1; |
| 708 | p->vui.bEnableColorDescriptionPresentFlag = 1; |
| 709 | p->vui.transferCharacteristics = parseName(value, x265_transfer_names, bError); |
| 710 | } |
| 711 | OPT("colormatrix") |
| 712 | { |
| 713 | p->vui.bEnableVideoSignalTypePresentFlag = 1; |
| 714 | p->vui.bEnableColorDescriptionPresentFlag = 1; |
| 715 | p->vui.matrixCoeffs = parseName(value, x265_colmatrix_names, bError); |
| 716 | } |
| 717 | OPT("chromaloc") |
| 718 | { |
| 719 | p->vui.bEnableChromaLocInfoPresentFlag = 1; |
| 720 | p->vui.chromaSampleLocTypeTopField = atoi(value); |
| 721 | p->vui.chromaSampleLocTypeBottomField = p->vui.chromaSampleLocTypeTopField; |
| 722 | } |
| 723 | OPT("crop-rect") |
| 724 | { |
| 725 | p->vui.bEnableDefaultDisplayWindowFlag = 1; |
| 726 | bError |= sscanf(value, "%d,%d,%d,%d", |
| 727 | &p->vui.defDispWinLeftOffset, |
| 728 | &p->vui.defDispWinTopOffset, |
| 729 | &p->vui.defDispWinRightOffset, |
| 730 | &p->vui.defDispWinBottomOffset) != 4; |
| 731 | } |
| 732 | OPT("nr") p->noiseReduction = atoi(value); |
| 733 | OPT("pass") |
| 734 | { |
| 735 | int pass = Clip3(0, 3, atoi(value)); |
| 736 | p->rc.bStatWrite = pass & 1; |
| 737 | p->rc.bStatRead = pass & 2; |
| 738 | } |
| 739 | OPT("stats") p->rc.statFileName = strdup(value); |
| 740 | else |
| 741 | return X265_PARAM_BAD_NAME; |
| 742 | #undef OPT |
| 743 | #undef atobool |
| 744 | #undef atoi |
| 745 | #undef atof |
| 746 | |
| 747 | bError |= bValueWasNull && !bNameWasBool; |
| 748 | return bError ? X265_PARAM_BAD_VALUE : 0; |
| 749 | } |
| 750 | |
| 751 | namespace x265 { |
| 752 | // internal encoder functions |
| 753 | |
| 754 | int x265_atoi(const char *str, bool& bError) |
| 755 | { |
| 756 | char *end; |
| 757 | int v = strtol(str, &end, 0); |
| 758 | |
| 759 | if (end == str || *end != '\0') |
| 760 | bError = true; |
| 761 | return v; |
| 762 | } |
| 763 | |
| 764 | /* cpu name can be: |
| 765 | * auto || true - x265::cpu_detect() |
| 766 | * false || no - disabled |
| 767 | * integer bitmap value |
| 768 | * comma separated list of SIMD names, eg: SSE4.1,XOP */ |
| 769 | int parseCpuName(const char *value, bool& bError) |
| 770 | { |
| 771 | if (!value) |
| 772 | { |
| 773 | bError = 1; |
| 774 | return 0; |
| 775 | } |
| 776 | int cpu; |
| 777 | if (isdigit(value[0])) |
| 778 | cpu = x265_atoi(value, bError); |
| 779 | else |
| 780 | cpu = !strcmp(value, "auto") || x265_atobool(value, bError) ? x265::cpu_detect() : 0; |
| 781 | |
| 782 | if (bError) |
| 783 | { |
| 784 | char *buf = strdup(value); |
| 785 | char *tok, *saveptr = NULL, *init; |
| 786 | bError = 0; |
| 787 | cpu = 0; |
| 788 | for (init = buf; (tok = strtok_r(init, ",", &saveptr)); init = NULL) |
| 789 | { |
| 790 | int i; |
| 791 | for (i = 0; x265::cpu_names[i].flags && strcasecmp(tok, x265::cpu_names[i].name); i++) |
| 792 | { |
| 793 | } |
| 794 | |
| 795 | cpu |= x265::cpu_names[i].flags; |
| 796 | if (!x265::cpu_names[i].flags) |
| 797 | bError = 1; |
| 798 | } |
| 799 | |
| 800 | free(buf); |
| 801 | if ((cpu & X265_CPU_SSSE3) && !(cpu & X265_CPU_SSE2_IS_SLOW)) |
| 802 | cpu |= X265_CPU_SSE2_IS_FAST; |
| 803 | } |
| 804 | |
| 805 | return cpu; |
| 806 | } |
| 807 | |
| 808 | static const int fixedRatios[][2] = |
| 809 | { |
| 810 | { 1, 1 }, |
| 811 | { 12, 11 }, |
| 812 | { 10, 11 }, |
| 813 | { 16, 11 }, |
| 814 | { 40, 33 }, |
| 815 | { 24, 11 }, |
| 816 | { 20, 11 }, |
| 817 | { 32, 11 }, |
| 818 | { 80, 33 }, |
| 819 | { 18, 11 }, |
| 820 | { 15, 11 }, |
| 821 | { 64, 33 }, |
| 822 | { 160, 99 }, |
| 823 | { 4, 3 }, |
| 824 | { 3, 2 }, |
| 825 | { 2, 1 }, |
| 826 | }; |
| 827 | |
| 828 | void setParamAspectRatio(x265_param *p, int width, int height) |
| 829 | { |
| 830 | p->vui.aspectRatioIdc = X265_EXTENDED_SAR; |
| 831 | p->vui.sarWidth = width; |
| 832 | p->vui.sarHeight = height; |
| 833 | for (size_t i = 0; i < sizeof(fixedRatios) / sizeof(fixedRatios[0]); i++) |
| 834 | { |
| 835 | if (width == fixedRatios[i][0] && height == fixedRatios[i][1]) |
| 836 | { |
| 837 | p->vui.aspectRatioIdc = (int)i + 1; |
| 838 | return; |
| 839 | } |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | void getParamAspectRatio(x265_param *p, int& width, int& height) |
| 844 | { |
| 845 | if (!p->vui.aspectRatioIdc) |
| 846 | { |
| 847 | width = height = 0; |
| 848 | } |
| 849 | else if ((size_t)p->vui.aspectRatioIdc <= sizeof(fixedRatios) / sizeof(fixedRatios[0])) |
| 850 | { |
| 851 | width = fixedRatios[p->vui.aspectRatioIdc - 1][0]; |
| 852 | height = fixedRatios[p->vui.aspectRatioIdc - 1][1]; |
| 853 | } |
| 854 | else if (p->vui.aspectRatioIdc == X265_EXTENDED_SAR) |
| 855 | { |
| 856 | width = p->vui.sarWidth; |
| 857 | height = p->vui.sarHeight; |
| 858 | } |
| 859 | else |
| 860 | { |
| 861 | width = height = 0; |
| 862 | } |
| 863 | } |
| 864 | |
| 865 | static inline int _confirm(x265_param *param, bool bflag, const char* message) |
| 866 | { |
| 867 | if (!bflag) |
| 868 | return 0; |
| 869 | |
| 870 | x265_log(param, X265_LOG_ERROR, "%s\n", message); |
| 871 | return 1; |
| 872 | } |
| 873 | |
| 874 | int x265_check_params(x265_param *param) |
| 875 | { |
| 876 | #define CHECK(expr, msg) check_failed |= _confirm(param, expr, msg) |
| 877 | int check_failed = 0; /* abort if there is a fatal configuration problem */ |
| 878 | |
| 879 | CHECK(param->maxCUSize != 64 && param->maxCUSize != 32 && param->maxCUSize != 16, |
| 880 | "max ctu size must be 16, 32, or 64"); |
| 881 | if (check_failed == 1) |
| 882 | return check_failed; |
| 883 | |
| 884 | uint32_t maxLog2CUSize = (uint32_t)g_log2Size[param->maxCUSize]; |
| 885 | uint32_t tuQTMaxLog2Size = X265_MIN(maxLog2CUSize, 5); |
| 886 | uint32_t tuQTMinLog2Size = 2; //log2(4) |
| 887 | |
| 888 | /* These checks might be temporary */ |
| 889 | #if HIGH_BIT_DEPTH |
| 890 | CHECK(param->internalBitDepth != 10, |
| 891 | "x265 was compiled for 10bit encodes, only 10bit internal depth supported"); |
| 892 | #else |
| 893 | CHECK(param->internalBitDepth != 8, |
| 894 | "x265 was compiled for 8bit encodes, only 8bit internal depth supported"); |
| 895 | #endif |
| 896 | |
| 897 | CHECK(param->rc.qp < -6 * (param->internalBitDepth - 8) || param->rc.qp > 51, |
| 898 | "QP exceeds supported range (-QpBDOffsety to 51)"); |
| 899 | CHECK(param->fpsNum == 0 || param->fpsDenom == 0, |
| 900 | "Frame rate numerator and denominator must be specified"); |
| 901 | CHECK(param->interlaceMode < 0 || param->interlaceMode > 2, |
| 902 | "Interlace mode must be 0 (progressive) 1 (top-field first) or 2 (bottom field first)"); |
| 903 | CHECK(param->searchMethod<0 || param->searchMethod> X265_FULL_SEARCH, |
| 904 | "Search method is not supported value (0:DIA 1:HEX 2:UMH 3:HM 5:FULL)"); |
| 905 | CHECK(param->searchRange < 0, |
| 906 | "Search Range must be more than 0"); |
| 907 | CHECK(param->searchRange >= 32768, |
| 908 | "Search Range must be less than 32768"); |
| 909 | CHECK(param->subpelRefine > X265_MAX_SUBPEL_LEVEL, |
| 910 | "subme must be less than or equal to X265_MAX_SUBPEL_LEVEL (7)"); |
| 911 | CHECK(param->subpelRefine < 0, |
| 912 | "subme must be greater than or equal to 0"); |
| 913 | CHECK(param->frameNumThreads < 0, |
| 914 | "frameNumThreads (--frame-threads) must be 0 or higher"); |
| 915 | CHECK(param->cbQpOffset < -12, "Min. Chroma Cb QP Offset is -12"); |
| 916 | CHECK(param->cbQpOffset > 12, "Max. Chroma Cb QP Offset is 12"); |
| 917 | CHECK(param->crQpOffset < -12, "Min. Chroma Cr QP Offset is -12"); |
| 918 | CHECK(param->crQpOffset > 12, "Max. Chroma Cr QP Offset is 12"); |
| 919 | |
| 920 | CHECK(tuQTMaxLog2Size > maxLog2CUSize, |
| 921 | "QuadtreeTULog2MaxSize must be log2(maxCUSize) or smaller."); |
| 922 | |
| 923 | CHECK(param->tuQTMaxInterDepth < 1 || param->tuQTMaxInterDepth > 4, |
| 924 | "QuadtreeTUMaxDepthInter must be greater than 0 and less than 5"); |
| 925 | CHECK(maxLog2CUSize < tuQTMinLog2Size + param->tuQTMaxInterDepth - 1, |
| 926 | "QuadtreeTUMaxDepthInter must be less than or equal to the difference between log2(maxCUSize) and QuadtreeTULog2MinSize plus 1"); |
| 927 | CHECK(param->tuQTMaxIntraDepth < 1 || param->tuQTMaxIntraDepth > 4, |
| 928 | "QuadtreeTUMaxDepthIntra must be greater 0 and less than 5"); |
| 929 | CHECK(maxLog2CUSize < tuQTMinLog2Size + param->tuQTMaxIntraDepth - 1, |
| 930 | "QuadtreeTUMaxDepthInter must be less than or equal to the difference between log2(maxCUSize) and QuadtreeTULog2MinSize plus 1"); |
| 931 | |
| 932 | CHECK(param->maxNumMergeCand < 1, "MaxNumMergeCand must be 1 or greater."); |
| 933 | CHECK(param->maxNumMergeCand > 5, "MaxNumMergeCand must be 5 or smaller."); |
| 934 | |
| 935 | CHECK(param->maxNumReferences < 1, "maxNumReferences must be 1 or greater."); |
| 936 | CHECK(param->maxNumReferences > MAX_NUM_REF, "maxNumReferences must be 16 or smaller."); |
| 937 | |
| 938 | CHECK(param->sourceWidth < (int)param->maxCUSize || param->sourceHeight < (int)param->maxCUSize, |
| 939 | "Picture size must be at least one CTU"); |
| 940 | CHECK(param->internalCsp < X265_CSP_I420 || X265_CSP_I444 < param->internalCsp, |
| 941 | "Color space must be i420, i422, or i444"); |
| 942 | CHECK(param->sourceWidth & !!CHROMA_H_SHIFT(param->internalCsp), |
| 943 | "Picture width must be an integer multiple of the specified chroma subsampling"); |
| 944 | CHECK(param->sourceHeight & !!CHROMA_V_SHIFT(param->internalCsp), |
| 945 | "Picture height must be an integer multiple of the specified chroma subsampling"); |
| 946 | |
| 947 | CHECK(param->rc.rateControlMode > X265_RC_CRF || param->rc.rateControlMode < X265_RC_ABR, |
| 948 | "Rate control mode is out of range"); |
| 949 | CHECK(param->rdLevel < 0 || param->rdLevel > 6, |
| 950 | "RD Level is out of range"); |
| 951 | CHECK(param->bframes > param->lookaheadDepth && !param->rc.bStatRead, |
| 952 | "Lookahead depth must be greater than the max consecutive bframe count"); |
| 953 | CHECK(param->bframes < 0, |
| 954 | "bframe count should be greater than zero"); |
| 955 | CHECK(param->bframes > X265_BFRAME_MAX, |
| 956 | "max consecutive bframe count must be 16 or smaller"); |
| 957 | CHECK(param->lookaheadDepth > X265_LOOKAHEAD_MAX, |
| 958 | "Lookahead depth must be less than 256"); |
| 959 | CHECK(param->rc.aqMode < X265_AQ_NONE || X265_AQ_AUTO_VARIANCE < param->rc.aqMode, |
| 960 | "Aq-Mode is out of range"); |
| 961 | CHECK(param->rc.aqStrength < 0 || param->rc.aqStrength > 3, |
| 962 | "Aq-Strength is out of range"); |
| 963 | CHECK(param->psyRd < 0 || 2.0 < param->psyRd, "Psy-rd strength must be between 0 and 2.0"); |
| 964 | CHECK(param->psyRdoq < 0 || 50.0 < param->psyRdoq, "Psy-rdoq strength must be between 0 and 50.0"); |
| 965 | CHECK(param->bEnableWavefront < 0, "WaveFrontSynchro cannot be negative"); |
| 966 | CHECK(!param->bEnableWavefront && param->rc.vbvBufferSize, "VBV requires wave-front parallelism (--wpp)"); |
| 967 | CHECK((param->vui.aspectRatioIdc < 0 |
| 968 | || param->vui.aspectRatioIdc > 16) |
| 969 | && param->vui.aspectRatioIdc != X265_EXTENDED_SAR, |
| 970 | "Sample Aspect Ratio must be 0-16 or 255"); |
| 971 | CHECK(param->vui.aspectRatioIdc == X265_EXTENDED_SAR && param->vui.sarWidth <= 0, |
| 972 | "Sample Aspect Ratio width must be greater than 0"); |
| 973 | CHECK(param->vui.aspectRatioIdc == X265_EXTENDED_SAR && param->vui.sarHeight <= 0, |
| 974 | "Sample Aspect Ratio height must be greater than 0"); |
| 975 | CHECK(param->vui.videoFormat < 0 || param->vui.videoFormat > 5, |
| 976 | "Video Format must be component," |
| 977 | " pal, ntsc, secam, mac or undef"); |
| 978 | CHECK(param->vui.colorPrimaries < 0 |
| 979 | || param->vui.colorPrimaries > 9 |
| 980 | || param->vui.colorPrimaries == 3, |
| 981 | "Color Primaries must be undef, bt709, bt470m," |
| 982 | " bt470bg, smpte170m, smpte240m, film or bt2020"); |
| 983 | CHECK(param->vui.transferCharacteristics < 0 |
| 984 | || param->vui.transferCharacteristics > 15 |
| 985 | || param->vui.transferCharacteristics == 3, |
| 986 | "Transfer Characteristics must be undef, bt709, bt470m, bt470bg," |
| 987 | " smpte170m, smpte240m, linear, log100, log316, iec61966-2-4, bt1361e," |
| 988 | " iec61966-2-1, bt2020-10 or bt2020-12"); |
| 989 | CHECK(param->vui.matrixCoeffs < 0 |
| 990 | || param->vui.matrixCoeffs > 10 |
| 991 | || param->vui.matrixCoeffs == 3, |
| 992 | "Matrix Coefficients must be undef, bt709, fcc, bt470bg, smpte170m," |
| 993 | " smpte240m, GBR, YCgCo, bt2020nc or bt2020c"); |
| 994 | CHECK(param->vui.chromaSampleLocTypeTopField < 0 |
| 995 | || param->vui.chromaSampleLocTypeTopField > 5, |
| 996 | "Chroma Sample Location Type Top Field must be 0-5"); |
| 997 | CHECK(param->vui.chromaSampleLocTypeBottomField < 0 |
| 998 | || param->vui.chromaSampleLocTypeBottomField > 5, |
| 999 | "Chroma Sample Location Type Bottom Field must be 0-5"); |
| 1000 | CHECK(param->vui.defDispWinLeftOffset < 0, |
| 1001 | "Default Display Window Left Offset must be 0 or greater"); |
| 1002 | CHECK(param->vui.defDispWinRightOffset < 0, |
| 1003 | "Default Display Window Right Offset must be 0 or greater"); |
| 1004 | CHECK(param->vui.defDispWinTopOffset < 0, |
| 1005 | "Default Display Window Top Offset must be 0 or greater"); |
| 1006 | CHECK(param->vui.defDispWinBottomOffset < 0, |
| 1007 | "Default Display Window Bottom Offset must be 0 or greater"); |
| 1008 | CHECK(param->rc.rfConstant < -6 * (param->internalBitDepth - 8) || param->rc.rfConstant > 51, |
| 1009 | "Valid quality based range: -qpBDOffsetY to 51"); |
| 1010 | CHECK(param->rc.rfConstantMax < -6 * (param->internalBitDepth - 8) || param->rc.rfConstantMax > 51, |
| 1011 | "Valid quality based range: -qpBDOffsetY to 51"); |
| 1012 | CHECK(param->rc.rfConstantMin < -6 * (param->internalBitDepth - 8) || param->rc.rfConstantMin > 51, |
| 1013 | "Valid quality based range: -qpBDOffsetY to 51"); |
| 1014 | CHECK(param->bFrameAdaptive < 0 || param->bFrameAdaptive > 2, |
| 1015 | "Valid adaptive b scheduling values 0 - none, 1 - fast, 2 - full"); |
| 1016 | CHECK(param->logLevel<-1 || param->logLevel> X265_LOG_FULL, |
| 1017 | "Valid Logging level -1:none 0:error 1:warning 2:info 3:debug 4:full"); |
| 1018 | CHECK(param->scenecutThreshold < 0, |
| 1019 | "scenecutThreshold must be greater than 0"); |
| 1020 | CHECK(param->rdPenalty < 0 || param->rdPenalty > 2, |
| 1021 | "Valid penalty for 32x32 intra TU in non-I slices. 0:disabled 1:RD-penalty 2:maximum"); |
| 1022 | CHECK(param->keyframeMax < -1, |
| 1023 | "Invalid max IDR period in frames. value should be greater than -1"); |
| 1024 | CHECK(param->decodedPictureHashSEI < 0 || param->decodedPictureHashSEI > 3, |
| 1025 | "Invalid hash option. Decoded Picture Hash SEI 0: disabled, 1: MD5, 2: CRC, 3: Checksum"); |
| 1026 | CHECK(param->rc.vbvBufferSize < 0, |
| 1027 | "Size of the vbv buffer can not be less than zero"); |
| 1028 | CHECK(param->rc.vbvMaxBitrate < 0, |
| 1029 | "Maximum local bit rate can not be less than zero"); |
| 1030 | CHECK(param->rc.vbvBufferInit < 0, |
| 1031 | "Valid initial VBV buffer occupancy must be a fraction 0 - 1, or size in kbits"); |
| 1032 | CHECK(param->rc.bitrate < 0, |
| 1033 | "Target bitrate can not be less than zero"); |
| 1034 | if (param->noiseReduction) |
| 1035 | CHECK(100 > param->noiseReduction || param->noiseReduction > 1000, "Valid noise reduction range 100 - 1000"); |
| 1036 | CHECK(param->rc.rateControlMode == X265_RC_CRF && param->rc.bStatRead, |
| 1037 | "Constant rate-factor is incompatible with 2pass"); |
| 1038 | CHECK(param->rc.rateControlMode == X265_RC_CQP && param->rc.bStatRead, |
| 1039 | "Constant QP is incompatible with 2pass"); |
| 1040 | return check_failed; |
| 1041 | } |
| 1042 | |
| 1043 | void x265_param_apply_fastfirstpass(x265_param* param) |
| 1044 | { |
| 1045 | /* Set faster options in case of turbo firstpass */ |
| 1046 | if (param->rc.bStatWrite && !param->rc.bStatRead) |
| 1047 | { |
| 1048 | param->maxNumReferences = 1; |
| 1049 | param->maxNumMergeCand = 1; |
| 1050 | param->bEnableRectInter = 0; |
| 1051 | param->bEnableFastIntra = 1; |
| 1052 | param->bEnableAMP = 0; |
| 1053 | param->searchMethod = X265_DIA_SEARCH; |
| 1054 | param->subpelRefine = X265_MIN(2, param->subpelRefine); |
| 1055 | param->bEnableEarlySkip = 1; |
| 1056 | param->rdLevel = X265_MIN(2, param->rdLevel); |
| 1057 | } |
| 1058 | } |
| 1059 | |
| 1060 | int x265_set_globals(x265_param *param) |
| 1061 | { |
| 1062 | static int once /* = 0 */; |
| 1063 | |
| 1064 | if (ATOMIC_CAS32(&once, 0, 1) == 1) |
| 1065 | { |
| 1066 | if (param->maxCUSize != g_maxCUSize) |
| 1067 | { |
| 1068 | x265_log(param, X265_LOG_ERROR, "maxCUSize must be the same for all encoders in a single process"); |
| 1069 | return -1; |
| 1070 | } |
| 1071 | } |
| 1072 | else |
| 1073 | { |
| 1074 | uint32_t maxLog2CUSize = (uint32_t)g_log2Size[param->maxCUSize]; |
| 1075 | |
| 1076 | // set max CU width & height |
| 1077 | g_maxCUSize = param->maxCUSize; |
| 1078 | g_maxLog2CUSize = maxLog2CUSize; |
| 1079 | |
| 1080 | // compute actual CU depth with respect to config depth and max transform size |
| 1081 | g_maxCUDepth = maxLog2CUSize - MIN_LOG2_CU_SIZE; |
| 1082 | g_maxFullDepth = maxLog2CUSize - LOG2_UNIT_SIZE; |
| 1083 | |
| 1084 | // initialize partition order |
| 1085 | uint32_t* tmp = &g_zscanToRaster[0]; |
| 1086 | initZscanToRaster(g_maxFullDepth, 1, 0, tmp); |
| 1087 | initRasterToZscan(g_maxFullDepth); |
| 1088 | } |
| 1089 | return 0; |
| 1090 | } |
| 1091 | |
| 1092 | void x265_print_params(x265_param *param) |
| 1093 | { |
| 1094 | if (param->logLevel < X265_LOG_INFO) |
| 1095 | return; |
| 1096 | |
| 1097 | #if HIGH_BIT_DEPTH |
| 1098 | x265_log(param, X265_LOG_INFO, "Internal bit depth : %d\n", param->internalBitDepth); |
| 1099 | #endif |
| 1100 | if (param->interlaceMode) |
| 1101 | x265_log(param, X265_LOG_INFO, "Interlaced field inputs : %s\n", x265_interlace_names[param->interlaceMode]); |
| 1102 | |
| 1103 | x265_log(param, X265_LOG_INFO, "CTU size / RQT depth inter / intra : %d / %d / %d\n", |
| 1104 | param->maxCUSize, param->tuQTMaxInterDepth, param->tuQTMaxIntraDepth); |
| 1105 | |
| 1106 | x265_log(param, X265_LOG_INFO, "ME / range / subpel / merge : %s / %d / %d / %d\n", |
| 1107 | x265_motion_est_names[param->searchMethod], param->searchRange, param->subpelRefine, param->maxNumMergeCand); |
| 1108 | |
| 1109 | if (param->keyframeMax != INT_MAX || param->scenecutThreshold) |
| 1110 | x265_log(param, X265_LOG_INFO, "Keyframe min / max / scenecut : %d / %d / %d\n", param->keyframeMin, param->keyframeMax, param->scenecutThreshold); |
| 1111 | else |
| 1112 | x265_log(param, X265_LOG_INFO, "Keyframe min / max / scenecut : disabled\n"); |
| 1113 | |
| 1114 | if (param->cbQpOffset || param->crQpOffset) |
| 1115 | x265_log(param, X265_LOG_INFO, "Cb/Cr QP Offset : %d / %d\n", param->cbQpOffset, param->crQpOffset); |
| 1116 | |
| 1117 | if (param->rdPenalty) |
| 1118 | x265_log(param, X265_LOG_INFO, "Intra 32x32 TU penalty type : %d\n", param->rdPenalty); |
| 1119 | |
| 1120 | x265_log(param, X265_LOG_INFO, "Lookahead / bframes / badapt : %d / %d / %d\n", param->lookaheadDepth, param->bframes, param->bFrameAdaptive); |
| 1121 | x265_log(param, X265_LOG_INFO, "b-pyramid / weightp / weightb / refs: %d / %d / %d / %d\n", |
| 1122 | param->bBPyramid, param->bEnableWeightedPred, param->bEnableWeightedBiPred, param->maxNumReferences); |
| 1123 | |
| 1124 | if (param->bLossless) |
| 1125 | x265_log(param, X265_LOG_INFO, "Rate Control : Lossless\n"); |
| 1126 | else switch (param->rc.rateControlMode) |
| 1127 | { |
| 1128 | case X265_RC_ABR: |
| 1129 | x265_log(param, X265_LOG_INFO, "Rate Control / AQ-Strength / CUTree : ABR-%d kbps / %0.1f / %d\n", param->rc.bitrate, |
| 1130 | param->rc.aqStrength, param->rc.cuTree); |
| 1131 | break; |
| 1132 | case X265_RC_CQP: |
| 1133 | x265_log(param, X265_LOG_INFO, "Rate Control / AQ-Strength / CUTree : CQP-%d / %0.1f / %d\n", param->rc.qp, param->rc.aqStrength, |
| 1134 | param->rc.cuTree); |
| 1135 | break; |
| 1136 | case X265_RC_CRF: |
| 1137 | x265_log(param, X265_LOG_INFO, "Rate Control / AQ-Strength / CUTree : CRF-%0.1f / %0.1f / %d\n", param->rc.rfConstant, |
| 1138 | param->rc.aqStrength, param->rc.cuTree); |
| 1139 | break; |
| 1140 | } |
| 1141 | |
| 1142 | if (param->rc.vbvBufferSize) |
| 1143 | x265_log(param, X265_LOG_INFO, "VBV/HRD buffer / max-rate / init : %d / %d / %.3f\n", |
| 1144 | param->rc.vbvBufferSize, param->rc.vbvMaxBitrate, param->rc.vbvBufferInit); |
| 1145 | |
| 1146 | x265_log(param, X265_LOG_INFO, "tools: "); |
| 1147 | #define TOOLOPT(FLAG, STR) if (FLAG) fprintf(stderr, "%s ", STR) |
| 1148 | TOOLOPT(param->bEnableRectInter, "rect"); |
| 1149 | TOOLOPT(param->bEnableAMP, "amp"); |
| 1150 | fprintf(stderr, "rd=%d ", param->rdLevel); |
| 1151 | if (param->psyRd > 0.) |
| 1152 | fprintf(stderr, "psy-rd=%.2lf ", param->psyRd); |
| 1153 | if (param->psyRdoq > 0.) |
| 1154 | fprintf(stderr, "psy-rdoq=%.2lf ", param->psyRdoq); |
| 1155 | TOOLOPT(param->bEnableEarlySkip, "esd"); |
| 1156 | TOOLOPT(param->bEnableCbfFastMode, "cfm"); |
| 1157 | if (param->noiseReduction) |
| 1158 | fprintf(stderr, "nr=%d ", param->noiseReduction); |
| 1159 | TOOLOPT(param->bEnableLoopFilter, "lft"); |
| 1160 | if (param->bEnableSAO) |
| 1161 | fprintf(stderr, "sao%s ", param->bSaoNonDeblocked ? "-non-deblock" : ""); |
| 1162 | TOOLOPT(param->bEnableSignHiding, "signhide"); |
| 1163 | TOOLOPT(param->bEnableConstrainedIntra, "cip"); |
| 1164 | TOOLOPT(param->bIntraInBFrames, "b-intra"); |
| 1165 | TOOLOPT(param->bEnableFastIntra, "fast-intra"); |
| 1166 | TOOLOPT(param->bEnableTemporalMvp, "tmvp"); |
| 1167 | if (param->bEnableTransformSkip) |
| 1168 | fprintf(stderr, "tskip%s ", param->bEnableTSkipFast ? "-fast" : ""); |
| 1169 | TOOLOPT(param->bCULossless, "cu-lossless"); |
| 1170 | TOOLOPT(param->rc.bStatWrite, "stats-write"); |
| 1171 | TOOLOPT(param->rc.bStatRead, "stats-read"); |
| 1172 | fprintf(stderr, "\n"); |
| 1173 | fflush(stderr); |
| 1174 | } |
| 1175 | |
| 1176 | char *x265_param2string(x265_param *p) |
| 1177 | { |
| 1178 | char *buf, *s; |
| 1179 | |
| 1180 | buf = s = X265_MALLOC(char, MAXPARAMSIZE); |
| 1181 | if (!buf) |
| 1182 | return NULL; |
| 1183 | |
| 1184 | #define BOOL(param, cliopt) \ |
| 1185 | s += sprintf(s, " %s", (param) ? cliopt : "no-"cliopt); |
| 1186 | |
| 1187 | s += sprintf(s, "%dx%d", p->sourceWidth,p->sourceHeight); |
| 1188 | s += sprintf(s, " fps=%u/%u", p->fpsNum, p->fpsDenom); |
| 1189 | s += sprintf(s, " bitdepth=%d", p->internalBitDepth); |
| 1190 | BOOL(p->bEnableWavefront, "wpp"); |
| 1191 | s += sprintf(s, " ctu=%d", p->maxCUSize); |
| 1192 | s += sprintf(s, " tu-intra-depth=%d", p->tuQTMaxIntraDepth); |
| 1193 | s += sprintf(s, " tu-inter-depth=%d", p->tuQTMaxInterDepth); |
| 1194 | s += sprintf(s, " me=%d", p->searchMethod); |
| 1195 | s += sprintf(s, " subme=%d", p->subpelRefine); |
| 1196 | s += sprintf(s, " merange=%d", p->searchRange); |
| 1197 | BOOL(p->bEnableRectInter, "rect"); |
| 1198 | BOOL(p->bEnableAMP, "amp"); |
| 1199 | s += sprintf(s, " max-merge=%d", p->maxNumMergeCand); |
| 1200 | BOOL(p->bEnableTemporalMvp, "temporal-mvp"); |
| 1201 | BOOL(p->bEnableEarlySkip, "early-skip"); |
| 1202 | BOOL(p->bEnableCbfFastMode, "fast-cbf"); |
| 1203 | s += sprintf(s, " rdpenalty=%d", p->rdPenalty); |
| 1204 | BOOL(p->bEnableTransformSkip, "tskip"); |
| 1205 | BOOL(p->bEnableTSkipFast, "tskip-fast"); |
| 1206 | BOOL(p->bEnableStrongIntraSmoothing, "strong-intra-smoothing"); |
| 1207 | BOOL(p->bLossless, "lossless"); |
| 1208 | BOOL(p->bCULossless, "cu-lossless"); |
| 1209 | BOOL(p->bEnableConstrainedIntra, "constrained-intra"); |
| 1210 | BOOL(p->bEnableFastIntra, "fast-intra"); |
| 1211 | BOOL(p->bOpenGOP, "open-gop"); |
| 1212 | s += sprintf(s, " interlace=%d", p->interlaceMode); |
| 1213 | s += sprintf(s, " keyint=%d", p->keyframeMax); |
| 1214 | s += sprintf(s, " min-keyint=%d", p->keyframeMin); |
| 1215 | s += sprintf(s, " scenecut=%d", p->scenecutThreshold); |
| 1216 | s += sprintf(s, " rc-lookahead=%d", p->lookaheadDepth); |
| 1217 | s += sprintf(s, " bframes=%d", p->bframes); |
| 1218 | s += sprintf(s, " bframe-bias=%d", p->bFrameBias); |
| 1219 | s += sprintf(s, " b-adapt=%d", p->bFrameAdaptive); |
| 1220 | s += sprintf(s, " ref=%d", p->maxNumReferences); |
| 1221 | BOOL(p->bEnableWeightedPred, "weightp"); |
| 1222 | BOOL(p->bEnableWeightedBiPred, "weightb"); |
| 1223 | s += sprintf(s, " aq-mode=%d", p->rc.aqMode); |
| 1224 | s += sprintf(s, " aq-strength=%.2f", p->rc.aqStrength); |
| 1225 | s += sprintf(s, " cbqpoffs=%d", p->cbQpOffset); |
| 1226 | s += sprintf(s, " crqpoffs=%d", p->crQpOffset); |
| 1227 | s += sprintf(s, " rd=%d", p->rdLevel); |
| 1228 | s += sprintf(s, " psy-rd=%.2f", p->psyRd); |
| 1229 | s += sprintf(s, " psy-rdoq=%.2f", p->psyRdoq); |
| 1230 | BOOL(p->bEnableSignHiding, "signhide"); |
| 1231 | BOOL(p->bEnableLoopFilter, "lft"); |
| 1232 | BOOL(p->bEnableSAO, "sao"); |
| 1233 | BOOL(p->bSaoNonDeblocked, "sao-non-deblock"); |
| 1234 | BOOL(p->bBPyramid, "b-pyramid"); |
| 1235 | BOOL(p->rc.cuTree, "cutree"); |
| 1236 | s += sprintf(s, " rc=%s", p->rc.rateControlMode == X265_RC_ABR ? ( |
| 1237 | p->rc.bStatRead ? "2 pass" : p->rc.bitrate == p->rc.vbvMaxBitrate ? "cbr" : "abr") |
| 1238 | : p->rc.rateControlMode == X265_RC_CRF ? "crf" : "cqp"); |
| 1239 | if (p->rc.rateControlMode == X265_RC_ABR || p->rc.rateControlMode == X265_RC_CRF) |
| 1240 | { |
| 1241 | if (p->rc.rateControlMode == X265_RC_CRF) |
| 1242 | s += sprintf(s, " crf=%.1f", p->rc.rfConstant); |
| 1243 | else |
| 1244 | s += sprintf(s, " bitrate=%d ratetol=%.1f", |
| 1245 | p->rc.bitrate, p->rc.rateTolerance); |
| 1246 | s += sprintf(s, " qcomp=%.2f qpmin=%d qpmax=%d qpstep=%d", |
| 1247 | p->rc.qCompress, QP_MIN, QP_MAX_SPEC, p->rc.qpStep); |
| 1248 | if (p->rc.bStatRead) |
| 1249 | s += sprintf( s, " cplxblur=%.1f qblur=%.1f", |
| 1250 | p->rc.complexityBlur, p->rc.qblur); |
| 1251 | if (p->rc.vbvBufferSize) |
| 1252 | { |
| 1253 | s += sprintf(s, " vbv-maxrate=%d vbv-bufsize=%d", |
| 1254 | p->rc.vbvMaxBitrate, p->rc.vbvBufferSize); |
| 1255 | if (p->rc.rateControlMode == X265_RC_CRF) |
| 1256 | s += sprintf(s, " crf-max=%.1f", p->rc.rfConstantMax); |
| 1257 | } |
| 1258 | } |
| 1259 | else if (p->rc.rateControlMode == X265_RC_CQP) |
| 1260 | s += sprintf(s, " qp=%d", p->rc.qp); |
| 1261 | if (!(p->rc.rateControlMode == X265_RC_CQP && p->rc.qp == 0)) |
| 1262 | { |
| 1263 | s += sprintf(s, " ipratio=%.2f", p->rc.ipFactor); |
| 1264 | if (p->bframes) |
| 1265 | s += sprintf(s, " pbratio=%.2f", p->rc.pbFactor); |
| 1266 | } |
| 1267 | #undef BOOL |
| 1268 | return buf; |
| 1269 | } |
| 1270 | |
| 1271 | bool parseLambdaFile(x265_param *param) |
| 1272 | { |
| 1273 | if (!param->rc.lambdaFileName) |
| 1274 | return false; |
| 1275 | |
| 1276 | FILE *lfn = fopen(param->rc.lambdaFileName, "r"); |
| 1277 | if (!lfn) |
| 1278 | { |
| 1279 | x265_log(param, X265_LOG_ERROR, "unable to read lambda file <%s>\n", param->rc.lambdaFileName); |
| 1280 | return true; |
| 1281 | } |
| 1282 | |
| 1283 | char line[2048]; |
| 1284 | char *toksave = NULL, *tok = NULL, *buf = NULL; |
| 1285 | |
| 1286 | for (int t = 0; t < 3; t++) |
| 1287 | { |
| 1288 | double *table = t ? x265_lambda2_tab : x265_lambda_tab; |
| 1289 | |
| 1290 | for (int i = 0; i < QP_MAX_MAX + 1; i++) |
| 1291 | { |
| 1292 | double value; |
| 1293 | |
| 1294 | do |
| 1295 | { |
| 1296 | if (!tok) |
| 1297 | { |
| 1298 | /* consume a line of text file */ |
| 1299 | if (!fgets(line, sizeof(line), lfn)) |
| 1300 | { |
| 1301 | fclose(lfn); |
| 1302 | |
| 1303 | if (t < 2) |
| 1304 | { |
| 1305 | x265_log(param, X265_LOG_ERROR, "lambda file is incomplete\n"); |
| 1306 | return true; |
| 1307 | } |
| 1308 | else |
| 1309 | return false; |
| 1310 | } |
| 1311 | |
| 1312 | /* truncate at first hash */ |
| 1313 | char *hash = strchr(line, '#'); |
| 1314 | if (hash) *hash = 0; |
| 1315 | buf = line; |
| 1316 | } |
| 1317 | |
| 1318 | tok = strtok_r(buf, " ,", &toksave); |
| 1319 | buf = NULL; |
| 1320 | if (tok && sscanf(tok, "%lf", &value) == 1) |
| 1321 | break; |
| 1322 | } |
| 1323 | while (1); |
| 1324 | |
| 1325 | if (t == 2) |
| 1326 | { |
| 1327 | x265_log(param, X265_LOG_ERROR, "lambda file contains too many values\n"); |
| 1328 | fclose(lfn); |
| 1329 | return true; |
| 1330 | } |
| 1331 | else |
| 1332 | x265_log(param, X265_LOG_DEBUG, "lambda%c[%d] = %lf\n", t ? '2' : ' ', i, value); |
| 1333 | table[i] = value; |
| 1334 | } |
| 1335 | } |
| 1336 | |
| 1337 | fclose(lfn); |
| 1338 | return false; |
| 1339 | } |
| 1340 | |
| 1341 | } |