Merge "Move svc layer_context to separate file."

This commit is contained in:
Marco Paniconi 2014-03-13 14:49:15 -07:00 committed by Gerrit Code Review
commit 07fbd70e38
6 changed files with 223 additions and 151 deletions

View File

@ -40,6 +40,7 @@
#include "vp9/encoder/vp9_temporal_filter.h"
#include "vp9/encoder/vp9_vaq.h"
#include "vp9/encoder/vp9_resize.h"
#include "vp9/encoder/vp9_svc_layercontext.h"
void vp9_coef_tree_initialize();
@ -1109,10 +1110,9 @@ static void update_frame_size(VP9_COMP *cpi) {
}
}
// Table that converts 0-63 Q range values passed in outside to the Qindex
// range used internally.
static const int q_trans[] = {
const int q_trans[] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, 52, 56, 60,
64, 68, 72, 76, 80, 84, 88, 92,
@ -1181,7 +1181,7 @@ void vp9_new_framerate(VP9_COMP *cpi, double framerate) {
rc->max_gf_interval = rc->static_scene_max_gf_interval;
}
static int64_t rescale(int64_t val, int64_t num, int denom) {
int64_t vp9_rescale(int64_t val, int64_t num, int denom) {
int64_t llnum = num;
int64_t llden = denom;
int64_t llval = val;
@ -1189,124 +1189,6 @@ static int64_t rescale(int64_t val, int64_t num, int denom) {
return (llval * llnum / llden);
}
// Initialize layer context data from init_config().
static void init_layer_context(VP9_COMP *const cpi) {
const VP9_CONFIG *const oxcf = &cpi->oxcf;
int temporal_layer = 0;
cpi->svc.spatial_layer_id = 0;
cpi->svc.temporal_layer_id = 0;
for (temporal_layer = 0; temporal_layer < cpi->svc.number_temporal_layers;
++temporal_layer) {
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
RATE_CONTROL *const lrc = &lc->rc;
lrc->avg_frame_qindex[INTER_FRAME] = q_trans[oxcf->worst_allowed_q];
lrc->last_q[INTER_FRAME] = q_trans[oxcf->worst_allowed_q];
lrc->ni_av_qi = q_trans[oxcf->worst_allowed_q];
lrc->total_actual_bits = 0;
lrc->total_target_vs_actual = 0;
lrc->ni_tot_qi = 0;
lrc->tot_q = 0.0;
lrc->avg_q = 0.0;
lrc->ni_frames = 0;
lrc->decimation_count = 0;
lrc->decimation_factor = 0;
lrc->rate_correction_factor = 1.0;
lrc->key_frame_rate_correction_factor = 1.0;
lc->target_bandwidth = oxcf->ts_target_bitrate[temporal_layer] *
1000;
lrc->buffer_level = rescale((int)(oxcf->starting_buffer_level),
lc->target_bandwidth, 1000);
lrc->bits_off_target = lrc->buffer_level;
}
}
// Update the layer context from a change_config() call.
static void update_layer_context_change_config(VP9_COMP *const cpi,
const int target_bandwidth) {
const VP9_CONFIG *const oxcf = &cpi->oxcf;
const RATE_CONTROL *const rc = &cpi->rc;
int temporal_layer = 0;
float bitrate_alloc = 1.0;
for (temporal_layer = 0; temporal_layer < cpi->svc.number_temporal_layers;
++temporal_layer) {
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
RATE_CONTROL *const lrc = &lc->rc;
lc->target_bandwidth = oxcf->ts_target_bitrate[temporal_layer] * 1000;
bitrate_alloc = (float)lc->target_bandwidth / (float)target_bandwidth;
// Update buffer-related quantities.
lc->starting_buffer_level =
(int64_t)(oxcf->starting_buffer_level * bitrate_alloc);
lc->optimal_buffer_level =
(int64_t)(oxcf->optimal_buffer_level * bitrate_alloc);
lc->maximum_buffer_size =
(int64_t)(oxcf->maximum_buffer_size * bitrate_alloc);
lrc->bits_off_target = MIN(lrc->bits_off_target, lc->maximum_buffer_size);
lrc->buffer_level = MIN(lrc->buffer_level, lc->maximum_buffer_size);
// Update framerate-related quantities.
lc->framerate = oxcf->framerate / oxcf->ts_rate_decimator[temporal_layer];
lrc->av_per_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
// Update qp-related quantities.
lrc->worst_quality = rc->worst_quality;
lrc->best_quality = rc->best_quality;
}
}
// Prior to encoding the frame, update framerate-related quantities
// for the current layer.
static void update_layer_framerate(VP9_COMP *const cpi) {
int temporal_layer = cpi->svc.temporal_layer_id;
const VP9_CONFIG *const oxcf = &cpi->oxcf;
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
RATE_CONTROL *const lrc = &lc->rc;
lc->framerate = oxcf->framerate / oxcf->ts_rate_decimator[temporal_layer];
lrc->av_per_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
// Update the average layer frame size (non-cumulative per-frame-bw).
if (temporal_layer == 0) {
lc->avg_frame_size = lrc->av_per_frame_bandwidth;
} else {
double prev_layer_framerate = oxcf->framerate /
oxcf->ts_rate_decimator[temporal_layer - 1];
int prev_layer_target_bandwidth =
oxcf->ts_target_bitrate[temporal_layer - 1] * 1000;
lc->avg_frame_size =
(int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
(lc->framerate - prev_layer_framerate));
}
}
// Prior to encoding the frame, set the layer context, for the current layer
// to be encoded, to the cpi struct.
static void restore_layer_context(VP9_COMP *const cpi) {
int temporal_layer = cpi->svc.temporal_layer_id;
LAYER_CONTEXT *lc = &cpi->svc.layer_context[temporal_layer];
int frame_since_key = cpi->rc.frames_since_key;
int frame_to_key = cpi->rc.frames_to_key;
cpi->rc = lc->rc;
cpi->oxcf.target_bandwidth = lc->target_bandwidth;
cpi->oxcf.starting_buffer_level = lc->starting_buffer_level;
cpi->oxcf.optimal_buffer_level = lc->optimal_buffer_level;
cpi->oxcf.maximum_buffer_size = lc->maximum_buffer_size;
cpi->output_framerate = lc->framerate;
// Reset the frames_since_key and frames_to_key counters to their values
// before the layer restore. Keep these defined for the stream (not layer).
cpi->rc.frames_since_key = frame_since_key;
cpi->rc.frames_to_key = frame_to_key;
}
// Save the layer context after encoding the frame.
static void save_layer_context(VP9_COMP *const cpi) {
int temporal_layer = cpi->svc.temporal_layer_id;
LAYER_CONTEXT *lc = &cpi->svc.layer_context[temporal_layer];
lc->rc = cpi->rc;
lc->target_bandwidth = (int)cpi->oxcf.target_bandwidth;
lc->starting_buffer_level = cpi->oxcf.starting_buffer_level;
lc->optimal_buffer_level = cpi->oxcf.optimal_buffer_level;
lc->maximum_buffer_size = cpi->oxcf.maximum_buffer_size;
lc->framerate = cpi->output_framerate;
}
static void set_tile_limits(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
@ -1339,7 +1221,7 @@ static void init_config(struct VP9_COMP *cpi, VP9_CONFIG *oxcf) {
if (cpi->svc.number_temporal_layers > 1 &&
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
init_layer_context(cpi);
vp9_init_layer_context(cpi);
}
// change includes all joint functionality
@ -1468,21 +1350,24 @@ void vp9_change_config(struct VP9_COMP *cpi, VP9_CONFIG *oxcf) {
// Convert target bandwidth from Kbit/s to Bit/s
cpi->oxcf.target_bandwidth *= 1000;
cpi->oxcf.starting_buffer_level = rescale(cpi->oxcf.starting_buffer_level,
cpi->oxcf.target_bandwidth, 1000);
cpi->oxcf.starting_buffer_level =
vp9_rescale(cpi->oxcf.starting_buffer_level,
cpi->oxcf.target_bandwidth, 1000);
// Set or reset optimal and maximum buffer levels.
if (cpi->oxcf.optimal_buffer_level == 0)
cpi->oxcf.optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
else
cpi->oxcf.optimal_buffer_level = rescale(cpi->oxcf.optimal_buffer_level,
cpi->oxcf.target_bandwidth, 1000);
cpi->oxcf.optimal_buffer_level =
vp9_rescale(cpi->oxcf.optimal_buffer_level,
cpi->oxcf.target_bandwidth, 1000);
if (cpi->oxcf.maximum_buffer_size == 0)
cpi->oxcf.maximum_buffer_size = cpi->oxcf.target_bandwidth / 8;
else
cpi->oxcf.maximum_buffer_size = rescale(cpi->oxcf.maximum_buffer_size,
cpi->oxcf.target_bandwidth, 1000);
cpi->oxcf.maximum_buffer_size =
vp9_rescale(cpi->oxcf.maximum_buffer_size,
cpi->oxcf.target_bandwidth, 1000);
// Under a configuration change, where maximum_buffer_size may change,
// keep buffer level clipped to the maximum allowed buffer size.
cpi->rc.bits_off_target = MIN(cpi->rc.bits_off_target,
@ -1522,7 +1407,8 @@ void vp9_change_config(struct VP9_COMP *cpi, VP9_CONFIG *oxcf) {
if (cpi->svc.number_temporal_layers > 1 &&
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
update_layer_context_change_config(cpi, (int)cpi->oxcf.target_bandwidth);
vp9_update_layer_context_change_config(cpi,
(int)cpi->oxcf.target_bandwidth);
}
cpi->speed = abs(cpi->oxcf.cpu_used);
@ -3671,8 +3557,8 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
if (cpi->svc.number_temporal_layers > 1 &&
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
update_layer_framerate(cpi);
restore_layer_context(cpi);
vp9_update_layer_framerate(cpi);
vp9_restore_layer_context(cpi);
}
// start with a 0 size frame
@ -3754,7 +3640,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
// Save layer specific state.
if (cpi->svc.number_temporal_layers > 1 &&
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
save_layer_context(cpi);
vp9_save_layer_context(cpi);
}
vpx_usec_timer_mark(&cmptimer);

View File

@ -30,6 +30,7 @@
#include "vp9/encoder/vp9_mcomp.h"
#include "vp9/encoder/vp9_quantize.h"
#include "vp9/encoder/vp9_ratectrl.h"
#include "vp9/encoder/vp9_svc_layercontext.h"
#include "vp9/encoder/vp9_tokenize.h"
#include "vp9/encoder/vp9_variance.h"
@ -432,16 +433,6 @@ typedef struct {
BLOCK_SIZE max_intra_bsize;
} SPEED_FEATURES;
typedef struct {
RATE_CONTROL rc;
int target_bandwidth;
int64_t starting_buffer_level;
int64_t optimal_buffer_level;
int64_t maximum_buffer_size;
double framerate;
int avg_frame_size;
} LAYER_CONTEXT;
typedef enum {
NORMAL = 0,
FOURFIVE = 1,
@ -822,15 +813,7 @@ typedef struct VP9_COMP {
int use_svc;
struct svc {
int spatial_layer_id;
int temporal_layer_id;
int number_spatial_layers;
int number_temporal_layers;
// Layer context used for rate control in CBR mode, only defined for
// temporal layers for now.
LAYER_CONTEXT layer_context[VPX_TS_MAX_LAYERS];
} svc;
SVC svc;
#if CONFIG_MULTIPLE_ARF
// ARF tracking variables.
@ -943,6 +926,10 @@ static int get_token_alloc(int mb_rows, int mb_cols) {
return mb_rows * mb_cols * (48 * 16 + 4);
}
extern const int q_trans[];
int64_t vp9_rescale(int64_t val, int64_t num, int denom);
static void set_ref_ptrs(VP9_COMMON *cm, MACROBLOCKD *xd,
MV_REFERENCE_FRAME ref0, MV_REFERENCE_FRAME ref1) {
xd->block_refs[0] = &cm->frame_refs[ref0 >= LAST_FRAME ? ref0 - LAST_FRAME

View File

@ -12,6 +12,10 @@
#ifndef VP9_ENCODER_VP9_RATECTRL_H_
#define VP9_ENCODER_VP9_RATECTRL_H_
#include "vpx/vpx_integer.h"
#include "vp9/common/vp9_blockd.h"
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "vp9/encoder/vp9_onyx_int.h"
#include "vp9/encoder/vp9_svc_layercontext.h"
void vp9_init_layer_context(VP9_COMP *const cpi) {
const VP9_CONFIG *const oxcf = &cpi->oxcf;
int temporal_layer = 0;
cpi->svc.spatial_layer_id = 0;
cpi->svc.temporal_layer_id = 0;
for (temporal_layer = 0; temporal_layer < cpi->svc.number_temporal_layers;
++temporal_layer) {
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
RATE_CONTROL *const lrc = &lc->rc;
lrc->avg_frame_qindex[INTER_FRAME] = q_trans[oxcf->worst_allowed_q];
lrc->last_q[INTER_FRAME] = q_trans[oxcf->worst_allowed_q];
lrc->ni_av_qi = q_trans[oxcf->worst_allowed_q];
lrc->total_actual_bits = 0;
lrc->total_target_vs_actual = 0;
lrc->ni_tot_qi = 0;
lrc->tot_q = 0.0;
lrc->avg_q = 0.0;
lrc->ni_frames = 0;
lrc->decimation_count = 0;
lrc->decimation_factor = 0;
lrc->rate_correction_factor = 1.0;
lrc->key_frame_rate_correction_factor = 1.0;
lc->target_bandwidth = oxcf->ts_target_bitrate[temporal_layer] *
1000;
lrc->buffer_level =
vp9_rescale((int)(oxcf->starting_buffer_level),
lc->target_bandwidth, 1000);
lrc->bits_off_target = lrc->buffer_level;
}
}
// Update the layer context from a change_config() call.
void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
const int target_bandwidth) {
const VP9_CONFIG *const oxcf = &cpi->oxcf;
const RATE_CONTROL *const rc = &cpi->rc;
int temporal_layer = 0;
float bitrate_alloc = 1.0;
for (temporal_layer = 0; temporal_layer < cpi->svc.number_temporal_layers;
++temporal_layer) {
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
RATE_CONTROL *const lrc = &lc->rc;
lc->target_bandwidth = oxcf->ts_target_bitrate[temporal_layer] * 1000;
bitrate_alloc = (float)lc->target_bandwidth / (float)target_bandwidth;
// Update buffer-related quantities.
lc->starting_buffer_level =
(int64_t)(oxcf->starting_buffer_level * bitrate_alloc);
lc->optimal_buffer_level =
(int64_t)(oxcf->optimal_buffer_level * bitrate_alloc);
lc->maximum_buffer_size =
(int64_t)(oxcf->maximum_buffer_size * bitrate_alloc);
lrc->bits_off_target = MIN(lrc->bits_off_target, lc->maximum_buffer_size);
lrc->buffer_level = MIN(lrc->buffer_level, lc->maximum_buffer_size);
// Update framerate-related quantities.
lc->framerate = oxcf->framerate / oxcf->ts_rate_decimator[temporal_layer];
lrc->av_per_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
// Update qp-related quantities.
lrc->worst_quality = rc->worst_quality;
lrc->best_quality = rc->best_quality;
}
}
void vp9_update_layer_framerate(VP9_COMP *const cpi) {
int temporal_layer = cpi->svc.temporal_layer_id;
const VP9_CONFIG *const oxcf = &cpi->oxcf;
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
RATE_CONTROL *const lrc = &lc->rc;
lc->framerate = oxcf->framerate / oxcf->ts_rate_decimator[temporal_layer];
lrc->av_per_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
// Update the average layer frame size (non-cumulative per-frame-bw).
if (temporal_layer == 0) {
lc->avg_frame_size = lrc->av_per_frame_bandwidth;
} else {
double prev_layer_framerate = oxcf->framerate /
oxcf->ts_rate_decimator[temporal_layer - 1];
int prev_layer_target_bandwidth =
oxcf->ts_target_bitrate[temporal_layer - 1] * 1000;
lc->avg_frame_size =
(int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
(lc->framerate - prev_layer_framerate));
}
}
void vp9_restore_layer_context(VP9_COMP *const cpi) {
int temporal_layer = cpi->svc.temporal_layer_id;
LAYER_CONTEXT *lc = &cpi->svc.layer_context[temporal_layer];
int frame_since_key = cpi->rc.frames_since_key;
int frame_to_key = cpi->rc.frames_to_key;
cpi->rc = lc->rc;
cpi->oxcf.target_bandwidth = lc->target_bandwidth;
cpi->oxcf.starting_buffer_level = lc->starting_buffer_level;
cpi->oxcf.optimal_buffer_level = lc->optimal_buffer_level;
cpi->oxcf.maximum_buffer_size = lc->maximum_buffer_size;
cpi->output_framerate = lc->framerate;
// Reset the frames_since_key and frames_to_key counters to their values
// before the layer restore. Keep these defined for the stream (not layer).
cpi->rc.frames_since_key = frame_since_key;
cpi->rc.frames_to_key = frame_to_key;
}
void vp9_save_layer_context(VP9_COMP *const cpi) {
int temporal_layer = cpi->svc.temporal_layer_id;
LAYER_CONTEXT *lc = &cpi->svc.layer_context[temporal_layer];
lc->rc = cpi->rc;
lc->target_bandwidth = (int)cpi->oxcf.target_bandwidth;
lc->starting_buffer_level = cpi->oxcf.starting_buffer_level;
lc->optimal_buffer_level = cpi->oxcf.optimal_buffer_level;
lc->maximum_buffer_size = cpi->oxcf.maximum_buffer_size;
lc->framerate = cpi->output_framerate;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP9_ENCODER_VP9_SVC_LAYERCONTEXT_H_
#define VP9_ENCODER_VP9_SVC_LAYERCONTEXT_H_
#include "vpx/vpx_encoder.h"
#include "vp9/encoder/vp9_ratectrl.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
RATE_CONTROL rc;
int target_bandwidth;
int64_t starting_buffer_level;
int64_t optimal_buffer_level;
int64_t maximum_buffer_size;
double framerate;
int avg_frame_size;
} LAYER_CONTEXT;
typedef struct {
int spatial_layer_id;
int temporal_layer_id;
int number_spatial_layers;
int number_temporal_layers;
// Layer context used for rate control in CBR mode, only defined for
// temporal layers for now.
LAYER_CONTEXT layer_context[VPX_TS_MAX_LAYERS];
} SVC;
struct VP9_COMP;
// Initialize layer context data from init_config().
void vp9_init_layer_context(struct VP9_COMP *const cpi);
// Update the layer context from a change_config() call.
void vp9_update_layer_context_change_config(struct VP9_COMP *const cpi,
const int target_bandwidth);
// Prior to encoding the frame, update framerate-related quantities
// for the current layer.
void vp9_update_layer_framerate(struct VP9_COMP *const cpi);
// Prior to encoding the frame, set the layer context, for the current layer
// to be encoded, to the cpi struct.
void vp9_restore_layer_context(struct VP9_COMP *const cpi);
// Save the layer context after encoding the frame.
void vp9_save_layer_context(struct VP9_COMP *const cpi);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP9_ENCODER_VP9_SVC_LAYERCONTEXT_

View File

@ -44,6 +44,7 @@ VP9_CX_SRCS-yes += encoder/vp9_quantize.h
VP9_CX_SRCS-yes += encoder/vp9_ratectrl.h
VP9_CX_SRCS-yes += encoder/vp9_rdopt.h
VP9_CX_SRCS-yes += encoder/vp9_pickmode.h
VP9_CX_SRCS-yes += encoder/vp9_svc_layercontext.h
VP9_CX_SRCS-yes += encoder/vp9_tokenize.h
VP9_CX_SRCS-yes += encoder/vp9_treewriter.h
VP9_CX_SRCS-yes += encoder/vp9_variance.h
@ -60,6 +61,7 @@ VP9_CX_SRCS-yes += encoder/vp9_segmentation.c
VP9_CX_SRCS-yes += encoder/vp9_segmentation.h
VP9_CX_SRCS-yes += encoder/vp9_subexp.c
VP9_CX_SRCS-yes += encoder/vp9_subexp.h
VP9_CX_SRCS-yes += encoder/vp9_svc_layercontext.c
VP9_CX_SRCS-yes += encoder/vp9_resize.c
VP9_CX_SRCS-yes += encoder/vp9_resize.h
VP9_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/vp9_ssim.c