[spatial svc]Add layer bitrates options and clean up parsing options from string
Change-Id: I6e8d3f08c8a8ce3555a498feba471ba9fec411c6
This commit is contained in:
Родитель
7ba600dc89
Коммит
a8d44b9915
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -47,8 +48,33 @@ _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
|
||||||
#define OPTION_BUFFER_SIZE 256
|
#define OPTION_BUFFER_SIZE 256
|
||||||
#define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v
|
#define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v
|
||||||
|
|
||||||
static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27";
|
static const int DEFAULT_QUANTIZER_VALUES[VPX_SS_MAX_LAYERS] = {
|
||||||
static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16";
|
60, 53, 39, 33, 27
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int DEFAULT_SCALE_FACTORS_NUM[VPX_SS_MAX_LAYERS] = {
|
||||||
|
4, 5, 7, 11, 16
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int DEFAULT_SCALE_FACTORS_DEN[VPX_SS_MAX_LAYERS] = {
|
||||||
|
16, 16, 16, 16, 16
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QUANTIZER = 0,
|
||||||
|
BITRATE,
|
||||||
|
SCALE_FACTOR,
|
||||||
|
AUTO_ALT_REF,
|
||||||
|
ALL_OPTION_TYPES
|
||||||
|
} LAYER_OPTION_TYPE;
|
||||||
|
|
||||||
|
static const int option_max_values[ALL_OPTION_TYPES] = {
|
||||||
|
63, INT_MAX, INT_MAX, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int option_min_values[ALL_OPTION_TYPES] = {
|
||||||
|
0, 0, 1, 0
|
||||||
|
};
|
||||||
|
|
||||||
// One encoded frame
|
// One encoded frame
|
||||||
typedef struct FrameData {
|
typedef struct FrameData {
|
||||||
|
@ -68,6 +94,7 @@ typedef struct SvcInternal {
|
||||||
int scaling_factor_den[VPX_SS_MAX_LAYERS];
|
int scaling_factor_den[VPX_SS_MAX_LAYERS];
|
||||||
int quantizer[VPX_SS_MAX_LAYERS];
|
int quantizer[VPX_SS_MAX_LAYERS];
|
||||||
int enable_auto_alt_ref[VPX_SS_MAX_LAYERS];
|
int enable_auto_alt_ref[VPX_SS_MAX_LAYERS];
|
||||||
|
int bitrates[VPX_SS_MAX_LAYERS];
|
||||||
|
|
||||||
// accumulated statistics
|
// accumulated statistics
|
||||||
double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V
|
double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V
|
||||||
|
@ -197,158 +224,62 @@ static int svc_log(SvcContext *svc_ctx, SVC_LOG_LEVEL level,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
|
static vpx_codec_err_t extract_option(LAYER_OPTION_TYPE type,
|
||||||
const char *quantizer_values) {
|
char *input,
|
||||||
char *input_string;
|
int *value0,
|
||||||
char *token;
|
int *value1) {
|
||||||
const char *delim = ",";
|
if (type == SCALE_FACTOR) {
|
||||||
char *save_ptr;
|
*value0 = strtol(input, &input, 10);
|
||||||
int found = 0;
|
if (*input++ != '/')
|
||||||
int i, q;
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
*value1 = strtol(input, &input, 10);
|
||||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
|
||||||
|
|
||||||
if (quantizer_values == NULL || strlen(quantizer_values) == 0) {
|
if (*value0 < option_min_values[SCALE_FACTOR] ||
|
||||||
input_string = strdup(DEFAULT_QUANTIZER_VALUES);
|
*value1 < option_min_values[SCALE_FACTOR] ||
|
||||||
|
*value0 > option_max_values[SCALE_FACTOR] ||
|
||||||
|
*value1 > option_max_values[SCALE_FACTOR])
|
||||||
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
} else {
|
} else {
|
||||||
input_string = strdup(quantizer_values);
|
*value0 = atoi(input);
|
||||||
|
if (*value0 < option_min_values[type] ||
|
||||||
|
*value0 > option_max_values[type])
|
||||||
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
return VPX_CODEC_OK;
|
||||||
token = strtok_r(input_string, delim, &save_ptr);
|
|
||||||
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
|
||||||
if (token != NULL) {
|
|
||||||
q = atoi(token);
|
|
||||||
if (q <= 0 || q > 100) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
|
||||||
"svc-quantizer-values: invalid value %s\n", token);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = strtok_r(NULL, delim, &save_ptr);
|
|
||||||
found = i + 1;
|
|
||||||
} else {
|
|
||||||
q = 0;
|
|
||||||
}
|
|
||||||
si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
|
|
||||||
}
|
|
||||||
if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
|
||||||
"svc: quantizers: %d values required, but only %d specified\n",
|
|
||||||
svc_ctx->spatial_layers, found);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
free(input_string);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpx_codec_err_t parse_auto_alt_ref(SvcContext *svc_ctx,
|
static vpx_codec_err_t parse_layer_options_from_string(SvcContext *svc_ctx,
|
||||||
const char *alt_ref_options) {
|
LAYER_OPTION_TYPE type,
|
||||||
char *input_string;
|
const char *input,
|
||||||
char *token;
|
int *option0,
|
||||||
const char *delim = ",";
|
int *option1) {
|
||||||
char *save_ptr;
|
|
||||||
int found = 0, enabled = 0;
|
|
||||||
int i, value;
|
|
||||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
|
||||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
|
||||||
|
|
||||||
if (alt_ref_options == NULL || strlen(alt_ref_options) == 0) {
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
} else {
|
|
||||||
input_string = strdup(alt_ref_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
token = strtok_r(input_string, delim, &save_ptr);
|
|
||||||
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
|
||||||
if (token != NULL) {
|
|
||||||
value = atoi(token);
|
|
||||||
if (value < 0 || value > 1) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
|
||||||
"enable auto alt ref values: invalid value %s\n", token);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = strtok_r(NULL, delim, &save_ptr);
|
|
||||||
found = i + 1;
|
|
||||||
} else {
|
|
||||||
value = 0;
|
|
||||||
}
|
|
||||||
si->enable_auto_alt_ref[i] = value;
|
|
||||||
if (value > 0)
|
|
||||||
++enabled;
|
|
||||||
}
|
|
||||||
if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
|
||||||
"svc: quantizers: %d values required, but only %d specified\n",
|
|
||||||
svc_ctx->spatial_layers, found);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
if (enabled > REF_FRAMES - svc_ctx->spatial_layers) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
|
||||||
"svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could"
|
|
||||||
"enabled auto alt reference frame, but % layers are enabled\n",
|
|
||||||
REF_FRAMES - svc_ctx->spatial_layers, enabled);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
free(input_string);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_invalid_scale_factor(SvcContext *svc_ctx, const char *value) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR, "svc scale-factors: invalid value %s\n",
|
|
||||||
value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static vpx_codec_err_t parse_scale_factors(SvcContext *svc_ctx,
|
|
||||||
const char *scale_factors) {
|
|
||||||
char *input_string;
|
|
||||||
char *token;
|
|
||||||
const char *delim = ",";
|
|
||||||
char *save_ptr;
|
|
||||||
int found = 0;
|
|
||||||
int i;
|
int i;
|
||||||
int64_t num, den;
|
|
||||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
vpx_codec_err_t res = VPX_CODEC_OK;
|
||||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
char *input_string;
|
||||||
|
char *token;
|
||||||
|
const char *delim = ",";
|
||||||
|
char *save_ptr;
|
||||||
|
|
||||||
if (scale_factors == NULL || strlen(scale_factors) == 0) {
|
if (input == NULL || option0 == NULL ||
|
||||||
input_string = strdup(DEFAULT_SCALE_FACTORS);
|
(option1 == NULL && type == SCALE_FACTOR))
|
||||||
} else {
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
input_string = strdup(scale_factors);
|
|
||||||
}
|
input_string = strdup(input);
|
||||||
token = strtok_r(input_string, delim, &save_ptr);
|
token = strtok_r(input_string, delim, &save_ptr);
|
||||||
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
||||||
num = den = 0;
|
|
||||||
if (token != NULL) {
|
if (token != NULL) {
|
||||||
num = strtol(token, &token, 10);
|
res = extract_option(type, token, option0 + i, option1 + i);
|
||||||
if (num <= 0) {
|
if (res != VPX_CODEC_OK)
|
||||||
log_invalid_scale_factor(svc_ctx, token);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (*token++ != '/') {
|
|
||||||
log_invalid_scale_factor(svc_ctx, token);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
den = strtol(token, &token, 10);
|
|
||||||
if (den <= 0) {
|
|
||||||
log_invalid_scale_factor(svc_ctx, token);
|
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = strtok_r(NULL, delim, &save_ptr);
|
token = strtok_r(NULL, delim, &save_ptr);
|
||||||
found = i + 1;
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
si->scaling_factor_num[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
|
|
||||||
(int)num;
|
|
||||||
si->scaling_factor_den[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
|
|
||||||
(int)den;
|
|
||||||
}
|
}
|
||||||
if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
|
if (res == VPX_CODEC_OK && i != svc_ctx->spatial_layers) {
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
svc_log(svc_ctx, SVC_LOG_ERROR,
|
||||||
"svc: scale-factors: %d values required, but only %d specified\n",
|
"svc: layer params type: %d %d values required, "
|
||||||
svc_ctx->spatial_layers, found);
|
"but only %d specified\n", type, svc_ctx->spatial_layers, i);
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
res = VPX_CODEC_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
free(input_string);
|
free(input_string);
|
||||||
|
@ -369,6 +300,7 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||||
char *input_ptr;
|
char *input_ptr;
|
||||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
SvcInternal *const si = get_svc_internal(svc_ctx);
|
||||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
vpx_codec_err_t res = VPX_CODEC_OK;
|
||||||
|
int i, alt_ref_enabled = 0;
|
||||||
|
|
||||||
if (options == NULL) return VPX_CODEC_OK;
|
if (options == NULL) return VPX_CODEC_OK;
|
||||||
input_string = strdup(options);
|
input_string = strdup(options);
|
||||||
|
@ -389,13 +321,21 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||||
} else if (strcmp("temporal-layers", option_name) == 0) {
|
} else if (strcmp("temporal-layers", option_name) == 0) {
|
||||||
svc_ctx->temporal_layers = atoi(option_value);
|
svc_ctx->temporal_layers = atoi(option_value);
|
||||||
} else if (strcmp("scale-factors", option_name) == 0) {
|
} else if (strcmp("scale-factors", option_name) == 0) {
|
||||||
res = parse_scale_factors(svc_ctx, option_value);
|
res = parse_layer_options_from_string(svc_ctx, SCALE_FACTOR, option_value,
|
||||||
|
si->scaling_factor_num,
|
||||||
|
si->scaling_factor_den);
|
||||||
if (res != VPX_CODEC_OK) break;
|
if (res != VPX_CODEC_OK) break;
|
||||||
} else if (strcmp("quantizers", option_name) == 0) {
|
} else if (strcmp("quantizers", option_name) == 0) {
|
||||||
res = parse_quantizer_values(svc_ctx, option_value);
|
res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
|
||||||
|
si->quantizer, NULL);
|
||||||
if (res != VPX_CODEC_OK) break;
|
if (res != VPX_CODEC_OK) break;
|
||||||
} else if (strcmp("auto-alt-refs", option_name) == 0) {
|
} else if (strcmp("auto-alt-refs", option_name) == 0) {
|
||||||
res = parse_auto_alt_ref(svc_ctx, option_value);
|
res = parse_layer_options_from_string(svc_ctx, AUTO_ALT_REF, option_value,
|
||||||
|
si->enable_auto_alt_ref, NULL);
|
||||||
|
if (res != VPX_CODEC_OK) break;
|
||||||
|
} else if (strcmp("bitrates", option_name) == 0) {
|
||||||
|
res = parse_layer_options_from_string(svc_ctx, BITRATE, option_value,
|
||||||
|
si->bitrates, NULL);
|
||||||
if (res != VPX_CODEC_OK) break;
|
if (res != VPX_CODEC_OK) break;
|
||||||
} else if (strcmp("multi-frame-contexts", option_name) == 0) {
|
} else if (strcmp("multi-frame-contexts", option_name) == 0) {
|
||||||
si->use_multiple_frame_contexts = atoi(option_value);
|
si->use_multiple_frame_contexts = atoi(option_value);
|
||||||
|
@ -413,6 +353,16 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||||
svc_ctx->spatial_layers * svc_ctx->temporal_layers > 4))
|
svc_ctx->spatial_layers * svc_ctx->temporal_layers > 4))
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
res = VPX_CODEC_INVALID_PARAM;
|
||||||
|
|
||||||
|
for (i = 0; i < svc_ctx->spatial_layers; ++i)
|
||||||
|
alt_ref_enabled += si->enable_auto_alt_ref[i];
|
||||||
|
if (alt_ref_enabled > REF_FRAMES - svc_ctx->spatial_layers) {
|
||||||
|
svc_log(svc_ctx, SVC_LOG_ERROR,
|
||||||
|
"svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could"
|
||||||
|
"enabled auto alt reference frame, but % layers are enabled\n",
|
||||||
|
REF_FRAMES - svc_ctx->spatial_layers, alt_ref_enabled);
|
||||||
|
res = VPX_CODEC_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,6 +398,39 @@ vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx,
|
||||||
return VPX_CODEC_OK;
|
return VPX_CODEC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assign_layer_bitrates(const SvcInternal *const si,
|
||||||
|
vpx_codec_enc_cfg_t *const enc_cfg) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (si->bitrates[0] != 0) {
|
||||||
|
enc_cfg->rc_target_bitrate = 0;
|
||||||
|
for (i = 0; i < si->layers; ++i) {
|
||||||
|
enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i];
|
||||||
|
enc_cfg->rc_target_bitrate += si->bitrates[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
float total = 0;
|
||||||
|
float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
|
||||||
|
|
||||||
|
for (i = 0; i < si->layers; ++i) {
|
||||||
|
if (si->scaling_factor_den[i] > 0) {
|
||||||
|
alloc_ratio[i] = (float)(si->scaling_factor_num[i] * 1.0 /
|
||||||
|
si->scaling_factor_den[i]);
|
||||||
|
|
||||||
|
alloc_ratio[i] *= alloc_ratio[i];
|
||||||
|
total += alloc_ratio[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < si->layers; ++i) {
|
||||||
|
if (total > 0) {
|
||||||
|
enc_cfg->ss_target_bitrate[i] = (unsigned int)
|
||||||
|
(enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||||
vpx_codec_iface_t *iface,
|
vpx_codec_iface_t *iface,
|
||||||
vpx_codec_enc_cfg_t *enc_cfg) {
|
vpx_codec_enc_cfg_t *enc_cfg) {
|
||||||
|
@ -481,11 +464,27 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = parse_quantizer_values(svc_ctx, si->quantizers);
|
for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||||
if (res != VPX_CODEC_OK) return res;
|
si->quantizer[i] = DEFAULT_QUANTIZER_VALUES[i];
|
||||||
|
si->scaling_factor_num[i] = DEFAULT_SCALE_FACTORS_NUM[i];
|
||||||
|
si->scaling_factor_den[i] = DEFAULT_SCALE_FACTORS_DEN[i];
|
||||||
|
}
|
||||||
|
|
||||||
res = parse_scale_factors(svc_ctx, si->scale_factors);
|
if (strlen(si->quantizers) > 0) {
|
||||||
if (res != VPX_CODEC_OK) return res;
|
res = parse_layer_options_from_string(svc_ctx, QUANTIZER, si->quantizers,
|
||||||
|
si->quantizer, NULL);
|
||||||
|
if (res != VPX_CODEC_OK)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(si->scale_factors) > 0) {
|
||||||
|
res = parse_layer_options_from_string(svc_ctx, SCALE_FACTOR,
|
||||||
|
si->scale_factors,
|
||||||
|
si->scaling_factor_num,
|
||||||
|
si->scaling_factor_den);
|
||||||
|
if (res != VPX_CODEC_OK)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse aggregate command line options. Options must start with
|
// Parse aggregate command line options. Options must start with
|
||||||
// "layers=xx" then followed by other options
|
// "layers=xx" then followed by other options
|
||||||
|
@ -504,33 +503,7 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||||
|
|
||||||
si->layers = svc_ctx->spatial_layers;
|
si->layers = svc_ctx->spatial_layers;
|
||||||
|
|
||||||
// Assign target bitrate for each layer. We calculate the ratio
|
assign_layer_bitrates(si, enc_cfg);
|
||||||
// from the resolution for now.
|
|
||||||
// TODO(Minghai): Optimize the mechanism of allocating bits after
|
|
||||||
// implementing svc two pass rate control.
|
|
||||||
if (si->layers > 1) {
|
|
||||||
float total = 0;
|
|
||||||
float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
|
|
||||||
|
|
||||||
assert(si->layers <= VPX_SS_MAX_LAYERS);
|
|
||||||
for (i = 0; i < si->layers; ++i) {
|
|
||||||
int pos = i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers;
|
|
||||||
if (pos < VPX_SS_MAX_LAYERS && si->scaling_factor_den[pos] > 0) {
|
|
||||||
alloc_ratio[i] = (float)(si->scaling_factor_num[pos] * 1.0 /
|
|
||||||
si->scaling_factor_den[pos]);
|
|
||||||
|
|
||||||
alloc_ratio[i] *= alloc_ratio[i];
|
|
||||||
total += alloc_ratio[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < si->layers; ++i) {
|
|
||||||
if (total > 0) {
|
|
||||||
enc_cfg->ss_target_bitrate[i] = (unsigned int)
|
|
||||||
(enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
#if CONFIG_SPATIAL_SVC
|
||||||
for (i = 0; i < si->layers; ++i)
|
for (i = 0; i < si->layers; ++i)
|
||||||
|
@ -585,7 +558,7 @@ vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
|
||||||
int layer,
|
int layer,
|
||||||
unsigned int *width,
|
unsigned int *width,
|
||||||
unsigned int *height) {
|
unsigned int *height) {
|
||||||
int w, h, index, num, den;
|
int w, h, num, den;
|
||||||
const SvcInternal *const si = get_const_svc_internal(svc_ctx);
|
const SvcInternal *const si = get_const_svc_internal(svc_ctx);
|
||||||
|
|
||||||
if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL) {
|
if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL) {
|
||||||
|
@ -593,9 +566,8 @@ vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
|
||||||
}
|
}
|
||||||
if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM;
|
if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM;
|
||||||
|
|
||||||
index = layer + VPX_SS_MAX_LAYERS - si->layers;
|
num = si->scaling_factor_num[layer];
|
||||||
num = si->scaling_factor_num[index];
|
den = si->scaling_factor_den[layer];
|
||||||
den = si->scaling_factor_den[index];
|
|
||||||
if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
|
if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
|
||||||
|
|
||||||
w = si->width * num / den;
|
w = si->width * num / den;
|
||||||
|
@ -613,7 +585,7 @@ vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
|
||||||
|
|
||||||
static void set_svc_parameters(SvcContext *svc_ctx,
|
static void set_svc_parameters(SvcContext *svc_ctx,
|
||||||
vpx_codec_ctx_t *codec_ctx) {
|
vpx_codec_ctx_t *codec_ctx) {
|
||||||
int layer, layer_index;
|
int layer;
|
||||||
vpx_svc_parameters_t svc_params;
|
vpx_svc_parameters_t svc_params;
|
||||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
SvcInternal *const si = get_svc_internal(svc_ctx);
|
||||||
|
|
||||||
|
@ -627,11 +599,10 @@ static void set_svc_parameters(SvcContext *svc_ctx,
|
||||||
&svc_params.height)) {
|
&svc_params.height)) {
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
|
svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
|
||||||
}
|
}
|
||||||
layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
|
|
||||||
|
|
||||||
if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) {
|
if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) {
|
||||||
svc_params.min_quantizer = si->quantizer[layer_index];
|
svc_params.min_quantizer = si->quantizer[layer];
|
||||||
svc_params.max_quantizer = si->quantizer[layer_index];
|
svc_params.max_quantizer = si->quantizer[layer];
|
||||||
} else {
|
} else {
|
||||||
svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer;
|
svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer;
|
||||||
svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer;
|
svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче