Minor refactoring of level checking

This commit is contained in:
Miika Metsoila 2017-11-20 13:25:26 +02:00
parent 4c1512e8c5
commit d249059d61

114
src/cfg.c
View file

@ -1453,6 +1453,27 @@ int kvz_config_validate(const kvz_config *const cfg)
} }
static int validate_hevc_level(const kvz_config *const cfg) { static int validate_hevc_level(const kvz_config *const cfg) {
static const struct { uint32_t lsr; uint32_t lps; } LEVEL_CONSTRAINTS[13] = {
{ 552'960, 36'864 }, // 1
{ 3'686'400, 122'880 }, // 2
{ 7'372'800, 245'760 }, // 2.1
{ 16'588'800, 552'960 }, // 3
{ 33'177'600, 983'040 }, // 3.1
{ 66'846'720, 2'228'224 }, // 4
{ 133'693'440, 2'228'224 }, // 4.1
{ 267'386'880, 8'912'896 }, // 5
{ 534'773'760, 8'912'896 }, // 5.1
{ 1'069'547'520, 8'912'896 }, // 5.2
{ 1'069'547'520, 35'651'584 }, // 6
{ 2'139'095'040, 35'651'584 }, // 6.1
{ 4'278'190'080, 35'651'584 }, // 6.2
};
int level_error = 0; int level_error = 0;
const char* level_err_prefix; const char* level_err_prefix;
@ -1462,64 +1483,48 @@ static int validate_hevc_level(const kvz_config *const cfg) {
level_err_prefix = "Level error"; level_err_prefix = "Level error";
} }
// max luma sample rate char lvl_idx;
unsigned long max_lsr;
// max luma picture size
unsigned int max_lps;
// check if the level is valid // check if the level is valid and get it's lsr and lps values
switch (cfg->level) { switch (cfg->level) {
case 10: case 10:
max_lsr = 552'960; lvl_idx = 0;
max_lps = 36'864;
break; break;
case 20: case 20:
max_lsr = 3'686'400; lvl_idx = 1;
max_lps = 122'880;
break; break;
case 21: case 21:
max_lsr = 7'372'800; lvl_idx = 2;
max_lps = 245'760;
break; break;
case 30: case 30:
max_lsr = 16'588'800; lvl_idx = 3;
max_lps = 552'960;
break; break;
case 31: case 31:
max_lsr = 33'177'600; lvl_idx = 4;
max_lps = 983'040;
break; break;
case 40: case 40:
max_lsr = 66'846'720; lvl_idx = 5;
goto lps4; break;
case 41: case 41:
max_lsr = 133'693'440; lvl_idx = 6;
lps4: max_lps = 2'228'224;
break; break;
case 50: case 50:
max_lsr = 267'386'880; lvl_idx = 7;
goto lps5; break;
case 51: case 51:
max_lsr = 534'773'760; lvl_idx = 8;
goto lps5; break;
case 52: case 52:
max_lsr = 1'069'547'520; lvl_idx = 9;
lps5: max_lps = 8'912'896;
break; break;
case 60: case 60:
max_lsr = 1'069'547'520; lvl_idx = 10;
goto lps6; break;
case 61: case 61:
max_lsr = 2'139'095'040; lvl_idx = 11;
goto lps6; break;
case 62: case 62:
max_lsr = 4'278'190'080; lvl_idx = 12;
lps6: max_lps = 35'651'584;
break; break;
default: default:
@ -1527,41 +1532,52 @@ static int validate_hevc_level(const kvz_config *const cfg) {
return 1; return 1;
} }
// max luma sample rate
uint32_t max_lsr = LEVEL_CONSTRAINTS[lvl_idx].lsr;
// max luma picture size
uint32_t max_lps = LEVEL_CONSTRAINTS[lvl_idx].lps;
// check the conformance to the level limits // check the conformance to the level limits
// luma samples // luma samples
unsigned long cfg_samples = cfg->width * cfg->height; uint64_t cfg_samples = cfg->width * cfg->height;
// luma sample rate // luma sample rate
double framerate = ((double)cfg->framerate_num) / ((double)cfg->framerate_denom); double framerate = ((double)cfg->framerate_num) / ((double)cfg->framerate_denom);
unsigned long cfg_sample_rate = cfg_samples * (unsigned long) framerate; uint64_t cfg_sample_rate = cfg_samples * (uint64_t) framerate;
// square of the maximum allowed dimension // square of the maximum allowed dimension
unsigned int max_dimension_squared = 8 * max_lps; uint32_t max_dimension_squared = 8 * max_lps;
// for nicer error print
float lvl = ((float)cfg->level) / 10.0f;
// check maximum dimensions // check maximum dimensions
if (cfg->width * cfg->width > max_dimension_squared) { if (cfg->width * cfg->width > max_dimension_squared) {
unsigned int max_dim = sqrtf(max_dimension_squared); uint32_t max_dim = sqrtf(max_dimension_squared);
fprintf(stderr, "%s: picture width of %i is too large for this level, maximum is %i\n", level_err_prefix, cfg->width, max_dim); fprintf(stderr, "%s: picture width of %i is too large for this level (%g), maximum dimension is %i\n",
level_err_prefix, cfg->width, lvl, max_dim);
level_error = 1; level_error = 1;
} }
if (cfg->height * cfg->height > max_dimension_squared) { if (cfg->height * cfg->height > max_dimension_squared) {
unsigned int max_dim = sqrtf(max_dimension_squared); uint32_t max_dim = sqrtf(max_dimension_squared);
fprintf(stderr, "%s: picture height of %i is too large for this level, maximum is %i\n", level_err_prefix, cfg->height, max_dim); fprintf(stderr, "%s: picture height of %i is too large for this level (%g), maximum dimension is %i\n",
level_err_prefix, cfg->height, lvl, max_dim);
level_error = 1; level_error = 1;
} }
// check luma picture size // check luma picture size
if (cfg_samples > max_lps) { if (cfg_samples > max_lps) {
fprintf(stderr, "%s: picture resolution of %ix%i is too big for this level (it has %ul samples, maximum is %ul samples)\n", fprintf(stderr, "%s: picture resolution of %ix%i is too large for this level (%g) (it has %u samples, maximum is %u samples)\n",
level_err_prefix, cfg->width, cfg->height, cfg_samples, max_lps); level_err_prefix, cfg->width, cfg->height, lvl, cfg_samples, max_lps);
level_error = 1; level_error = 1;
} }
// check luma sample rate // check luma sample rate
if (cfg_sample_rate > max_lsr) { if (cfg_sample_rate > max_lsr) {
fprintf(stderr, "%s: framerate of %g is too big for this level and picture resolution (it has a sample rate of %ul, the maximum sample rate is %ul)\n", fprintf(stderr, "%s: framerate of %g is too big for this level (%g) and picture resolution (it has the sample rate of %u, maximum is %u\n",
level_err_prefix, framerate, cfg_sample_rate, max_lsr); level_err_prefix, framerate, lvl, cfg_sample_rate, max_lsr);
level_error = 1; level_error = 1;
} }