Commit 217591fd authored by Adrian Grange's avatar Adrian Grange

Added rate-targeted temporal scalability

Added the ability to create rate-targeted, temporally
scalable, VP8 compatible bitstreams.

The application vp8_scalable_patterns.c demonstrates how
to use this capability. Users can create output bitstreams
containing upto 5 temporally separable streams encoded
as a single VP8 bitstream.
(previously abandoned as:
I92d1483e887adb274d07ce9e567e4d0314881b0a)

Change-Id: I156250a3fe930be57c069d508c41b6a7a4ea8d6a
parent af12c23e
......@@ -48,7 +48,6 @@
/twopass_encoder.dox
/vp8_api1_migration.dox
/vp8_scalable_patterns
/vp8_scalable_patterns.c
/vp8_scalable_patterns.dox
/vp8_set_maps
/vp8_set_maps.c
......
......@@ -37,6 +37,9 @@ vpxenc.SRCS += libmkv/EbmlWriter.c
vpxenc.SRCS += libmkv/EbmlWriter.h
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
vpxenc.DESCRIPTION = Full featured encoder
UTILS-$(CONFIG_ENCODERS) += vp8_scalable_patterns.c
vp8_scalable_patterns.GUID = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
vp8_scalable_patterns.DESCRIPTION = Temporal Scalability Encoder
# Clean up old ivfenc, ivfdec binaries.
ifeq ($(CONFIG_MSVS),yes)
......@@ -86,9 +89,6 @@ GEN_EXAMPLES-$(CONFIG_ENCODERS) += error_resilient.c
error_resilient.GUID = DF5837B9-4145-4F92-A031-44E4F832E00C
error_resilient.DESCRIPTION = Error Resiliency Feature
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_scalable_patterns.c
vp8_scalable_patterns.GUID = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
vp8_scalable_patterns.DESCRIPTION = VP8 Scalable Bitstream Patterns
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_set_maps.c
vp8_set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
vp8_set_maps.DESCRIPTION = VP8 set active and ROI maps
......
@TEMPLATE encoder_tmpl.c
VP8 Scalable Frame Patterns
===========================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
This is an example demonstrating how to control the VP8 encoder's
reference frame selection and update mechanism for video applications
that benefit from a scalable bitstream.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
Configuration
-------------
Scalable frame patterns are most useful in an error resilient context,
so error resiliency mode is enabled, as in the `error_resilient.c`
example. In addition, we want to disable automatic keyframe selection,
so we force an interval of 1000 frames.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
/* Enable error resilient mode */
cfg.g_error_resilient = 1;
cfg.g_lag_in_frames = 0;
cfg.kf_mode = VPX_KF_FIXED;
/* Disable automatic keyframe placement */
cfg.kf_min_dist = cfg.kf_max_dist = 1000;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
This example uses the following frame pattern (L->last_frame,
G->golden_frame, A->alt_ref_frame):
* Frame 0 Intra, use none, update L&G&A
* Frame 1 Inter, use LGA, update none
* Frame 2 Inter, use LGA, update L
* Frame 3 Inter, use LGA, update none
* Frame 4 Inter, use GA, update L&G
* Frame 5 Inter, use LGA, update none
* Frame 6 Inter, use LGA, update L
* Frame 7 Inter, use LGA, update none
* Frame 8 Inter, use A, update L&G&A
* Frame 9 Inter, use LGA, update none
* Frame 10 Inter, use LGA, update L
* Frame 11 Inter, use LGA, update none
* Frame 12 Inter, use GA, update L&G
* Frame 13 Inter, use LGA, update none
* Frame 14 Inter, use LGA, update L
* Frame 15 Inter, use LGA, update none
* ...Repeats the pattern from frame 0
Change this variable to test the 3 decodable streams case.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS
int num_streams = 5;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
flags = 0;
if(num_streams == 5)
{
switch(frame_cnt % 16) {
case 0:
flags |= VPX_EFLAG_FORCE_KF;
flags |= VP8_EFLAG_FORCE_GF;
flags |= VP8_EFLAG_FORCE_ARF;
break;
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 13:
case 15:
flags |= VP8_EFLAG_NO_UPD_LAST;
flags |= VP8_EFLAG_NO_UPD_GF;
flags |= VP8_EFLAG_NO_UPD_ARF;
break;
case 2:
case 6:
case 10:
case 14:
break;
case 4:
flags |= VP8_EFLAG_NO_REF_LAST;
flags |= VP8_EFLAG_FORCE_GF;
break;
case 8:
flags |= VP8_EFLAG_NO_REF_LAST;
flags |= VP8_EFLAG_NO_REF_GF;
flags |= VP8_EFLAG_FORCE_GF;
flags |= VP8_EFLAG_FORCE_ARF;
break;
case 12:
flags |= VP8_EFLAG_NO_REF_LAST;
flags |= VP8_EFLAG_FORCE_GF;
break;
}
}
else
{
switch(frame_cnt % 9) {
case 0:
if(frame_cnt==0)
{
flags |= VPX_EFLAG_FORCE_KF;
}
else
{
cfg.rc_max_quantizer = 26;
cfg.rc_min_quantizer = 0;
cfg.rc_target_bitrate = 300;
flags |= VP8_EFLAG_NO_REF_LAST;
flags |= VP8_EFLAG_NO_REF_ARF;
}
flags |= VP8_EFLAG_FORCE_GF;
flags |= VP8_EFLAG_FORCE_ARF;
break;
case 1:
case 2:
case 4:
case 5:
case 7:
case 8:
cfg.rc_max_quantizer = 45;
cfg.rc_min_quantizer = 0;
cfg.rc_target_bitrate = 230;
break;
case 3:
case 6:
cfg.rc_max_quantizer = 45;
cfg.rc_min_quantizer = 0;
cfg.rc_target_bitrate = 215;
flags |= VP8_EFLAG_NO_REF_LAST;
flags |= VP8_EFLAG_FORCE_ARF;
break;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
Observing The Effects
---------------------
Use the `decode_with_drops` example to decode with various dropped frame
patterns. Good patterns to start with are 1/2, 3/4, 7/8, and 15/16
drops.
......@@ -19,6 +19,7 @@ extern "C"
#include "vpx/internal/vpx_codec_internal.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
#include "vpx_scale/yv12config.h"
#include "type_aliases.h"
#include "ppflags.h"
......@@ -198,6 +199,14 @@ extern "C"
struct vpx_codec_pkt_list *output_pkt_list;
vp8e_tuning tuning;
// Temporal scaling parameters
unsigned int number_of_layers;
unsigned int target_bitrate[MAX_PERIODICITY];
unsigned int rate_decimator[MAX_PERIODICITY];
unsigned int periodicity;
unsigned int layer_id[MAX_PERIODICITY];
} VP8_CONFIG;
......
......@@ -456,7 +456,7 @@ void encode_mb_row(VP8_COMP *cpi,
vp8_activity_masking(cpi, x);
// Is segmentation enabled
// MB level adjutment to quantizer
// MB level adjustment to quantizer
if (xd->segmentation_enabled)
{
// Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
......@@ -505,7 +505,8 @@ void encode_mb_row(VP8_COMP *cpi,
// Special case code for cyclic refresh
// If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
// during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
if ((cpi->current_layer == 0) &&
(cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled))
{
cpi->segmentation_map[map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
......@@ -648,6 +649,30 @@ void init_encode_frame_mb_context(VP8_COMP *cpi)
+ vp8_cost_one(255)
+ vp8_cost_one(128);
}
else if ((cpi->oxcf.number_of_layers > 1) &&
(cpi->ref_frame_flags == VP8_GOLD_FLAG))
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(1);
xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_zero(255);
xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_one(255);
}
else if ((cpi->oxcf.number_of_layers > 1) &&
(cpi->ref_frame_flags == VP8_ALT_FLAG))
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(1);
xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_zero(1);
xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_one(1);
}
else
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
......@@ -937,7 +962,8 @@ void vp8_encode_frame(VP8_COMP *cpi)
// Adjust the projected reference frame useage probability numbers to reflect
// what we have just seen. This may be usefull when we make multiple itterations
// of the recode loop rather than continuing to use values from the previous frame.
if ((cm->frame_type != KEY_FRAME) && !cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)
if ((cm->frame_type != KEY_FRAME) && ((cpi->oxcf.number_of_layers > 1) ||
(!cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)))
{
const int *const rfct = cpi->count_mb_ref_frame_usage;
const int rf_intra = rfct[INTRA_FRAME];
......@@ -1220,7 +1246,7 @@ int vp8cx_encode_inter_macroblock
if (xd->segmentation_enabled)
{
// If cyclic update enabled
if (cpi->cyclic_refresh_mode_enabled)
if (cpi->current_layer == 0 && cpi->cyclic_refresh_mode_enabled)
{
// Clear segment_id back to 0 if not coded (last frame 0,0)
if ((xd->mode_info_context->mbmi.segment_id == 1) &&
......
This diff is collapsed.
......@@ -56,6 +56,8 @@
#define VP8_TEMPORAL_ALT_REF 1
#endif
#define MAX_PERIODICITY 16
typedef struct
{
int kf_indicated;
......@@ -238,6 +240,52 @@ enum
BLOCK_MAX_SEGMENTS
};
typedef struct
{
// Layer configuration
double frame_rate;
int target_bandwidth;
// Layer specific coding parameters
int starting_buffer_level;
int optimal_buffer_level;
int maximum_buffer_size;
int avg_frame_size_for_layer;
int buffer_level;
int bits_off_target;
long long total_actual_bits;
int total_target_vs_actual;
int worst_quality;
int active_worst_quality;
int best_quality;
int active_best_quality;
int ni_av_qi;
int ni_tot_qi;
int ni_frames;
int avg_frame_qindex;
double rate_correction_factor;
double key_frame_rate_correction_factor;
double gf_rate_correction_factor;
int zbin_over_quant;
int inter_frame_target;
INT64 total_byte_count;
int filter_level;
int last_frame_percent_intra;
int count_mb_ref_frame_usage[MAX_REF_FRAMES];
} LAYER_CONTEXT;
typedef struct VP8_COMP
{
......@@ -610,6 +658,25 @@ typedef struct VP8_COMP
int force_next_frame_intra; /* force next frame to intra when kf_auto says so */
int droppable;
// Coding layer state variables
unsigned int current_layer;
LAYER_CONTEXT layer_context[MAX_LAYERS];
long long frames_in_layer[MAX_LAYERS];
long long bytes_in_layer[MAX_LAYERS];
double sum_psnr[MAX_LAYERS];
double sum_psnr_p[MAX_LAYERS];
double total_error2[MAX_LAYERS];
double total_error2_p[MAX_LAYERS];
double sum_ssim[MAX_LAYERS];
double sum_weights[MAX_LAYERS];
double total_ssimg_y_in_layer[MAX_LAYERS];
double total_ssimg_u_in_layer[MAX_LAYERS];
double total_ssimg_v_in_layer[MAX_LAYERS];
double total_ssimg_all_in_layer[MAX_LAYERS];
} VP8_COMP;
void control_data_rate(VP8_COMP *cpi);
......
......@@ -471,7 +471,8 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
else
skip_mode[GOLDEN_FRAME] = 1;
if (cpi->ref_frame_flags & VP8_ALT_FLAG && cpi->source_alt_ref_active)
if ((cpi->ref_frame_flags & VP8_ALT_FLAG) &&
(cpi->source_alt_ref_active || cpi->oxcf.number_of_layers > 1))
{
YV12_BUFFER_CONFIG *alt_yv12 = &cpi->common.yv12_fb[cpi->common.alt_fb_idx];
y_buffer[ALTREF_FRAME] = alt_yv12->y_buffer + recon_yoffset;
......
......@@ -436,7 +436,8 @@ static void calc_iframe_target_size(VP8_COMP *cpi)
}
// Do the best we can to define the parameteres for the next GF based on what information we have available.
// Do the best we can to define the parameters for the next GF based on what
// information we have available.
static void calc_gf_params(VP8_COMP *cpi)
{
int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
......@@ -607,6 +608,11 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
{
int min_frame_target;
int Adjustment;
int old_per_frame_bandwidth = cpi->per_frame_bandwidth;
if ( cpi->current_layer > 0)
cpi->per_frame_bandwidth =
cpi->layer_context[cpi->current_layer].avg_frame_size_for_layer;
min_frame_target = 0;
......@@ -622,7 +628,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
// Special alt reference frame case
if (cpi->common.refresh_alt_ref_frame)
if((cpi->common.refresh_alt_ref_frame) && (cpi->oxcf.number_of_layers == 1))
{
if (cpi->pass == 2)
{
......@@ -789,7 +795,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
// Decide whether or not we need to adjust the frame data rate target.
//
// If we are are below the optimal buffer fullness level and adherence
// to buffering contraints is important to the end useage then adjust
// to buffering constraints is important to the end usage then adjust
// the per frame target.
if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
(cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
......@@ -812,12 +818,12 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
percent_low = 0;
// lower the target bandwidth for this frame.
cpi->this_frame_target -= (cpi->this_frame_target * percent_low)
/ 200;
cpi->this_frame_target -=
(cpi->this_frame_target * percent_low) / 200;
// Are we using allowing control of active_worst_allowed_q
// according to buffer level.
if (cpi->auto_worst_q)
if (cpi->auto_worst_q && cpi->ni_frames > 150)
{
int critical_buffer_level;
......@@ -834,7 +840,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
(cpi->buffer_level < cpi->bits_off_target)
? cpi->buffer_level : cpi->bits_off_target;
}
// For local file playback short term buffering contraints
// For local file playback short term buffering constraints
// are less of an issue
else
{
......@@ -905,11 +911,11 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
percent_high = 0;
cpi->this_frame_target += (cpi->this_frame_target *
percent_high) / 200;
percent_high) / 200;
// Are we allowing control of active_worst_allowed_q according to bufferl level.
if (cpi->auto_worst_q)
// Are we allowing control of active_worst_allowed_q according
// to buffer level.
if (cpi->auto_worst_q && cpi->ni_frames > 150)
{
// When using the relaxed buffer model stick to the user specified value
cpi->active_worst_quality = cpi->ni_av_qi;
......@@ -1112,6 +1118,8 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
}
}
cpi->per_frame_bandwidth = old_per_frame_bandwidth;
}
......@@ -1421,8 +1429,14 @@ void vp8_adjust_key_frame_context(VP8_COMP *cpi)
* bits allocated than those following other gfs.
*/
overspend = (cpi->projected_frame_size - cpi->per_frame_bandwidth);
cpi->kf_overspend_bits += overspend * 7 / 8;
cpi->gf_overspend_bits += overspend * 1 / 8;
if (cpi->oxcf.number_of_layers > 1)
cpi->kf_overspend_bits += overspend;
else
{
cpi->kf_overspend_bits += overspend * 7 / 8;
cpi->gf_overspend_bits += overspend * 1 / 8;
}
/* Work out how much to try and recover per frame. */
cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits
......@@ -1452,7 +1466,9 @@ void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit,
}
else
{
if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
if (cpi->oxcf.number_of_layers > 1 ||
cpi->common.refresh_alt_ref_frame ||
cpi->common.refresh_golden_frame)
{
*frame_over_shoot_limit = cpi->this_frame_target * 9 / 8;
*frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
......
......@@ -218,6 +218,25 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
}
#endif
RANGE_CHECK(cfg, ts_number_layers, 1, 5);
if (cfg->ts_number_layers > 1)
{
int i;
RANGE_CHECK_HI(cfg, ts_periodicity, 16);
for (i=1; i<cfg->ts_number_layers; i++)
if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1])
ERROR("ts_target_bitrate entries are not strictly increasing");
RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
for (i=cfg->ts_number_layers-2; i>0; i--)
if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i])
ERROR("ts_rate_decimator factors are not powers of 2");
RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers-1);
}
return VPX_CODEC_OK;
}
......@@ -253,14 +272,15 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->Width = cfg.g_w;
oxcf->Height = cfg.g_h;
/* guess a frame rate if out of whack, use 30 */
oxcf->frame_rate = (double)(cfg.g_timebase.den) / (double)(cfg.g_timebase.num);
oxcf->frame_rate = (double)(cfg.g_timebase.den) /
(double)(cfg.g_timebase.num);
if (oxcf->frame_rate > 180)
{
oxcf->frame_rate = 30;
}
oxcf->error_resilient_mode = cfg.g_error_resilient;
oxcf->error_resilient_mode = cfg.g_error_resilient;
switch (cfg.g_pass)
{
......@@ -277,13 +297,13 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
if (cfg.g_pass == VPX_RC_FIRST_PASS)
{
oxcf->allow_lag = 0;
oxcf->lag_in_frames = 0;
oxcf->allow_lag = 0;
oxcf->lag_in_frames = 0;
}
else
{
oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
oxcf->lag_in_frames = cfg.g_lag_in_frames;
oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
oxcf->lag_in_frames = cfg.g_lag_in_frames;
}
oxcf->allow_df = (cfg.rc_dropframe_thresh > 0);
......@@ -295,59 +315,71 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
if (cfg.rc_end_usage == VPX_VBR)
{
oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
}
else if (cfg.rc_end_usage == VPX_CBR)
{
oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
}
else if (cfg.rc_end_usage == VPX_CQ)
{
oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
}
oxcf->target_bandwidth = cfg.rc_target_bitrate;
oxcf->target_bandwidth = cfg.rc_target_bitrate;
oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
oxcf->best_allowed_q = cfg.rc_min_quantizer;
oxcf->worst_allowed_q = cfg.rc_max_quantizer;
oxcf->cq_level = vp8_cfg.cq_level;
oxcf->best_allowed_q = cfg.rc_min_quantizer;
oxcf->worst_allowed_q = cfg.rc_max_quantizer;
oxcf->cq_level = vp8_cfg.cq_level;
oxcf->fixed_q = -1;
oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
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;
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;
oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct;
oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct;
oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO
&& cfg.kf_min_dist != cfg.kf_max_dist;
//oxcf->kf_min_dist = cfg.kf_min_dis;
oxcf->key_freq = cfg.kf_max_dist;
oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO
&& cfg.kf_min_dist != cfg.kf_max_dist;
//oxcf->kf_min_dist = cfg.kf_min_dis;
oxcf->key_freq = cfg.kf_max_dist;
oxcf->number_of_layers = cfg.ts_number_layers;
oxcf->periodicity = cfg.ts_periodicity;
if (oxcf->number_of_layers > 1)
{
memcpy (oxcf->target_bitrate, cfg.ts_target_bitrate,
sizeof(cfg.ts_target_bitrate));
memcpy (oxcf->rate_decimator, cfg.ts_rate_decimator,
sizeof(cfg.ts_rate_decimator));
memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
}
//oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
//strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
oxcf->cpu_used = vp8_cfg.cpu_used;
oxcf->encode_breakout = vp8_cfg.static_thresh;
oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
oxcf->Sharpness = vp8_cfg.Sharpness;
oxcf->token_partitions = vp8_cfg.token_partitions;
oxcf->cpu_used = vp8_cfg.cpu_used;
oxcf->encode_breakout = vp8_cfg.static_thresh;
oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
oxcf->Sharpness = vp8_cfg.Sharpness;
oxcf->token_partitions = vp8_cfg.token_partitions;
oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
oxcf->output_pkt_list = vp8_cfg.pkt_list;
oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
oxcf->output_pkt_list = vp8_cfg.pkt_list;
oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
oxcf->arnr_strength = vp8_cfg.arnr_strength;
oxcf->arnr_type = vp8_cfg.arnr_type;
oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
oxcf->arnr_strength = vp8_cfg.arnr_strength;
oxcf->arnr_type = vp8_cfg.arnr_type;
oxcf->tuning = vp8_cfg.tuning;
oxcf->tuning = vp8_cfg.tuning;
/*
printf("Current VP8 Settings: \n");
......@@ -515,7 +547,7 @@ static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx)
cfg = &ctx->priv->alg_priv->cfg;
/* Select the extra vp6 configuration table based on the current
/* Select the extra vp8 configuration table based on the current
* usage value. If the current usage value isn't found, use the
* values for usage case 0.
*/
......@@ -1143,6 +1175,12 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
1, /* g_delete_first_pass_file */
"vp8.fpf" /* first pass filename */
#endif
1, /* ts_number_layers */
{0}, /* ts_target_bitrate */
{0}, /* ts_rate_decimator */
0, /* ts_periodicity */
{0}, /* ts_layer_id */
}},
{ -1, {NOT_IMPLEMENTED}}
};
......
This diff is collapsed.
......@@ -32,6 +32,8 @@ extern "C" {
#define VPX_ENCODER_H
#include "vpx_codec.h"
#define MAX_PERIODICITY 16
#define MAX_LAYERS 5
/*!\brief Current ABI version number
*
......@@ -592,6 +594,47 @@ extern "C" {
*/
unsigned int kf_max_dist;
/*
* Temporal scalability settings (ts)
*/
/*!\brief Number of coding layers
*
* This value specifies the number of coding layers to be used.
*/
unsigned int ts_number_layers;
/*!\brief Target bitrate for each layer
*
* These values specify the target coding bitrate for each coding layer.
*/
unsigned int ts_target_bitrate[MAX_LAYERS];
/*!\brief Frame rate decimation factor for each layer
*
* These values specify the frame rate decimation factors to apply
* to each layer.
*/
unsigned int ts_rate_decimator[MAX_LAYERS];
/*!\brief Length of the sequence defining frame layer membership
*
* This value specifies the length of the sequence that defines the
* membership of frames to layers. For example, if ts_periodicity=8 then
* frames are assigned to coding layers with a repeated sequence of
* length 8.
*/
unsigned int ts_periodicity;
/*!\brief Template defining the membership of frames to coding layers
*
* This array defines the membership of frames to coding layers. For a
* 2-layer encoding that assigns even numbered frames to one layer (0)
* and odd numbered frames to a second layer (1) with ts_periodicity=8,
* then ts_layer_id = (0,1,0,1,0,1,0,1).
*/
unsigned int ts_layer_id[MAX_PERIODICITY];
} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
......
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