Merge "[svc] Finalize spatial svc first pass rate control"

This commit is contained in:
Minghai Shang
2014-03-20 15:12:14 -07:00
committed by Gerrit Code Review
9 changed files with 173 additions and 65 deletions

View File

@@ -181,11 +181,13 @@ static void zero_stats(FIRSTPASS_STATS *section) {
section->new_mv_count = 0.0;
section->count = 0.0;
section->duration = 1.0;
section->spatial_layer_id = 0;
}
static void accumulate_stats(FIRSTPASS_STATS *section,
const FIRSTPASS_STATS *frame) {
section->frame += frame->frame;
section->spatial_layer_id = frame->spatial_layer_id;
section->intra_error += frame->intra_error;
section->coded_error += frame->coded_error;
section->sr_coded_error += frame->sr_coded_error;
@@ -342,7 +344,15 @@ void vp9_init_first_pass(VP9_COMP *cpi) {
}
void vp9_end_first_pass(VP9_COMP *cpi) {
output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
int i;
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
output_stats(&cpi->svc.layer_context[i].twopass.total_stats,
cpi->output_pkt_list);
}
} else {
output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
}
}
static vp9_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
@@ -464,11 +474,11 @@ void vp9_first_pass(VP9_COMP *cpi) {
int recon_yoffset, recon_uvoffset;
YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
YV12_BUFFER_CONFIG *const gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
const int recon_y_stride = lst_yv12->y_stride;
const int recon_uv_stride = lst_yv12->uv_stride;
const int uv_mb_height = 16 >> (lst_yv12->y_height > lst_yv12->uv_height);
int recon_y_stride = lst_yv12->y_stride;
int recon_uv_stride = lst_yv12->uv_stride;
int uv_mb_height = 16 >> (lst_yv12->y_height > lst_yv12->uv_height);
int64_t intra_error = 0;
int64_t coded_error = 0;
int64_t sr_coded_error = 0;
@@ -484,13 +494,43 @@ void vp9_first_pass(VP9_COMP *cpi) {
int new_mv_count = 0;
int sum_in_vectors = 0;
uint32_t lastmv_as_int = 0;
struct twopass_rc *const twopass = &cpi->twopass;
struct twopass_rc *twopass = &cpi->twopass;
const MV zero_mv = {0, 0};
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
vp9_clear_system_state();
if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
MV_REFERENCE_FRAME ref_frame = LAST_FRAME;
const YV12_BUFFER_CONFIG *scaled_ref_buf = NULL;
twopass = &cpi->svc.layer_context[cpi->svc.spatial_layer_id].twopass;
vp9_scale_references(cpi);
// Use either last frame or alt frame for motion search.
if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
scaled_ref_buf = vp9_get_scaled_ref_frame(cpi, LAST_FRAME);
ref_frame = LAST_FRAME;
} else if (cpi->ref_frame_flags & VP9_ALT_FLAG) {
scaled_ref_buf = vp9_get_scaled_ref_frame(cpi, ALTREF_FRAME);
ref_frame = ALTREF_FRAME;
}
if (scaled_ref_buf != NULL) {
// Update the stride since we are using scaled reference buffer
first_ref_buf = scaled_ref_buf;
recon_y_stride = first_ref_buf->y_stride;
recon_uv_stride = first_ref_buf->uv_stride;
uv_mb_height = 16 >> (first_ref_buf->y_height > first_ref_buf->uv_height);
}
// Disable golden frame for svc first pass for now.
gld_yv12 = NULL;
set_ref_ptrs(cm, xd, ref_frame, NONE);
}
vp9_setup_src_planes(x, cpi->Source, 0, 0);
vp9_setup_pre_planes(xd, 0, lst_yv12, 0, 0, NULL);
vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
vp9_setup_dst_planes(xd, new_yv12, 0, 0);
xd->mi_8x8 = cm->mi_grid_visible;
@@ -583,7 +623,7 @@ void vp9_first_pass(VP9_COMP *cpi) {
int tmp_err, motion_error;
int_mv mv, tmp_mv;
xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
motion_error = zz_motion_search(x);
// Assume 0,0 motion with no mv overhead.
mv.as_int = tmp_mv.as_int = 0;
@@ -615,7 +655,7 @@ void vp9_first_pass(VP9_COMP *cpi) {
}
// Search in an older reference frame.
if (cm->current_video_frame > 1) {
if (cm->current_video_frame > 1 && gld_yv12 != NULL) {
// Assume 0,0 motion with no mv overhead.
int gf_motion_error;
@@ -633,9 +673,9 @@ void vp9_first_pass(VP9_COMP *cpi) {
++second_ref_count;
// Reset to last frame as reference buffer.
xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
xd->plane[1].pre[0].buf = lst_yv12->u_buffer + recon_uvoffset;
xd->plane[2].pre[0].buf = lst_yv12->v_buffer + recon_uvoffset;
xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
xd->plane[1].pre[0].buf = first_ref_buf->u_buffer + recon_uvoffset;
xd->plane[2].pre[0].buf = first_ref_buf->v_buffer + recon_uvoffset;
// In accumulating a score for the older reference frame take the
// best of the motion predicted score and the intra coded error
@@ -743,6 +783,7 @@ void vp9_first_pass(VP9_COMP *cpi) {
FIRSTPASS_STATS fps;
fps.frame = cm->current_video_frame;
fps.spatial_layer_id = cpi->svc.spatial_layer_id;
fps.intra_error = (double)(intra_error >> 8);
fps.coded_error = (double)(coded_error >> 8);
fps.sr_coded_error = (double)(sr_coded_error >> 8);
@@ -792,20 +833,28 @@ void vp9_first_pass(VP9_COMP *cpi) {
(twopass->this_frame_stats.pcnt_inter > 0.20) &&
((twopass->this_frame_stats.intra_error /
DOUBLE_DIVIDE_CHECK(twopass->this_frame_stats.coded_error)) > 2.0))) {
vp8_yv12_copy_frame(lst_yv12, gld_yv12);
if (gld_yv12 != NULL) {
vp8_yv12_copy_frame(lst_yv12, gld_yv12);
}
twopass->sr_update_lag = 1;
} else {
++twopass->sr_update_lag;
}
// Swap frame pointers so last frame refers to the frame we just compressed.
swap_yv12(lst_yv12, new_yv12);
if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
vp9_update_reference_frames(cpi);
} else {
// Swap frame pointers so last frame refers to the frame we just compressed.
swap_yv12(lst_yv12, new_yv12);
}
vp9_extend_frame_borders(lst_yv12);
// Special case for the first frame. Copy into the GF buffer as a second
// reference.
if (cm->current_video_frame == 0)
if (cm->current_video_frame == 0 && gld_yv12 != NULL) {
vp8_yv12_copy_frame(lst_yv12, gld_yv12);
}
// Use this to see what the first pass reconstruction looks like.
if (0) {