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_ctx *ctx, int drain) { struct lookahead_entry *buf = NULL; if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) { buf = vp9_lookahead_peek(ctx, 0); if (buf != NULL) { // Only remove the buffer when pop the highest layer. if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) { vp9_lookahead_pop(ctx, drain); } } } return buf; }
void vp9_update_mbgraph_stats ( VP9_COMP *cpi ) { VP9_COMMON *const cm = &cpi->common; int i, n_frames = vp9_lookahead_depth(cpi->lookahead); YV12_BUFFER_CONFIG *golden_ref = &cm->yv12_fb[cm->gld_fb_idx]; // we need to look ahead beyond where the ARF transitions into // being a GF - so exit if we don't look ahead beyond that if (n_frames <= cpi->frames_till_gf_update_due) return; if (n_frames > (int)cpi->common.frames_till_alt_ref_frame) n_frames = cpi->common.frames_till_alt_ref_frame; if (n_frames > MAX_LAG_BUFFERS) n_frames = MAX_LAG_BUFFERS; cpi->mbgraph_n_frames = n_frames; for (i = 0; i < n_frames; i++) { MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i]; vpx_memset(frame_stats->mb_stats, 0, cm->mb_rows * cm->mb_cols * sizeof(*cpi->mbgraph_stats[i].mb_stats)); } // do motion search to find contribution of each reference to data // later on in this GF group // FIXME really, the GF/last MC search should be done forward, and // the ARF MC search backwards, to get optimal results for MV caching for (i = 0; i < n_frames; i++) { MBGRAPH_FRAME_STATS *frame_stats = &cpi->mbgraph_stats[i]; struct lookahead_entry *q_cur = vp9_lookahead_peek(cpi->lookahead, i); assert(q_cur != NULL); update_mbgraph_frame_stats(cpi, frame_stats, &q_cur->img, golden_ref, cpi->Source); } vp9_clear_system_state(); // __asm emms; separate_arf_mbs(cpi); }
int vp9_svc_start_frame(VP9_COMP *const cpi) { int width = 0, height = 0; LAYER_CONTEXT *lc; struct lookahead_entry *buf; int count = 1 << (cpi->svc.number_temporal_layers - 1); cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode; lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id]; cpi->svc.temporal_layer_id = 0; while ((lc->current_video_frame_in_layer % count) != 0) { ++cpi->svc.temporal_layer_id; count >>= 1; } cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG; cpi->lst_fb_idx = cpi->svc.spatial_layer_id; if (cpi->svc.spatial_layer_id == 0) cpi->gld_fb_idx = (lc->gold_ref_idx >= 0) ? lc->gold_ref_idx : cpi->lst_fb_idx; else cpi->gld_fb_idx = cpi->svc.spatial_layer_id - 1; if (lc->current_video_frame_in_layer == 0) { if (cpi->svc.spatial_layer_id >= 2) { cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2; } else { cpi->alt_fb_idx = cpi->lst_fb_idx; cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_ALT_FLAG); } } else { if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id]) { cpi->alt_fb_idx = lc->alt_ref_idx; if (!lc->has_alt_frame) cpi->ref_frame_flags &= (~VP9_ALT_FLAG); } else { // Find a proper alt_fb_idx for layers that don't have alt ref frame if (cpi->svc.spatial_layer_id == 0) { cpi->alt_fb_idx = cpi->lst_fb_idx; } else { LAYER_CONTEXT *lc_lower = &cpi->svc.layer_context[cpi->svc.spatial_layer_id - 1]; if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id - 1] && lc_lower->alt_ref_source != NULL) cpi->alt_fb_idx = lc_lower->alt_ref_idx; else if (cpi->svc.spatial_layer_id >= 2) cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2; else cpi->alt_fb_idx = cpi->lst_fb_idx; } } } get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height, lc->scaling_factor_num, lc->scaling_factor_den, &width, &height); // Workaround for multiple frame contexts. In some frames we can't use prev_mi // since its previous frame could be changed during decoding time. The idea is // we put a empty invisible frame in front of them, then we will not use // prev_mi when encoding these frames. buf = vp9_lookahead_peek(cpi->lookahead, 0); if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 && cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE && lc->rc.frames_to_key != 0 && !(buf != NULL && (buf->flags & VPX_EFLAG_FORCE_KF))) { if ((cpi->svc.number_temporal_layers > 1 && cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1) || (cpi->svc.number_spatial_layers > 1 && cpi->svc.spatial_layer_id == 0)) { struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead, 0); if (buf != NULL) { cpi->svc.empty_frame.ts_start = buf->ts_start; cpi->svc.empty_frame.ts_end = buf->ts_end; cpi->svc.encode_empty_frame_state = ENCODING; cpi->common.show_frame = 0; cpi->ref_frame_flags = 0; cpi->common.frame_type = INTER_FRAME; cpi->lst_fb_idx = cpi->gld_fb_idx = cpi->alt_fb_idx = SMALL_FRAME_FB_IDX; if (cpi->svc.encode_intra_empty_frame != 0) cpi->common.intra_only = 1; width = SMALL_FRAME_WIDTH; height = SMALL_FRAME_HEIGHT; } } } cpi->oxcf.worst_allowed_q = vp9_quantizer_to_qindex(lc->max_q); cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q); vp9_change_config(cpi, &cpi->oxcf); if (vp9_set_size_literal(cpi, width, height) != 0) return VPX_CODEC_INVALID_PARAM; vp9_set_high_precision_mv(cpi, 1); cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source; return 0; }
int vp9_svc_start_frame(VP9_COMP *const cpi) { int width = 0, height = 0; LAYER_CONTEXT *lc; struct lookahead_entry *buf; int count = 1 << (cpi->svc.number_temporal_layers - 1); cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode; lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id]; cpi->svc.temporal_layer_id = 0; while ((lc->current_video_frame_in_layer % count) != 0) { ++cpi->svc.temporal_layer_id; count >>= 1; } cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG; cpi->lst_fb_idx = cpi->svc.spatial_layer_id; if (cpi->svc.spatial_layer_id == 0) cpi->gld_fb_idx = (lc->gold_ref_idx >= 0) ? lc->gold_ref_idx : cpi->lst_fb_idx; else cpi->gld_fb_idx = cpi->svc.spatial_layer_id - 1; if (lc->current_video_frame_in_layer == 0) { if (cpi->svc.spatial_layer_id >= 2) { cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2; } else { cpi->alt_fb_idx = cpi->lst_fb_idx; cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_ALT_FLAG); } } else { if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id]) { cpi->alt_fb_idx = lc->alt_ref_idx; if (!lc->has_alt_frame) cpi->ref_frame_flags &= (~VP9_ALT_FLAG); } else { // Find a proper alt_fb_idx for layers that don't have alt ref frame if (cpi->svc.spatial_layer_id == 0) { cpi->alt_fb_idx = cpi->lst_fb_idx; } else { LAYER_CONTEXT *lc_lower = &cpi->svc.layer_context[cpi->svc.spatial_layer_id - 1]; if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id - 1] && lc_lower->alt_ref_source != NULL) cpi->alt_fb_idx = lc_lower->alt_ref_idx; else if (cpi->svc.spatial_layer_id >= 2) cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2; else cpi->alt_fb_idx = cpi->lst_fb_idx; } } } get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height, lc->scaling_factor_num, lc->scaling_factor_den, &width, &height); // Workaround for multiple frame contexts. In some frames we can't use prev_mi // since its previous frame could be changed during decoding time. The idea is // we put a empty invisible frame in front of them, then we will not use // prev_mi when encoding these frames. buf = vp9_lookahead_peek(cpi->lookahead, 0); if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 && cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE && lc->rc.frames_to_key != 0 && !(buf != NULL && (buf->flags & VPX_EFLAG_FORCE_KF))) { if ((cpi->svc.number_temporal_layers > 1 && cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1) || (cpi->svc.number_spatial_layers > 1 && cpi->svc.spatial_layer_id == 0)) { struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead, 0); if (buf != NULL) { cpi->svc.empty_frame.ts_start = buf->ts_start; cpi->svc.empty_frame.ts_end = buf->ts_end; cpi->svc.encode_empty_frame_state = ENCODING; cpi->common.show_frame = 0; cpi->ref_frame_flags = 0; cpi->common.frame_type = INTER_FRAME; cpi->lst_fb_idx = cpi->gld_fb_idx = cpi->alt_fb_idx = SMALL_FRAME_FB_IDX; // Gradually make the empty frame smaller to save bits. Make it half of // its previous size because of the scaling factor restriction. cpi->svc.empty_frame_width >>= 1; cpi->svc.empty_frame_width = (cpi->svc.empty_frame_width + 1) & ~1; if (cpi->svc.empty_frame_width < 16) cpi->svc.empty_frame_width = 16; cpi->svc.empty_frame_height >>= 1; cpi->svc.empty_frame_height = (cpi->svc.empty_frame_height + 1) & ~1; if (cpi->svc.empty_frame_height < 16) cpi->svc.empty_frame_height = 16; width = cpi->svc.empty_frame_width; height = cpi->svc.empty_frame_height; } } }