Merge "[spatial svc] Remove vpx_svc_parameters_t and the loop that sets it for each layer"
This commit is contained in:
Коммит
38b6aed8fd
|
@ -305,12 +305,6 @@ int main(int argc, const char **argv) {
|
||||||
info.codec_fourcc = VP9_FOURCC;
|
info.codec_fourcc = VP9_FOURCC;
|
||||||
info.time_base.numerator = enc_cfg.g_timebase.num;
|
info.time_base.numerator = enc_cfg.g_timebase.num;
|
||||||
info.time_base.denominator = enc_cfg.g_timebase.den;
|
info.time_base.denominator = enc_cfg.g_timebase.den;
|
||||||
if (vpx_svc_get_layer_resolution(&svc_ctx, svc_ctx.spatial_layers - 1,
|
|
||||||
(unsigned int *)&info.frame_width,
|
|
||||||
(unsigned int *)&info.frame_height) !=
|
|
||||||
VPX_CODEC_OK) {
|
|
||||||
die("Failed to get output resolution");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(app_input.passes == 2 && app_input.pass == 1)) {
|
if (!(app_input.passes == 2 && app_input.pass == 1)) {
|
||||||
// We don't save the bitstream for the 1st pass on two pass rate control
|
// We don't save the bitstream for the 1st pass on two pass rate control
|
||||||
|
|
|
@ -515,37 +515,6 @@ TEST_F(SvcTest, OnePassEncodeThreeFrames) {
|
||||||
FreeBitstreamBuffers(&outputs[0], 3);
|
FreeBitstreamBuffers(&outputs[0], 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SvcTest, GetLayerResolution) {
|
|
||||||
svc_.spatial_layers = 2;
|
|
||||||
vpx_svc_set_options(&svc_, "scale-factors=4/16,8/16");
|
|
||||||
InitializeEncoder();
|
|
||||||
|
|
||||||
// ensure that requested layer is a valid layer
|
|
||||||
uint32_t layer_width, layer_height;
|
|
||||||
vpx_codec_err_t res = vpx_svc_get_layer_resolution(&svc_, svc_.spatial_layers,
|
|
||||||
&layer_width, &layer_height);
|
|
||||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
|
||||||
|
|
||||||
res = vpx_svc_get_layer_resolution(NULL, 0, &layer_width, &layer_height);
|
|
||||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
|
||||||
|
|
||||||
res = vpx_svc_get_layer_resolution(&svc_, 0, NULL, &layer_height);
|
|
||||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
|
||||||
|
|
||||||
res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, NULL);
|
|
||||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
|
||||||
|
|
||||||
res = vpx_svc_get_layer_resolution(&svc_, 0, &layer_width, &layer_height);
|
|
||||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
|
||||||
EXPECT_EQ(kWidth * 4 / 16, layer_width);
|
|
||||||
EXPECT_EQ(kHeight * 4 / 16, layer_height);
|
|
||||||
|
|
||||||
res = vpx_svc_get_layer_resolution(&svc_, 1, &layer_width, &layer_height);
|
|
||||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
|
||||||
EXPECT_EQ(kWidth * 8 / 16, layer_width);
|
|
||||||
EXPECT_EQ(kHeight * 8 / 16, layer_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(SvcTest, TwoPassEncode10Frames) {
|
TEST_F(SvcTest, TwoPassEncode10Frames) {
|
||||||
// First pass encode
|
// First pass encode
|
||||||
std::string stats_buf;
|
std::string stats_buf;
|
||||||
|
|
|
@ -2448,15 +2448,7 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, unsigned int frame_flags,
|
||||||
|
|
||||||
vpx_usec_timer_start(&timer);
|
vpx_usec_timer_start(&timer);
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
if (vp9_lookahead_push(cpi->lookahead, sd, time_stamp, end_time, frame_flags))
|
||||||
if (is_two_pass_svc(cpi))
|
|
||||||
res = vp9_svc_lookahead_push(cpi, cpi->lookahead, sd, time_stamp, end_time,
|
|
||||||
frame_flags);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
res = vp9_lookahead_push(cpi->lookahead,
|
|
||||||
sd, time_stamp, end_time, frame_flags);
|
|
||||||
if (res)
|
|
||||||
res = -1;
|
res = -1;
|
||||||
vpx_usec_timer_mark(&timer);
|
vpx_usec_timer_mark(&timer);
|
||||||
cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
|
cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
|
||||||
|
@ -2585,11 +2577,12 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||||
MV_REFERENCE_FRAME ref_frame;
|
MV_REFERENCE_FRAME ref_frame;
|
||||||
int arf_src_index;
|
int arf_src_index;
|
||||||
|
|
||||||
if (is_two_pass_svc(cpi) && oxcf->pass == 2) {
|
if (is_two_pass_svc(cpi)) {
|
||||||
#if CONFIG_SPATIAL_SVC
|
#if CONFIG_SPATIAL_SVC
|
||||||
vp9_svc_lookahead_peek(cpi, cpi->lookahead, 0, 1);
|
vp9_svc_start_frame(cpi);
|
||||||
#endif
|
#endif
|
||||||
vp9_restore_layer_context(cpi);
|
if (oxcf->pass == 2)
|
||||||
|
vp9_restore_layer_context(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
vpx_usec_timer_start(&cmptimer);
|
vpx_usec_timer_start(&cmptimer);
|
||||||
|
@ -2608,13 +2601,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||||
if (arf_src_index) {
|
if (arf_src_index) {
|
||||||
assert(arf_src_index <= rc->frames_to_key);
|
assert(arf_src_index <= rc->frames_to_key);
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
if ((source = vp9_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
|
||||||
if (is_two_pass_svc(cpi))
|
|
||||||
source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, arf_src_index, 0);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
|
|
||||||
if (source != NULL) {
|
|
||||||
cpi->alt_ref_source = source;
|
cpi->alt_ref_source = source;
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
#if CONFIG_SPATIAL_SVC
|
||||||
|
@ -2652,13 +2639,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||||
if (!source) {
|
if (!source) {
|
||||||
// Get last frame source.
|
// Get last frame source.
|
||||||
if (cm->current_video_frame > 0) {
|
if (cm->current_video_frame > 0) {
|
||||||
#if CONFIG_SPATIAL_SVC
|
if ((last_source = vp9_lookahead_peek(cpi->lookahead, -1)) == NULL)
|
||||||
if (is_two_pass_svc(cpi))
|
|
||||||
last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
last_source = vp9_lookahead_peek(cpi->lookahead, -1);
|
|
||||||
if (last_source == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2918,6 +2899,12 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (is_two_pass_svc(cpi) && cm->show_frame) {
|
||||||
|
++cpi->svc.spatial_layer_to_encode;
|
||||||
|
if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
|
||||||
|
cpi->svc.spatial_layer_to_encode = 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,6 @@ struct lookahead_entry {
|
||||||
int64_t ts_start;
|
int64_t ts_start;
|
||||||
int64_t ts_end;
|
int64_t ts_end;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
|
||||||
vpx_svc_parameters_t svc_params[VPX_SS_MAX_LAYERS];
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The max of past frames we want to keep in the queue.
|
// The max of past frames we want to keep in the queue.
|
||||||
|
|
|
@ -233,51 +233,31 @@ int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_SPATIAL_SVC
|
#if CONFIG_SPATIAL_SVC
|
||||||
int vp9_svc_lookahead_push(const VP9_COMP *const cpi, struct lookahead_ctx *ctx,
|
static void get_layer_resolution(const int width_org, const int height_org,
|
||||||
YV12_BUFFER_CONFIG *src, int64_t ts_start,
|
const int num, const int den,
|
||||||
int64_t ts_end, unsigned int flags) {
|
int *width_out, int *height_out) {
|
||||||
struct lookahead_entry *buf;
|
int w, h;
|
||||||
int i, index;
|
|
||||||
|
|
||||||
if (vp9_lookahead_push(ctx, src, ts_start, ts_end, flags))
|
if (width_out == NULL || height_out == NULL || den == 0)
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
index = ctx->write_idx - 1;
|
w = width_org * num / den;
|
||||||
if (index < 0)
|
h = height_org * num / den;
|
||||||
index += ctx->max_sz;
|
|
||||||
|
|
||||||
buf = ctx->buf + index;
|
// make height and width even to make chrome player happy
|
||||||
|
w += w % 2;
|
||||||
|
h += h % 2;
|
||||||
|
|
||||||
if (buf == NULL)
|
*width_out = w;
|
||||||
return 1;
|
*height_out = h;
|
||||||
|
|
||||||
// Store svc parameters for each layer
|
|
||||||
for (i = 0; i < cpi->svc.number_spatial_layers; ++i)
|
|
||||||
buf->svc_params[i] = cpi->svc.layer_context[i].svc_params_received;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int copy_svc_params(VP9_COMP *const cpi, struct lookahead_entry *buf) {
|
int vp9_svc_start_frame(VP9_COMP *const cpi) {
|
||||||
int layer_id;
|
int width = 0, height = 0;
|
||||||
vpx_svc_parameters_t *layer_param;
|
|
||||||
LAYER_CONTEXT *lc;
|
LAYER_CONTEXT *lc;
|
||||||
int count = 1 << (cpi->svc.number_temporal_layers - 1);
|
int count = 1 << (cpi->svc.number_temporal_layers - 1);
|
||||||
|
|
||||||
// Find the next layer to be encoded
|
cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
|
||||||
for (layer_id = 0; layer_id < cpi->svc.number_spatial_layers; ++layer_id) {
|
|
||||||
if (buf->svc_params[layer_id].spatial_layer >=0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layer_id == cpi->svc.number_spatial_layers)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
layer_param = &buf->svc_params[layer_id];
|
|
||||||
cpi->svc.spatial_layer_id = layer_param->spatial_layer;
|
|
||||||
cpi->svc.temporal_layer_id = layer_param->temporal_layer;
|
|
||||||
cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
|
|
||||||
|
|
||||||
lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
|
lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
|
||||||
|
|
||||||
cpi->svc.temporal_layer_id = 0;
|
cpi->svc.temporal_layer_id = 0;
|
||||||
|
@ -286,6 +266,8 @@ static int copy_svc_params(VP9_COMP *const cpi, struct lookahead_entry *buf) {
|
||||||
count >>= 1;
|
count >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
|
||||||
|
|
||||||
cpi->lst_fb_idx = cpi->svc.spatial_layer_id;
|
cpi->lst_fb_idx = cpi->svc.spatial_layer_id;
|
||||||
|
|
||||||
if (cpi->svc.spatial_layer_id == 0)
|
if (cpi->svc.spatial_layer_id == 0)
|
||||||
|
@ -325,13 +307,14 @@ static int copy_svc_params(VP9_COMP *const cpi, struct lookahead_entry *buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vp9_set_size_literal(cpi, layer_param->width, layer_param->height) != 0)
|
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
|
||||||
|
lc->scaling_factor_num, lc->scaling_factor_den,
|
||||||
|
&width, &height);
|
||||||
|
if (vp9_set_size_literal(cpi, width, height) != 0)
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
|
|
||||||
cpi->oxcf.worst_allowed_q =
|
cpi->oxcf.worst_allowed_q = vp9_quantizer_to_qindex(lc->max_q);
|
||||||
vp9_quantizer_to_qindex(layer_param->max_quantizer);
|
cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q);
|
||||||
cpi->oxcf.best_allowed_q =
|
|
||||||
vp9_quantizer_to_qindex(layer_param->min_quantizer);
|
|
||||||
|
|
||||||
vp9_change_config(cpi, &cpi->oxcf);
|
vp9_change_config(cpi, &cpi->oxcf);
|
||||||
|
|
||||||
|
@ -342,29 +325,15 @@ static int copy_svc_params(VP9_COMP *const cpi, struct lookahead_entry *buf) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct lookahead_entry *vp9_svc_lookahead_peek(VP9_COMP *const cpi,
|
|
||||||
struct lookahead_ctx *ctx,
|
|
||||||
int index, int copy_params) {
|
|
||||||
struct lookahead_entry *buf = vp9_lookahead_peek(ctx, index);
|
|
||||||
|
|
||||||
if (buf != NULL && copy_params != 0) {
|
|
||||||
if (copy_svc_params(cpi, buf) != 0)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
|
struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
|
||||||
struct lookahead_ctx *ctx,
|
struct lookahead_ctx *ctx,
|
||||||
int drain) {
|
int drain) {
|
||||||
struct lookahead_entry *buf = NULL;
|
struct lookahead_entry *buf = NULL;
|
||||||
|
|
||||||
if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
|
if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
|
||||||
buf = vp9_svc_lookahead_peek(cpi, ctx, 0, 1);
|
buf = vp9_lookahead_peek(ctx, 0);
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
// Only remove the buffer when pop the highest layer. Simply set the
|
// Only remove the buffer when pop the highest layer.
|
||||||
// spatial_layer to -1 for lower layers.
|
|
||||||
buf->svc_params[cpi->svc.spatial_layer_id].spatial_layer = -1;
|
|
||||||
if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
|
if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
|
||||||
vp9_lookahead_pop(ctx, drain);
|
vp9_lookahead_pop(ctx, drain);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,16 @@ typedef struct {
|
||||||
int target_bandwidth;
|
int target_bandwidth;
|
||||||
double framerate;
|
double framerate;
|
||||||
int avg_frame_size;
|
int avg_frame_size;
|
||||||
|
int max_q;
|
||||||
|
int min_q;
|
||||||
|
int scaling_factor_num;
|
||||||
|
int scaling_factor_den;
|
||||||
TWO_PASS twopass;
|
TWO_PASS twopass;
|
||||||
vpx_fixed_buf_t rc_twopass_stats_in;
|
vpx_fixed_buf_t rc_twopass_stats_in;
|
||||||
unsigned int current_video_frame_in_layer;
|
unsigned int current_video_frame_in_layer;
|
||||||
int is_key_frame;
|
int is_key_frame;
|
||||||
int frames_from_key_frame;
|
int frames_from_key_frame;
|
||||||
FRAME_TYPE last_frame_type;
|
FRAME_TYPE last_frame_type;
|
||||||
vpx_svc_parameters_t svc_params_received;
|
|
||||||
struct lookahead_entry *alt_ref_source;
|
struct lookahead_entry *alt_ref_source;
|
||||||
int alt_ref_idx;
|
int alt_ref_idx;
|
||||||
int gold_ref_idx;
|
int gold_ref_idx;
|
||||||
|
@ -45,6 +48,8 @@ typedef struct {
|
||||||
int number_spatial_layers;
|
int number_spatial_layers;
|
||||||
int number_temporal_layers;
|
int number_temporal_layers;
|
||||||
|
|
||||||
|
int spatial_layer_to_encode;
|
||||||
|
|
||||||
// Store scaled source frames to be used for temporal filter to generate
|
// Store scaled source frames to be used for temporal filter to generate
|
||||||
// a alt ref frame.
|
// a alt ref frame.
|
||||||
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
|
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
|
||||||
|
@ -88,22 +93,13 @@ void vp9_inc_frame_in_layer(struct VP9_COMP *const cpi);
|
||||||
// Check if current layer is key frame in spatial upper layer
|
// Check if current layer is key frame in spatial upper layer
|
||||||
int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi);
|
int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi);
|
||||||
|
|
||||||
// Copy the source image, flags and svc parameters into a new framebuffer
|
|
||||||
// with the expected stride/border
|
|
||||||
int vp9_svc_lookahead_push(const struct VP9_COMP *const cpi,
|
|
||||||
struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
|
|
||||||
int64_t ts_start, int64_t ts_end,
|
|
||||||
unsigned int flags);
|
|
||||||
|
|
||||||
// Get the next source buffer to encode
|
// Get the next source buffer to encode
|
||||||
struct lookahead_entry *vp9_svc_lookahead_pop(struct VP9_COMP *const cpi,
|
struct lookahead_entry *vp9_svc_lookahead_pop(struct VP9_COMP *const cpi,
|
||||||
struct lookahead_ctx *ctx,
|
struct lookahead_ctx *ctx,
|
||||||
int drain);
|
int drain);
|
||||||
|
|
||||||
// Get a future source buffer to encode
|
// Start a frame and initialize svc parameters
|
||||||
struct lookahead_entry *vp9_svc_lookahead_peek(struct VP9_COMP *const cpi,
|
int vp9_svc_start_frame(struct VP9_COMP *const cpi);
|
||||||
struct lookahead_ctx *ctx,
|
|
||||||
int index, int copy_params);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -1198,22 +1198,18 @@ static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
|
||||||
static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
|
static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
|
||||||
va_list args) {
|
va_list args) {
|
||||||
VP9_COMP *const cpi = ctx->cpi;
|
VP9_COMP *const cpi = ctx->cpi;
|
||||||
vpx_svc_parameters_t *const params = va_arg(args, vpx_svc_parameters_t *);
|
vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (params == NULL || params->spatial_layer < 0 ||
|
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
|
||||||
params->spatial_layer >= cpi->svc.number_spatial_layers)
|
LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
|
|
||||||
if (params->spatial_layer == 0) {
|
lc->max_q = params->max_quantizers[i];
|
||||||
int i;
|
lc->min_q = params->min_quantizers[i];
|
||||||
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
|
lc->scaling_factor_num = params->scaling_factor_num[i];
|
||||||
cpi->svc.layer_context[i].svc_params_received.spatial_layer = -1;
|
lc->scaling_factor_den = params->scaling_factor_den[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpi->svc.layer_context[params->spatial_layer].svc_params_received =
|
|
||||||
*params;
|
|
||||||
|
|
||||||
return VPX_CODEC_OK;
|
return VPX_CODEC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,3 @@ text vpx_svc_get_message
|
||||||
text vpx_svc_init
|
text vpx_svc_init
|
||||||
text vpx_svc_release
|
text vpx_svc_release
|
||||||
text vpx_svc_set_options
|
text vpx_svc_set_options
|
||||||
text vpx_svc_get_layer_resolution
|
|
||||||
|
|
|
@ -85,10 +85,7 @@ typedef struct SvcInternal {
|
||||||
char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
|
char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
|
||||||
|
|
||||||
// values extracted from option, quantizers
|
// values extracted from option, quantizers
|
||||||
int scaling_factor_num[VPX_SS_MAX_LAYERS];
|
vpx_svc_extra_cfg_t svc_params;
|
||||||
int scaling_factor_den[VPX_SS_MAX_LAYERS];
|
|
||||||
int max_quantizers[VPX_SS_MAX_LAYERS];
|
|
||||||
int min_quantizers[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];
|
int bitrates[VPX_SS_MAX_LAYERS];
|
||||||
|
|
||||||
|
@ -174,7 +171,8 @@ static vpx_codec_err_t extract_option(LAYER_OPTION_TYPE type,
|
||||||
if (*value0 < option_min_values[SCALE_FACTOR] ||
|
if (*value0 < option_min_values[SCALE_FACTOR] ||
|
||||||
*value1 < option_min_values[SCALE_FACTOR] ||
|
*value1 < option_min_values[SCALE_FACTOR] ||
|
||||||
*value0 > option_max_values[SCALE_FACTOR] ||
|
*value0 > option_max_values[SCALE_FACTOR] ||
|
||||||
*value1 > option_max_values[SCALE_FACTOR])
|
*value1 > option_max_values[SCALE_FACTOR] ||
|
||||||
|
*value0 > *value1) // num shouldn't be greater than den
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
} else {
|
} else {
|
||||||
*value0 = atoi(input);
|
*value0 = atoi(input);
|
||||||
|
@ -259,16 +257,18 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||||
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_layer_options_from_string(svc_ctx, SCALE_FACTOR, option_value,
|
res = parse_layer_options_from_string(svc_ctx, SCALE_FACTOR, option_value,
|
||||||
si->scaling_factor_num,
|
si->svc_params.scaling_factor_num,
|
||||||
si->scaling_factor_den);
|
si->svc_params.scaling_factor_den);
|
||||||
if (res != VPX_CODEC_OK) break;
|
if (res != VPX_CODEC_OK) break;
|
||||||
} else if (strcmp("max-quantizers", option_name) == 0) {
|
} else if (strcmp("max-quantizers", option_name) == 0) {
|
||||||
res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
|
res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
|
||||||
si->max_quantizers, NULL);
|
si->svc_params.max_quantizers,
|
||||||
|
NULL);
|
||||||
if (res != VPX_CODEC_OK) break;
|
if (res != VPX_CODEC_OK) break;
|
||||||
} else if (strcmp("min-quantizers", option_name) == 0) {
|
} else if (strcmp("min-quantizers", option_name) == 0) {
|
||||||
res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
|
res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
|
||||||
si->min_quantizers, NULL);
|
si->svc_params.min_quantizers,
|
||||||
|
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_layer_options_from_string(svc_ctx, AUTO_ALT_REF, option_value,
|
res = parse_layer_options_from_string(svc_ctx, AUTO_ALT_REF, option_value,
|
||||||
|
@ -290,9 +290,10 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||||
free(input_string);
|
free(input_string);
|
||||||
|
|
||||||
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
||||||
if (si->max_quantizers[i] > MAX_QUANTIZER || si->max_quantizers[i] < 0 ||
|
if (si->svc_params.max_quantizers[i] > MAX_QUANTIZER ||
|
||||||
si->min_quantizers[i] > si->max_quantizers[i] ||
|
si->svc_params.max_quantizers[i] < 0 ||
|
||||||
si->min_quantizers[i] < 0)
|
si->svc_params.min_quantizers[i] > si->svc_params.max_quantizers[i] ||
|
||||||
|
si->svc_params.min_quantizers[i] < 0)
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
res = VPX_CODEC_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,9 +341,9 @@ void assign_layer_bitrates(const SvcContext *svc_ctx,
|
||||||
float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
|
float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
|
||||||
|
|
||||||
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
||||||
if (si->scaling_factor_den[i] > 0) {
|
if (si->svc_params.scaling_factor_den[i] > 0) {
|
||||||
alloc_ratio[i] = (float)(si->scaling_factor_num[i] * 1.0 /
|
alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 /
|
||||||
si->scaling_factor_den[i]);
|
si->svc_params.scaling_factor_den[i]);
|
||||||
|
|
||||||
alloc_ratio[i] *= alloc_ratio[i];
|
alloc_ratio[i] *= alloc_ratio[i];
|
||||||
total += alloc_ratio[i];
|
total += alloc_ratio[i];
|
||||||
|
@ -392,10 +393,10 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
|
for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||||
si->max_quantizers[i] = MAX_QUANTIZER;
|
si->svc_params.max_quantizers[i] = MAX_QUANTIZER;
|
||||||
si->min_quantizers[i] = 0;
|
si->svc_params.min_quantizers[i] = 0;
|
||||||
si->scaling_factor_num[i] = DEFAULT_SCALE_FACTORS_NUM[i];
|
si->svc_params.scaling_factor_num[i] = DEFAULT_SCALE_FACTORS_NUM[i];
|
||||||
si->scaling_factor_den[i] = DEFAULT_SCALE_FACTORS_DEN[i];
|
si->svc_params.scaling_factor_den[i] = DEFAULT_SCALE_FACTORS_DEN[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse aggregate command line options. Options must start with
|
// Parse aggregate command line options. Options must start with
|
||||||
|
@ -444,62 +445,11 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
|
vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
|
||||||
|
vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &si->svc_params);
|
||||||
|
|
||||||
return VPX_CODEC_OK;
|
return VPX_CODEC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
|
|
||||||
int layer,
|
|
||||||
unsigned int *width,
|
|
||||||
unsigned int *height) {
|
|
||||||
int w, h, num, den;
|
|
||||||
const SvcInternal *const si = get_const_svc_internal(svc_ctx);
|
|
||||||
|
|
||||||
if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL)
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
if (layer < 0 || layer >= svc_ctx->spatial_layers)
|
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
|
||||||
|
|
||||||
num = si->scaling_factor_num[layer];
|
|
||||||
den = si->scaling_factor_den[layer];
|
|
||||||
if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
|
|
||||||
|
|
||||||
w = si->width * num / den;
|
|
||||||
h = si->height * num / den;
|
|
||||||
|
|
||||||
// make height and width even to make chrome player happy
|
|
||||||
w += w % 2;
|
|
||||||
h += h % 2;
|
|
||||||
|
|
||||||
*width = w;
|
|
||||||
*height = h;
|
|
||||||
|
|
||||||
return VPX_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_svc_parameters(SvcContext *svc_ctx,
|
|
||||||
vpx_codec_ctx_t *codec_ctx) {
|
|
||||||
int layer;
|
|
||||||
vpx_svc_parameters_t svc_params;
|
|
||||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
|
||||||
|
|
||||||
memset(&svc_params, 0, sizeof(svc_params));
|
|
||||||
svc_params.temporal_layer = 0;
|
|
||||||
svc_params.spatial_layer = si->layer;
|
|
||||||
|
|
||||||
layer = si->layer;
|
|
||||||
if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer,
|
|
||||||
&svc_params.width,
|
|
||||||
&svc_params.height)) {
|
|
||||||
svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
svc_params.min_quantizer = si->min_quantizers[layer];
|
|
||||||
svc_params.max_quantizer = si->max_quantizers[layer];
|
|
||||||
|
|
||||||
vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &svc_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode a frame into multiple layers
|
* Encode a frame into multiple layers
|
||||||
* Create a superframe containing the individual layers
|
* Create a superframe containing the individual layers
|
||||||
|
@ -517,13 +467,6 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||||
|
|
||||||
svc_log_reset(svc_ctx);
|
svc_log_reset(svc_ctx);
|
||||||
|
|
||||||
if (rawimg != NULL) {
|
|
||||||
// encode each layer
|
|
||||||
for (si->layer = 0; si->layer < svc_ctx->spatial_layers; ++si->layer) {
|
|
||||||
set_svc_parameters(svc_ctx, codec_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0,
|
res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0,
|
||||||
deadline);
|
deadline);
|
||||||
if (res != VPX_CODEC_OK) {
|
if (res != VPX_CODEC_OK) {
|
||||||
|
|
|
@ -79,14 +79,6 @@ const char *vpx_svc_dump_statistics(SvcContext *svc_ctx);
|
||||||
*/
|
*/
|
||||||
const char *vpx_svc_get_message(const SvcContext *svc_ctx);
|
const char *vpx_svc_get_message(const SvcContext *svc_ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* return spatial resolution of the specified layer
|
|
||||||
*/
|
|
||||||
vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
|
|
||||||
int layer,
|
|
||||||
unsigned int *width,
|
|
||||||
unsigned int *height);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
19
vpx/vp8cx.h
19
vpx/vp8cx.h
|
@ -305,23 +305,6 @@ typedef enum {
|
||||||
VP8_TUNE_SSIM
|
VP8_TUNE_SSIM
|
||||||
} vp8e_tuning;
|
} vp8e_tuning;
|
||||||
|
|
||||||
/*!\brief vp9 svc parameters
|
|
||||||
*
|
|
||||||
* This defines parameters for svc encoding.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef struct vpx_svc_parameters {
|
|
||||||
unsigned int width; /**< width of current spatial layer */
|
|
||||||
unsigned int height; /**< height of current spatial layer */
|
|
||||||
int spatial_layer; /**< current spatial layer number - 0 = base */
|
|
||||||
int temporal_layer; /**< current temporal layer number - 0 = base */
|
|
||||||
int max_quantizer; /**< max quantizer for current layer */
|
|
||||||
int min_quantizer; /**< min quantizer for current layer */
|
|
||||||
int lst_fb_idx; /**< last frame frame buffer index */
|
|
||||||
int gld_fb_idx; /**< golden frame frame buffer index */
|
|
||||||
int alt_fb_idx; /**< alt reference frame frame buffer index */
|
|
||||||
} vpx_svc_parameters_t;
|
|
||||||
|
|
||||||
/*!\brief vp9 svc layer parameters
|
/*!\brief vp9 svc layer parameters
|
||||||
*
|
*
|
||||||
* This defines the spatial and temporal layer id numbers for svc encoding.
|
* This defines the spatial and temporal layer id numbers for svc encoding.
|
||||||
|
@ -354,7 +337,7 @@ VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
|
||||||
VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
|
VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
|
||||||
|
|
||||||
VPX_CTRL_USE_TYPE(VP9E_SET_SVC, int)
|
VPX_CTRL_USE_TYPE(VP9E_SET_SVC, int)
|
||||||
VPX_CTRL_USE_TYPE(VP9E_SET_SVC_PARAMETERS, vpx_svc_parameters_t *)
|
VPX_CTRL_USE_TYPE(VP9E_SET_SVC_PARAMETERS, void *)
|
||||||
VPX_CTRL_USE_TYPE(VP9E_SET_SVC_LAYER_ID, vpx_svc_layer_id_t *)
|
VPX_CTRL_USE_TYPE(VP9E_SET_SVC_LAYER_ID, vpx_svc_layer_id_t *)
|
||||||
|
|
||||||
VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
|
VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
|
||||||
|
|
|
@ -711,6 +711,18 @@ extern "C" {
|
||||||
unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
|
unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
|
||||||
} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
|
} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
|
||||||
|
|
||||||
|
/*!\brief vp9 svc extra configure parameters
|
||||||
|
*
|
||||||
|
* This defines max/min quantizers and scale factors for each layer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct vpx_svc_parameters {
|
||||||
|
int max_quantizers[VPX_SS_MAX_LAYERS];
|
||||||
|
int min_quantizers[VPX_SS_MAX_LAYERS];
|
||||||
|
int scaling_factor_num[VPX_SS_MAX_LAYERS];
|
||||||
|
int scaling_factor_den[VPX_SS_MAX_LAYERS];
|
||||||
|
} vpx_svc_extra_cfg_t;
|
||||||
|
|
||||||
|
|
||||||
/*!\brief Initialize an encoder instance
|
/*!\brief Initialize an encoder instance
|
||||||
*
|
*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче