| Index: source/libvpx/vp9/encoder/vp9_encoder.c
|
| ===================================================================
|
| --- source/libvpx/vp9/encoder/vp9_encoder.c (revision 291857)
|
| +++ source/libvpx/vp9/encoder/vp9_encoder.c (working copy)
|
| @@ -24,6 +24,7 @@
|
| #include "vp9/common/vp9_postproc.h"
|
| #endif
|
| #include "vp9/common/vp9_reconinter.h"
|
| +#include "vp9/common/vp9_reconintra.h"
|
| #include "vp9/common/vp9_systemdependent.h"
|
| #include "vp9/common/vp9_tile_common.h"
|
|
|
| @@ -128,11 +129,13 @@
|
| }
|
|
|
| if (cm->frame_type == KEY_FRAME) {
|
| - if (!is_spatial_svc(cpi))
|
| + if (!is_two_pass_svc(cpi))
|
| cpi->refresh_golden_frame = 1;
|
| cpi->refresh_alt_ref_frame = 1;
|
| + vp9_zero(cpi->interp_filter_selected);
|
| } else {
|
| cm->fc = cm->frame_contexts[cm->frame_context_idx];
|
| + vp9_zero(cpi->interp_filter_selected[0]);
|
| }
|
| }
|
|
|
| @@ -140,7 +143,9 @@
|
| static int init_done = 0;
|
|
|
| if (!init_done) {
|
| + vp9_rtcd();
|
| vp9_init_neighbors();
|
| + vp9_init_intra_predictors();
|
| vp9_coef_tree_initialize();
|
| vp9_tokenize_initialize();
|
| vp9_init_me_luts();
|
| @@ -167,6 +172,26 @@
|
| vpx_free(cpi->complexity_map);
|
| cpi->complexity_map = NULL;
|
|
|
| + vpx_free(cpi->nmvcosts[0]);
|
| + vpx_free(cpi->nmvcosts[1]);
|
| + cpi->nmvcosts[0] = NULL;
|
| + cpi->nmvcosts[1] = NULL;
|
| +
|
| + vpx_free(cpi->nmvcosts_hp[0]);
|
| + vpx_free(cpi->nmvcosts_hp[1]);
|
| + cpi->nmvcosts_hp[0] = NULL;
|
| + cpi->nmvcosts_hp[1] = NULL;
|
| +
|
| + vpx_free(cpi->nmvsadcosts[0]);
|
| + vpx_free(cpi->nmvsadcosts[1]);
|
| + cpi->nmvsadcosts[0] = NULL;
|
| + cpi->nmvsadcosts[1] = NULL;
|
| +
|
| + vpx_free(cpi->nmvsadcosts_hp[0]);
|
| + vpx_free(cpi->nmvsadcosts_hp[1]);
|
| + cpi->nmvsadcosts_hp[0] = NULL;
|
| + cpi->nmvsadcosts_hp[1] = NULL;
|
| +
|
| vp9_cyclic_refresh_free(cpi->cyclic_refresh);
|
| cpi->cyclic_refresh = NULL;
|
|
|
| @@ -212,9 +237,16 @@
|
| // intended for use in a re-code loop in vp9_compress_frame where the
|
| // quantizer value is adjusted between loop iterations.
|
| vp9_copy(cc->nmvjointcost, cpi->mb.nmvjointcost);
|
| - vp9_copy(cc->nmvcosts, cpi->mb.nmvcosts);
|
| - vp9_copy(cc->nmvcosts_hp, cpi->mb.nmvcosts_hp);
|
|
|
| + vpx_memcpy(cc->nmvcosts[0], cpi->nmvcosts[0],
|
| + MV_VALS * sizeof(*cpi->nmvcosts[0]));
|
| + vpx_memcpy(cc->nmvcosts[1], cpi->nmvcosts[1],
|
| + MV_VALS * sizeof(*cpi->nmvcosts[1]));
|
| + vpx_memcpy(cc->nmvcosts_hp[0], cpi->nmvcosts_hp[0],
|
| + MV_VALS * sizeof(*cpi->nmvcosts_hp[0]));
|
| + vpx_memcpy(cc->nmvcosts_hp[1], cpi->nmvcosts_hp[1],
|
| + MV_VALS * sizeof(*cpi->nmvcosts_hp[1]));
|
| +
|
| vp9_copy(cc->segment_pred_probs, cm->seg.pred_probs);
|
|
|
| vpx_memcpy(cpi->coding_context.last_frame_seg_map_copy,
|
| @@ -233,9 +265,16 @@
|
| // Restore key state variables to the snapshot state stored in the
|
| // previous call to vp9_save_coding_context.
|
| vp9_copy(cpi->mb.nmvjointcost, cc->nmvjointcost);
|
| - vp9_copy(cpi->mb.nmvcosts, cc->nmvcosts);
|
| - vp9_copy(cpi->mb.nmvcosts_hp, cc->nmvcosts_hp);
|
|
|
| + vpx_memcpy(cpi->nmvcosts[0], cc->nmvcosts[0],
|
| + MV_VALS * sizeof(*cc->nmvcosts[0]));
|
| + vpx_memcpy(cpi->nmvcosts[1], cc->nmvcosts[1],
|
| + MV_VALS * sizeof(*cc->nmvcosts[1]));
|
| + vpx_memcpy(cpi->nmvcosts_hp[0], cc->nmvcosts_hp[0],
|
| + MV_VALS * sizeof(*cc->nmvcosts_hp[0]));
|
| + vpx_memcpy(cpi->nmvcosts_hp[1], cc->nmvcosts_hp[1],
|
| + MV_VALS * sizeof(*cc->nmvcosts_hp[1]));
|
| +
|
| vp9_copy(cm->seg.pred_probs, cc->segment_pred_probs);
|
|
|
| vpx_memcpy(cm->last_frame_seg_map,
|
| @@ -386,27 +425,15 @@
|
| }
|
| }
|
|
|
| -
|
| -static void set_speed_features(VP9_COMP *cpi) {
|
| -#if CONFIG_INTERNAL_STATS
|
| - int i;
|
| - for (i = 0; i < MAX_MODES; ++i)
|
| - cpi->mode_chosen_counts[i] = 0;
|
| -#endif
|
| -
|
| - vp9_set_speed_features(cpi);
|
| -
|
| - // Set rd thresholds based on mode and speed setting
|
| - vp9_set_rd_speed_thresholds(cpi);
|
| - vp9_set_rd_speed_thresholds_sub8x8(cpi);
|
| -}
|
| -
|
| static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
|
| VP9_COMMON *cm = &cpi->common;
|
| const VP9EncoderConfig *oxcf = &cpi->oxcf;
|
|
|
| cpi->lookahead = vp9_lookahead_init(oxcf->width, oxcf->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| oxcf->lag_in_frames);
|
| if (!cpi->lookahead)
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| @@ -415,6 +442,9 @@
|
| if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
|
| oxcf->width, oxcf->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate altref buffer");
|
| @@ -432,6 +462,9 @@
|
| if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
|
| cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate last frame buffer");
|
| @@ -439,6 +472,9 @@
|
| if (vp9_realloc_frame_buffer(&cpi->scaled_source,
|
| cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate scaled source buffer");
|
| @@ -446,6 +482,9 @@
|
| if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
|
| cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate scaled last source buffer");
|
| @@ -474,10 +513,13 @@
|
| vp9_init_context_buffers(cm);
|
| init_macroblockd(cm, xd);
|
|
|
| - if (is_spatial_svc(cpi)) {
|
| + if (is_two_pass_svc(cpi)) {
|
| if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
|
| cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to reallocate alt_ref_buffer");
|
| @@ -526,7 +568,9 @@
|
| cpi->svc.number_temporal_layers = oxcf->ts_number_layers;
|
|
|
| if ((cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ||
|
| - (cpi->svc.number_spatial_layers > 1 && cpi->oxcf.pass == 2)) {
|
| + ((cpi->svc.number_temporal_layers > 1 ||
|
| + cpi->svc.number_spatial_layers > 1) &&
|
| + cpi->oxcf.pass == 2)) {
|
| vp9_init_layer_context(cpi);
|
| }
|
|
|
| @@ -564,9 +608,9 @@
|
| cm->bit_depth = oxcf->bit_depth;
|
|
|
| if (cm->profile <= PROFILE_1)
|
| - assert(cm->bit_depth == BITS_8);
|
| + assert(cm->bit_depth == VPX_BITS_8);
|
| else
|
| - assert(cm->bit_depth > BITS_8);
|
| + assert(cm->bit_depth > VPX_BITS_8);
|
|
|
| cpi->oxcf = *oxcf;
|
|
|
| @@ -618,7 +662,9 @@
|
|
|
| if ((cpi->svc.number_temporal_layers > 1 &&
|
| cpi->oxcf.rc_mode == VPX_CBR) ||
|
| - (cpi->svc.number_spatial_layers > 1 && cpi->oxcf.pass == 2)) {
|
| + ((cpi->svc.number_temporal_layers > 1 ||
|
| + cpi->svc.number_spatial_layers > 1) &&
|
| + cpi->oxcf.pass == 2)) {
|
| vp9_update_layer_context_change_config(cpi,
|
| (int)cpi->oxcf.target_bandwidth);
|
| }
|
| @@ -641,6 +687,9 @@
|
| if (cpi->oxcf.noise_sensitivity > 0) {
|
| vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS);
|
| }
|
| #endif
|
| @@ -707,8 +756,6 @@
|
|
|
| cm->error.setjmp = 1;
|
|
|
| - vp9_rtcd();
|
| -
|
| cpi->use_svc = 0;
|
|
|
| init_config(cpi, oxcf);
|
| @@ -734,6 +781,23 @@
|
| CHECK_MEM_ERROR(cm, cpi->coding_context.last_frame_seg_map_copy,
|
| vpx_calloc(cm->mi_rows * cm->mi_cols, 1));
|
|
|
| + CHECK_MEM_ERROR(cm, cpi->nmvcosts[0],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts[0])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvcosts[1],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts[1])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvcosts_hp[0],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts_hp[0])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvcosts_hp[1],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts_hp[1])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvsadcosts[0],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts[0])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvsadcosts[1],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts[1])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvsadcosts_hp[0],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts_hp[0])));
|
| + CHECK_MEM_ERROR(cm, cpi->nmvsadcosts_hp[1],
|
| + vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts_hp[1])));
|
| +
|
| for (i = 0; i < (sizeof(cpi->mbgraph_stats) /
|
| sizeof(cpi->mbgraph_stats[0])); i++) {
|
| CHECK_MEM_ERROR(cm, cpi->mbgraph_stats[i].mb_stats,
|
| @@ -814,16 +878,16 @@
|
| cpi->first_time_stamp_ever = INT64_MAX;
|
|
|
| cal_nmvjointsadcost(cpi->mb.nmvjointsadcost);
|
| - cpi->mb.nmvcost[0] = &cpi->mb.nmvcosts[0][MV_MAX];
|
| - cpi->mb.nmvcost[1] = &cpi->mb.nmvcosts[1][MV_MAX];
|
| - cpi->mb.nmvsadcost[0] = &cpi->mb.nmvsadcosts[0][MV_MAX];
|
| - cpi->mb.nmvsadcost[1] = &cpi->mb.nmvsadcosts[1][MV_MAX];
|
| + cpi->mb.nmvcost[0] = &cpi->nmvcosts[0][MV_MAX];
|
| + cpi->mb.nmvcost[1] = &cpi->nmvcosts[1][MV_MAX];
|
| + cpi->mb.nmvsadcost[0] = &cpi->nmvsadcosts[0][MV_MAX];
|
| + cpi->mb.nmvsadcost[1] = &cpi->nmvsadcosts[1][MV_MAX];
|
| cal_nmvsadcosts(cpi->mb.nmvsadcost);
|
|
|
| - cpi->mb.nmvcost_hp[0] = &cpi->mb.nmvcosts_hp[0][MV_MAX];
|
| - cpi->mb.nmvcost_hp[1] = &cpi->mb.nmvcosts_hp[1][MV_MAX];
|
| - cpi->mb.nmvsadcost_hp[0] = &cpi->mb.nmvsadcosts_hp[0][MV_MAX];
|
| - cpi->mb.nmvsadcost_hp[1] = &cpi->mb.nmvsadcosts_hp[1][MV_MAX];
|
| + cpi->mb.nmvcost_hp[0] = &cpi->nmvcosts_hp[0][MV_MAX];
|
| + cpi->mb.nmvcost_hp[1] = &cpi->nmvcosts_hp[1][MV_MAX];
|
| + cpi->mb.nmvsadcost_hp[0] = &cpi->nmvsadcosts_hp[0][MV_MAX];
|
| + cpi->mb.nmvsadcost_hp[1] = &cpi->nmvsadcosts_hp[1][MV_MAX];
|
| cal_nmvsadcosts_hp(cpi->mb.nmvsadcost_hp);
|
|
|
| #if CONFIG_VP9_TEMPORAL_DENOISING
|
| @@ -840,8 +904,6 @@
|
| kf_list = fopen("kf_list.stt", "w");
|
| #endif
|
|
|
| - cpi->output_pkt_list = oxcf->output_pkt_list;
|
| -
|
| cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
|
|
|
| if (oxcf->pass == 1) {
|
| @@ -851,7 +913,7 @@
|
| const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
|
|
|
| if (cpi->svc.number_spatial_layers > 1
|
| - && cpi->svc.number_temporal_layers == 1) {
|
| + || cpi->svc.number_temporal_layers > 1) {
|
| FIRSTPASS_STATS *const stats = oxcf->two_pass_stats_in.buf;
|
| FIRSTPASS_STATS *stats_copy[VPX_SS_MAX_LAYERS] = {0};
|
| int i;
|
| @@ -909,7 +971,7 @@
|
| }
|
| }
|
|
|
| - set_speed_features(cpi);
|
| + vp9_set_speed_features(cpi);
|
|
|
| // Allocate memory to store variances for a frame.
|
| CHECK_MEM_ERROR(cm, cpi->source_diff_var,
|
| @@ -1394,40 +1456,6 @@
|
| vp9_extend_frame_borders(dst);
|
| }
|
|
|
| -#define WRITE_RECON_BUFFER 0
|
| -#if WRITE_RECON_BUFFER
|
| -void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
|
| - FILE *yframe;
|
| - int i;
|
| - char filename[255];
|
| -
|
| - snprintf(filename, sizeof(filename), "cx\\y%04d.raw", this_frame);
|
| - yframe = fopen(filename, "wb");
|
| -
|
| - for (i = 0; i < frame->y_height; i++)
|
| - fwrite(frame->y_buffer + i * frame->y_stride,
|
| - frame->y_width, 1, yframe);
|
| -
|
| - fclose(yframe);
|
| - snprintf(filename, sizeof(filename), "cx\\u%04d.raw", this_frame);
|
| - yframe = fopen(filename, "wb");
|
| -
|
| - for (i = 0; i < frame->uv_height; i++)
|
| - fwrite(frame->u_buffer + i * frame->uv_stride,
|
| - frame->uv_width, 1, yframe);
|
| -
|
| - fclose(yframe);
|
| - snprintf(filename, sizeof(filename), "cx\\v%04d.raw", this_frame);
|
| - yframe = fopen(filename, "wb");
|
| -
|
| - for (i = 0; i < frame->uv_height; i++)
|
| - fwrite(frame->v_buffer + i * frame->uv_stride,
|
| - frame->uv_width, 1, yframe);
|
| -
|
| - fclose(yframe);
|
| -}
|
| -#endif
|
| -
|
| // Function to test for conditions that indicate we should loop
|
| // back and recode a frame.
|
| static int recode_loop_test(const VP9_COMP *cpi,
|
| @@ -1493,7 +1521,7 @@
|
| cpi->alt_fb_idx = cpi->gld_fb_idx;
|
| cpi->gld_fb_idx = tmp;
|
|
|
| - if (is_spatial_svc(cpi)) {
|
| + if (is_two_pass_svc(cpi)) {
|
| cpi->svc.layer_context[0].gold_ref_idx = cpi->gld_fb_idx;
|
| cpi->svc.layer_context[0].alt_ref_idx = cpi->alt_fb_idx;
|
| }
|
| @@ -1507,17 +1535,32 @@
|
|
|
| ref_cnt_fb(cm->frame_bufs,
|
| &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
|
| + vpx_memcpy(cpi->interp_filter_selected[ALTREF_FRAME],
|
| + cpi->interp_filter_selected[0],
|
| + sizeof(cpi->interp_filter_selected[0]));
|
| }
|
|
|
| if (cpi->refresh_golden_frame) {
|
| ref_cnt_fb(cm->frame_bufs,
|
| &cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
|
| + if (!cpi->rc.is_src_frame_alt_ref)
|
| + vpx_memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
|
| + cpi->interp_filter_selected[0],
|
| + sizeof(cpi->interp_filter_selected[0]));
|
| + else
|
| + vpx_memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
|
| + cpi->interp_filter_selected[ALTREF_FRAME],
|
| + sizeof(cpi->interp_filter_selected[ALTREF_FRAME]));
|
| }
|
| }
|
|
|
| if (cpi->refresh_last_frame) {
|
| ref_cnt_fb(cm->frame_bufs,
|
| &cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
|
| + if (!cpi->rc.is_src_frame_alt_ref)
|
| + vpx_memcpy(cpi->interp_filter_selected[LAST_FRAME],
|
| + cpi->interp_filter_selected[0],
|
| + sizeof(cpi->interp_filter_selected[0]));
|
| }
|
| #if CONFIG_VP9_TEMPORAL_DENOISING
|
| if (cpi->oxcf.noise_sensitivity > 0) {
|
| @@ -1572,6 +1615,9 @@
|
| vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
|
| cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
|
| scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf);
|
| cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
|
| @@ -1746,7 +1792,6 @@
|
| // to recode.
|
| if (cpi->sf.recode_loop >= ALLOW_RECODE_KFARFGF) {
|
| save_coding_context(cpi);
|
| - cpi->dummy_packing = 1;
|
| if (!cpi->sf.use_nonrd_pick_mode)
|
| vp9_pack_bitstream(cpi, dest, size);
|
|
|
| @@ -1905,8 +1950,7 @@
|
| if (gold_is_last)
|
| flags &= ~VP9_GOLD_FLAG;
|
|
|
| - if (cpi->rc.frames_till_gf_update_due == INT_MAX &&
|
| - !is_spatial_svc(cpi))
|
| + if (cpi->rc.frames_till_gf_update_due == INT_MAX && !is_two_pass_svc(cpi))
|
| flags &= ~VP9_GOLD_FLAG;
|
|
|
| if (alt_is_last)
|
| @@ -1947,18 +1991,16 @@
|
| }
|
| }
|
|
|
| -static void configure_skippable_frame(VP9_COMP *cpi) {
|
| +static int is_skippable_frame(const VP9_COMP *cpi) {
|
| // If the current frame does not have non-zero motion vector detected in the
|
| // first pass, and so do its previous and forward frames, then this frame
|
| // can be skipped for partition check, and the partition size is assigned
|
| // according to the variance
|
| + const SVC *const svc = &cpi->svc;
|
| + const TWO_PASS *const twopass = is_two_pass_svc(cpi) ?
|
| + &svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass;
|
|
|
| - SVC *const svc = &cpi->svc;
|
| - TWO_PASS *const twopass = is_spatial_svc(cpi) ?
|
| - &svc->layer_context[svc->spatial_layer_id].twopass
|
| - : &cpi->twopass;
|
| -
|
| - cpi->skippable_frame = (!frame_is_intra_only(&cpi->common) &&
|
| + return (!frame_is_intra_only(&cpi->common) &&
|
| twopass->stats_in - 2 > twopass->stats_in_start &&
|
| twopass->stats_in < twopass->stats_in_end &&
|
| (twopass->stats_in - 1)->pcnt_inter - (twopass->stats_in - 1)->pcnt_motion
|
| @@ -2008,11 +2050,39 @@
|
| }
|
| }
|
|
|
| +
|
| +int setup_interp_filter_search_mask(VP9_COMP *cpi) {
|
| + INTERP_FILTER ifilter;
|
| + int ref_total[MAX_REF_FRAMES] = {0};
|
| + MV_REFERENCE_FRAME ref;
|
| + int mask = 0;
|
| + if (cpi->common.last_frame_type == KEY_FRAME ||
|
| + cpi->refresh_alt_ref_frame)
|
| + return mask;
|
| + for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref)
|
| + for (ifilter = EIGHTTAP; ifilter <= EIGHTTAP_SHARP; ++ifilter)
|
| + ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
|
| +
|
| + for (ifilter = EIGHTTAP; ifilter <= EIGHTTAP_SHARP; ++ifilter) {
|
| + if ((ref_total[LAST_FRAME] &&
|
| + cpi->interp_filter_selected[LAST_FRAME][ifilter] == 0) &&
|
| + (ref_total[GOLDEN_FRAME] == 0 ||
|
| + cpi->interp_filter_selected[GOLDEN_FRAME][ifilter] * 50
|
| + < ref_total[GOLDEN_FRAME]) &&
|
| + (ref_total[ALTREF_FRAME] == 0 ||
|
| + cpi->interp_filter_selected[ALTREF_FRAME][ifilter] * 50
|
| + < ref_total[ALTREF_FRAME]))
|
| + mask |= 1 << ifilter;
|
| + }
|
| + return mask;
|
| +}
|
| +
|
| static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
| size_t *size,
|
| uint8_t *dest,
|
| unsigned int *frame_flags) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| + const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
| struct segmentation *const seg = &cm->seg;
|
| TX_SIZE t;
|
| int q;
|
| @@ -2046,6 +2116,12 @@
|
|
|
| set_mv_search_params(cpi);
|
|
|
| + if (cpi->oxcf.pass == 2 &&
|
| + cpi->sf.adaptive_interp_filter_search)
|
| + cpi->sf.interp_filter_search_mask =
|
| + setup_interp_filter_search_mask(cpi);
|
| +
|
| +
|
| // Set various flags etc to special state if it is a key frame.
|
| if (frame_is_intra_only(cm)) {
|
| // Reset the loop filter deltas and segmentation map.
|
| @@ -2060,9 +2136,7 @@
|
| // The alternate reference frame cannot be active for a key frame.
|
| cpi->rc.source_alt_ref_active = 0;
|
|
|
| - cm->error_resilient_mode = (cpi->oxcf.error_resilient_mode != 0);
|
| - cm->frame_parallel_decoding_mode =
|
| - (cpi->oxcf.frame_parallel_decoding_mode != 0);
|
| + cm->error_resilient_mode = oxcf->error_resilient_mode;
|
|
|
| // By default, encoder assumes decoder can use prev_mi.
|
| if (cm->error_resilient_mode) {
|
| @@ -2070,29 +2144,59 @@
|
| cm->reset_frame_context = 0;
|
| cm->refresh_frame_context = 0;
|
| } else if (cm->intra_only) {
|
| + cm->frame_parallel_decoding_mode = oxcf->frame_parallel_decoding_mode;
|
| // Only reset the current context.
|
| cm->reset_frame_context = 2;
|
| }
|
| }
|
| + if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0) {
|
| + cm->frame_context_idx =
|
| + cpi->svc.spatial_layer_id * cpi->svc.number_temporal_layers +
|
| + cpi->svc.temporal_layer_id;
|
|
|
| + // The probs will be updated based on the frame type of its previous
|
| + // frame if frame_parallel_decoding_mode is 0. The type may vary for
|
| + // the frame after a key frame in base layer since we may drop enhancement
|
| + // layers. So set frame_parallel_decoding_mode to 1 in this case.
|
| + if (cpi->svc.number_temporal_layers == 1) {
|
| + if (cpi->svc.spatial_layer_id == 0 &&
|
| + cpi->svc.layer_context[0].last_frame_type == KEY_FRAME)
|
| + cm->frame_parallel_decoding_mode = 1;
|
| + else
|
| + cm->frame_parallel_decoding_mode = 0;
|
| + } else if (cpi->svc.spatial_layer_id == 0) {
|
| + // Find the 2nd frame in temporal base layer and 1st frame in temporal
|
| + // enhancement layers from the key frame.
|
| + int i;
|
| + for (i = 0; i < cpi->svc.number_temporal_layers; ++i) {
|
| + if (cpi->svc.layer_context[0].frames_from_key_frame == 1 << i) {
|
| + cm->frame_parallel_decoding_mode = 1;
|
| + break;
|
| + }
|
| + }
|
| + if (i == cpi->svc.number_temporal_layers)
|
| + cm->frame_parallel_decoding_mode = 0;
|
| + }
|
| + }
|
| +
|
| // Configure experimental use of segmentation for enhanced coding of
|
| // static regions if indicated.
|
| // Only allowed in second pass of two pass (as requires lagged coding)
|
| // and if the relevant speed feature flag is set.
|
| - if (cpi->oxcf.pass == 2 && cpi->sf.static_segmentation)
|
| + if (oxcf->pass == 2 && cpi->sf.static_segmentation)
|
| configure_static_seg_features(cpi);
|
|
|
| // Check if the current frame is skippable for the partition search in the
|
| // second pass according to the first pass stats
|
| - if (cpi->oxcf.pass == 2 &&
|
| - (!cpi->use_svc || is_spatial_svc(cpi))) {
|
| - configure_skippable_frame(cpi);
|
| + if (oxcf->pass == 2 &&
|
| + (!cpi->use_svc || is_two_pass_svc(cpi))) {
|
| + cpi->skippable_frame = is_skippable_frame(cpi);
|
| }
|
|
|
| // For 1 pass CBR, check if we are dropping this frame.
|
| // Never drop on key frame.
|
| - if (cpi->oxcf.pass == 0 &&
|
| - cpi->oxcf.rc_mode == VPX_CBR &&
|
| + if (oxcf->pass == 0 &&
|
| + oxcf->rc_mode == VPX_CBR &&
|
| cm->frame_type != KEY_FRAME) {
|
| if (vp9_rc_drop_frame(cpi)) {
|
| vp9_rc_postencode_update_drop_frame(cpi);
|
| @@ -2104,9 +2208,9 @@
|
| vp9_clear_system_state();
|
|
|
| #if CONFIG_VP9_POSTPROC
|
| - if (cpi->oxcf.noise_sensitivity > 0) {
|
| + if (oxcf->noise_sensitivity > 0) {
|
| int l = 0;
|
| - switch (cpi->oxcf.noise_sensitivity) {
|
| + switch (oxcf->noise_sensitivity) {
|
| case 1:
|
| l = 20;
|
| break;
|
| @@ -2128,8 +2232,17 @@
|
| }
|
| #endif
|
|
|
| - set_speed_features(cpi);
|
| +#if CONFIG_INTERNAL_STATS
|
| + int i;
|
| + for (i = 0; i < MAX_MODES; ++i)
|
| + cpi->mode_chosen_counts[i] = 0;
|
| +#endif
|
|
|
| + vp9_set_speed_features(cpi);
|
| +
|
| + vp9_set_rd_speed_thresholds(cpi);
|
| + vp9_set_rd_speed_thresholds_sub8x8(cpi);
|
| +
|
| // Decide q and q bounds.
|
| q = vp9_rc_pick_q_and_bounds(cpi, &bottom_index, &top_index);
|
|
|
| @@ -2147,7 +2260,7 @@
|
|
|
| #if CONFIG_VP9_TEMPORAL_DENOISING
|
| #ifdef OUTPUT_YUV_DENOISED
|
| - if (cpi->oxcf.noise_sensitivity > 0) {
|
| + if (oxcf->noise_sensitivity > 0) {
|
| vp9_write_yuv_frame_420(&cpi->denoiser.running_avg_y[INTRA_FRAME],
|
| yuv_denoised_file);
|
| }
|
| @@ -2168,29 +2281,10 @@
|
|
|
| cm->frame_to_show = get_frame_new_buffer(cm);
|
|
|
| -#if WRITE_RECON_BUFFER
|
| - if (cm->show_frame)
|
| - write_cx_frame_to_file(cm->frame_to_show,
|
| - cm->current_video_frame);
|
| - else
|
| - write_cx_frame_to_file(cm->frame_to_show,
|
| - cm->current_video_frame + 1000);
|
| -#endif
|
| -
|
| // Pick the loop filter level for the frame.
|
| loopfilter_frame(cpi, cm);
|
|
|
| -#if WRITE_RECON_BUFFER
|
| - if (cm->show_frame)
|
| - write_cx_frame_to_file(cm->frame_to_show,
|
| - cm->current_video_frame + 2000);
|
| - else
|
| - write_cx_frame_to_file(cm->frame_to_show,
|
| - cm->current_video_frame + 3000);
|
| -#endif
|
| -
|
| // build the bitstream
|
| - cpi->dummy_packing = 0;
|
| vp9_pack_bitstream(cpi, dest, size);
|
|
|
| if (cm->seg.update_map)
|
| @@ -2249,8 +2343,12 @@
|
| cm->last_height = cm->height;
|
|
|
| // reset to normal state now that we are done.
|
| - if (!cm->show_existing_frame)
|
| - cm->last_show_frame = cm->show_frame;
|
| + if (!cm->show_existing_frame) {
|
| + if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0)
|
| + cm->last_show_frame = 0;
|
| + else
|
| + cm->last_show_frame = cm->show_frame;
|
| + }
|
|
|
| if (cm->show_frame) {
|
| vp9_swap_mi_and_prev_mi(cm);
|
| @@ -2259,8 +2357,12 @@
|
| // update not a real frame
|
| ++cm->current_video_frame;
|
| if (cpi->use_svc)
|
| - vp9_inc_frame_in_layer(&cpi->svc);
|
| + vp9_inc_frame_in_layer(cpi);
|
| }
|
| +
|
| + if (is_two_pass_svc(cpi))
|
| + cpi->svc.layer_context[cpi->svc.spatial_layer_id].last_frame_type =
|
| + cm->frame_type;
|
| }
|
|
|
| static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
|
| @@ -2333,7 +2435,7 @@
|
| vpx_usec_timer_start(&timer);
|
|
|
| #if CONFIG_SPATIAL_SVC
|
| - if (is_spatial_svc(cpi))
|
| + if (is_two_pass_svc(cpi))
|
| res = vp9_svc_lookahead_push(cpi, cpi->lookahead, sd, time_stamp, end_time,
|
| frame_flags);
|
| else
|
| @@ -2375,8 +2477,8 @@
|
| cm->seg.update_data;
|
| }
|
|
|
| -void adjust_frame_rate(VP9_COMP *cpi) {
|
| - const struct lookahead_entry *const source = cpi->source;
|
| +void adjust_frame_rate(VP9_COMP *cpi,
|
| + const struct lookahead_entry *source) {
|
| int64_t this_duration;
|
| int step = 0;
|
|
|
| @@ -2432,7 +2534,8 @@
|
| return arf_src_index;
|
| }
|
|
|
| -static void check_src_altref(VP9_COMP *cpi) {
|
| +static void check_src_altref(VP9_COMP *cpi,
|
| + const struct lookahead_entry *source) {
|
| RATE_CONTROL *const rc = &cpi->rc;
|
|
|
| if (cpi->oxcf.pass == 2) {
|
| @@ -2441,7 +2544,7 @@
|
| (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
|
| } else {
|
| rc->is_src_frame_alt_ref = cpi->alt_ref_source &&
|
| - (cpi->source == cpi->alt_ref_source);
|
| + (source == cpi->alt_ref_source);
|
| }
|
|
|
| if (rc->is_src_frame_alt_ref) {
|
| @@ -2463,10 +2566,12 @@
|
| RATE_CONTROL *const rc = &cpi->rc;
|
| struct vpx_usec_timer cmptimer;
|
| YV12_BUFFER_CONFIG *force_src_buffer = NULL;
|
| + struct lookahead_entry *last_source = NULL;
|
| + struct lookahead_entry *source = NULL;
|
| MV_REFERENCE_FRAME ref_frame;
|
| int arf_src_index;
|
|
|
| - if (is_spatial_svc(cpi) && oxcf->pass == 2) {
|
| + if (is_two_pass_svc(cpi) && oxcf->pass == 2) {
|
| #if CONFIG_SPATIAL_SVC
|
| vp9_svc_lookahead_peek(cpi, cpi->lookahead, 0, 1);
|
| #endif
|
| @@ -2475,9 +2580,6 @@
|
|
|
| vpx_usec_timer_start(&cmptimer);
|
|
|
| - cpi->source = NULL;
|
| - cpi->last_source = NULL;
|
| -
|
| vp9_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
|
|
|
| // Normal defaults
|
| @@ -2493,17 +2595,16 @@
|
| assert(arf_src_index <= rc->frames_to_key);
|
|
|
| #if CONFIG_SPATIAL_SVC
|
| - if (is_spatial_svc(cpi))
|
| - cpi->source = vp9_svc_lookahead_peek(cpi, cpi->lookahead,
|
| - arf_src_index, 0);
|
| + if (is_two_pass_svc(cpi))
|
| + source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, arf_src_index, 0);
|
| else
|
| #endif
|
| - cpi->source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
|
| - if (cpi->source != NULL) {
|
| - cpi->alt_ref_source = cpi->source;
|
| + source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
|
| + if (source != NULL) {
|
| + cpi->alt_ref_source = source;
|
|
|
| #if CONFIG_SPATIAL_SVC
|
| - if (is_spatial_svc(cpi) && cpi->svc.spatial_layer_id > 0) {
|
| + if (is_two_pass_svc(cpi) && cpi->svc.spatial_layer_id > 0) {
|
| int i;
|
| // Reference a hidden frame from a lower layer
|
| for (i = cpi->svc.spatial_layer_id - 1; i >= 0; --i) {
|
| @@ -2534,46 +2635,44 @@
|
| }
|
| }
|
|
|
| - if (!cpi->source) {
|
| + if (!source) {
|
| // Get last frame source.
|
| if (cm->current_video_frame > 0) {
|
| #if CONFIG_SPATIAL_SVC
|
| - if (is_spatial_svc(cpi))
|
| - cpi->last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
|
| + if (is_two_pass_svc(cpi))
|
| + last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
|
| else
|
| #endif
|
| - cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1);
|
| - if (cpi->last_source == NULL)
|
| + last_source = vp9_lookahead_peek(cpi->lookahead, -1);
|
| + if (last_source == NULL)
|
| return -1;
|
| }
|
|
|
| // Read in the source frame.
|
| #if CONFIG_SPATIAL_SVC
|
| - if (is_spatial_svc(cpi))
|
| - cpi->source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
|
| + if (is_two_pass_svc(cpi))
|
| + source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
|
| else
|
| #endif
|
| - cpi->source = vp9_lookahead_pop(cpi->lookahead, flush);
|
| - if (cpi->source != NULL) {
|
| + source = vp9_lookahead_pop(cpi->lookahead, flush);
|
| + if (source != NULL) {
|
| cm->show_frame = 1;
|
| cm->intra_only = 0;
|
|
|
| // Check to see if the frame should be encoded as an arf overlay.
|
| - check_src_altref(cpi);
|
| + check_src_altref(cpi, source);
|
| }
|
| }
|
|
|
| - if (cpi->source) {
|
| + if (source) {
|
| cpi->un_scaled_source = cpi->Source = force_src_buffer ? force_src_buffer
|
| - : &cpi->source->img;
|
| + : &source->img;
|
|
|
| - cpi->unscaled_last_source = cpi->last_source != NULL ?
|
| - &cpi->last_source->img : NULL;
|
| + cpi->unscaled_last_source = last_source != NULL ? &last_source->img : NULL;
|
|
|
| - *time_stamp = cpi->source->ts_start;
|
| - *time_end = cpi->source->ts_end;
|
| - *frame_flags =
|
| - (cpi->source->flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
|
| + *time_stamp = source->ts_start;
|
| + *time_end = source->ts_end;
|
| + *frame_flags = (source->flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
|
|
|
| } else {
|
| *size = 0;
|
| @@ -2584,9 +2683,9 @@
|
| return -1;
|
| }
|
|
|
| - if (cpi->source->ts_start < cpi->first_time_stamp_ever) {
|
| - cpi->first_time_stamp_ever = cpi->source->ts_start;
|
| - cpi->last_end_time_stamp_seen = cpi->source->ts_start;
|
| + if (source->ts_start < cpi->first_time_stamp_ever) {
|
| + cpi->first_time_stamp_ever = source->ts_start;
|
| + cpi->last_end_time_stamp_seen = source->ts_start;
|
| }
|
|
|
| // Clear down mmx registers
|
| @@ -2594,7 +2693,7 @@
|
|
|
| // adjust frame rates based on timestamps given
|
| if (cm->show_frame) {
|
| - adjust_frame_rate(cpi);
|
| + adjust_frame_rate(cpi, source);
|
| }
|
|
|
| if (cpi->svc.number_temporal_layers > 1 &&
|
| @@ -2636,6 +2735,9 @@
|
| vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
|
| cm->width, cm->height,
|
| cm->subsampling_x, cm->subsampling_y,
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + cm->use_highbitdepth,
|
| +#endif
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
|
|
|
| alloc_util_frame_buffers(cpi);
|
| @@ -2662,13 +2764,13 @@
|
| }
|
|
|
| if (oxcf->pass == 1 &&
|
| - (!cpi->use_svc || is_spatial_svc(cpi))) {
|
| + (!cpi->use_svc || is_two_pass_svc(cpi))) {
|
| const int lossless = is_lossless_requested(oxcf);
|
| cpi->mb.fwd_txm4x4 = lossless ? vp9_fwht4x4 : vp9_fdct4x4;
|
| cpi->mb.itxm_add = lossless ? vp9_iwht4x4_add : vp9_idct4x4_add;
|
| - vp9_first_pass(cpi);
|
| + vp9_first_pass(cpi, source);
|
| } else if (oxcf->pass == 2 &&
|
| - (!cpi->use_svc || is_spatial_svc(cpi))) {
|
| + (!cpi->use_svc || is_two_pass_svc(cpi))) {
|
| Pass2Encode(cpi, size, dest, frame_flags);
|
| } else if (cpi->use_svc) {
|
| SvcEncode(cpi, size, dest, frame_flags);
|
| @@ -2691,8 +2793,10 @@
|
|
|
| // Save layer specific state.
|
| if ((cpi->svc.number_temporal_layers > 1 &&
|
| - oxcf->rc_mode == VPX_CBR) ||
|
| - (cpi->svc.number_spatial_layers > 1 && oxcf->pass == 2)) {
|
| + oxcf->rc_mode == VPX_CBR) ||
|
| + ((cpi->svc.number_temporal_layers > 1 ||
|
| + cpi->svc.number_spatial_layers > 1) &&
|
| + oxcf->pass == 2)) {
|
| vp9_save_layer_context(cpi);
|
| }
|
|
|
| @@ -2744,12 +2848,12 @@
|
| cpi->totalp_sq_error += psnr2.sse[0];
|
| cpi->totalp_samples += psnr2.samples[0];
|
|
|
| - frame_ssim2 = vp9_calc_ssim(orig, recon, 1, &weight);
|
| + frame_ssim2 = vp9_calc_ssim(orig, recon, &weight);
|
|
|
| cpi->summed_quality += frame_ssim2 * weight;
|
| cpi->summed_weights += weight;
|
|
|
| - frame_ssim2 = vp9_calc_ssim(orig, &cm->post_proc_buffer, 1, &weight);
|
| + frame_ssim2 = vp9_calc_ssim(orig, &cm->post_proc_buffer, &weight);
|
|
|
| cpi->summedp_quality += frame_ssim2 * weight;
|
| cpi->summedp_weights += weight;
|
| @@ -2765,6 +2869,7 @@
|
| }
|
| }
|
|
|
| +
|
| if (cpi->b_calculate_ssimg) {
|
| double y, u, v, frame_all;
|
| frame_all = vp9_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
|
|
|