Commit e479379a authored by Adrian Grange's avatar Adrian Grange

Fixed bugs in multi-layer code related to changing params

When running multi-layer (ML) encodes and dynamically
changing coding parameters on the fly (e.g. frame
duration/rate, bandwidths allocated to each layer)
the encoder would not produce sensible output.

In certain cases the rate targeting would be
hideously inaccurate.

These fixes make it possible to change these coding
parameters correctly and to maintain accurate control
of the rate targeting.

I also added the specification of the input timebase
into the test program, vp8_scalable_patterns.c.

Patch 2: Moved declaration to appease MS compiler)

Change-Id: Ic8bb5a16daa924bb64974e740696e040d07ae363
parent 9c2ca8c1
......@@ -147,10 +147,14 @@ extern "C"
int over_shoot_pct;
// buffering parameters
int64_t starting_buffer_level; // in seconds
int64_t starting_buffer_level; // in bytes
int64_t optimal_buffer_level;
int64_t maximum_buffer_size;
int64_t starting_buffer_level_in_ms; // in milli-seconds
int64_t optimal_buffer_level_in_ms;
int64_t maximum_buffer_size_in_ms;
// controlling quality
int fixed_q;
int worst_allowed_q;
......
This diff is collapsed.
......@@ -253,6 +253,9 @@ typedef struct
int starting_buffer_level;
int optimal_buffer_level;
int maximum_buffer_size;
int starting_buffer_level_in_ms;
int optimal_buffer_level_in_ms;
int maximum_buffer_size_in_ms;
int avg_frame_size_for_layer;
......@@ -421,6 +424,7 @@ typedef struct VP8_COMP
int buffered_mode;
double frame_rate;
double ref_frame_rate;
int64_t buffer_level;
int bits_off_target;
......
......@@ -335,6 +335,10 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
oxcf->maximum_buffer_size_in_ms = cfg.rc_buf_sz;
oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz;
oxcf->optimal_buffer_level_in_ms = cfg.rc_buf_optimal_sz;
oxcf->maximum_buffer_size = cfg.rc_buf_sz;
oxcf->starting_buffer_level = cfg.rc_buf_initial_sz;
oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz;
......
......@@ -129,27 +129,29 @@ int main(int argc, char **argv) {
int got_data;
int flags = 0;
int i;
int pts = 0; // PTS starts at 0
int frame_duration = 1; // 1 timebase tick per frame
int layering_mode = 0;
int frames_in_layer[MAX_LAYERS] = {0};
int layer_flags[MAX_PERIODICITY] = {0};
// Check usage and arguments
if (argc < 7)
die("Usage: %s <infile> <outfile> <width> <height> <mode> "
"<Rate_0> ... <Rate_nlayers-1>\n", argv[0]);
if (argc < 9)
die("Usage: %s <infile> <outfile> <width> <height> <rate_num> "
" <rate_den> <mode> <Rate_0> ... <Rate_nlayers-1>\n", argv[0]);
width = strtol (argv[3], NULL, 0);
height = strtol (argv[4], NULL, 0);
if (width < 16 || width%2 || height <16 || height%2)
die ("Invalid resolution: %d x %d", width, height);
if (!sscanf(argv[5], "%d", &layering_mode))
die ("Invalid mode %s", argv[5]);
if (!sscanf(argv[7], "%d", &layering_mode))
die ("Invalid mode %s", argv[7]);
if (layering_mode<0 || layering_mode>6)
die ("Invalid mode (0..6) %s", argv[5]);
die ("Invalid mode (0..6) %s", argv[7]);
if (argc != 6+mode_to_num_layers[layering_mode])
if (argc != 8+mode_to_num_layers[layering_mode])
die ("Invalid number of arguments");
if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 1))
......@@ -168,8 +170,14 @@ int main(int argc, char **argv) {
cfg.g_w = width;
cfg.g_h = height;
for (i=6; i<6+mode_to_num_layers[layering_mode]; i++)
if (!sscanf(argv[i], "%d", &cfg.ts_target_bitrate[i-6]))
// Timebase format e.g. 30fps: numerator=1, demoninator=30
if (!sscanf (argv[5], "%d", &cfg.g_timebase.num ))
die ("Invalid timebase numerator %s", argv[5]);
if (!sscanf (argv[6], "%d", &cfg.g_timebase.den ))
die ("Invalid timebase denominator %s", argv[6]);
for (i=8; i<8+mode_to_num_layers[layering_mode]; i++)
if (!sscanf(argv[i], "%d", &cfg.ts_target_bitrate[i-8]))
die ("Invalid data rate %s", argv[i]);
// Real time parameters
......@@ -193,7 +201,7 @@ int main(int argc, char **argv) {
cfg.kf_min_dist = cfg.kf_max_dist = 1000;
// Temporal scaling parameters:
// NOTE: The 3 prediction frames cannot be used interchangebly due to
// NOTE: The 3 prediction frames cannot be used interchangeably due to
// differences in the way they are handled throughout the code. The
// frames should be allocated to layers in the order LAST, GF, ARF.
// Other combinations work, but may produce slightly inferior results.
......@@ -210,14 +218,15 @@ int main(int argc, char **argv) {
cfg.ts_rate_decimator[1] = 1;
memcpy(cfg.ts_layer_id, ids, sizeof(ids));
#if 1
// 0=L, 1=GF, Intra-layer prediction enabled
layer_flags[0] = VPX_EFLAG_FORCE_KF |
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_REF_ARF;
#if 0
// 0=L, 1=GF, Intra-layer 1 prediction disabled
#else
// 0=L, 1=GF, Intra-layer prediction disabled
layer_flags[0] = VPX_EFLAG_FORCE_KF |
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
......@@ -275,7 +284,7 @@ int main(int argc, char **argv) {
case 3:
{
// 3-layers, 4-frame period
int ids[6] = {0,2,1,2};
int ids[4] = {0,2,1,2};
cfg.ts_number_layers = 3;
cfg.ts_periodicity = 4;
cfg.ts_rate_decimator[0] = 4;
......@@ -295,13 +304,12 @@ int main(int argc, char **argv) {
VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
break;
cfg.ts_rate_decimator[2] = 1;
}
case 4:
{
// 3-layers, 4-frame period
int ids[6] = {0,2,1,2};
int ids[4] = {0,2,1,2};
cfg.ts_number_layers = 3;
cfg.ts_periodicity = 4;
cfg.ts_rate_decimator[0] = 4;
......@@ -326,7 +334,7 @@ int main(int argc, char **argv) {
case 5:
{
// 3-layers, 4-frame period
int ids[6] = {0,2,1,2};
int ids[4] = {0,2,1,2};
cfg.ts_number_layers = 3;
cfg.ts_periodicity = 4;
cfg.ts_rate_decimator[0] = 4;
......@@ -417,7 +425,7 @@ int main(int argc, char **argv) {
flags = layer_flags[frame_cnt % cfg.ts_periodicity];
frame_avail = read_frame(infile, &raw);
if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts,
1, flags, VPX_DL_REALTIME))
die_codec(&codec, "Failed to encode frame");
......@@ -446,6 +454,7 @@ int main(int argc, char **argv) {
fflush (stdout);
}
frame_cnt++;
pts += frame_duration;
}
printf ("\n");
fclose (infile);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment