| Index: source/libvpx/vp9/encoder/vp9_encoder.c
|
| ===================================================================
|
| --- source/libvpx/vp9/encoder/vp9_encoder.c (revision 281795)
|
| +++ source/libvpx/vp9/encoder/vp9_encoder.c (working copy)
|
| @@ -39,7 +39,7 @@
|
| #include "vp9/encoder/vp9_encoder.h"
|
| #include "vp9/encoder/vp9_picklpf.h"
|
| #include "vp9/encoder/vp9_ratectrl.h"
|
| -#include "vp9/encoder/vp9_rdopt.h"
|
| +#include "vp9/encoder/vp9_rd.h"
|
| #include "vp9/encoder/vp9_segmentation.h"
|
| #include "vp9/encoder/vp9_speed_features.h"
|
| #if CONFIG_INTERNAL_STATS
|
| @@ -65,7 +65,7 @@
|
| // #define OUTPUT_YUV_REC
|
|
|
| #ifdef OUTPUT_YUV_DENOISED
|
| -FILE *yuv_denoised_file;
|
| +FILE *yuv_denoised_file = NULL;
|
| #endif
|
| #ifdef OUTPUT_YUV_SRC
|
| FILE *yuv_file;
|
| @@ -106,7 +106,7 @@
|
| }
|
| }
|
|
|
| -static void set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
|
| +void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
|
| MACROBLOCK *const mb = &cpi->mb;
|
| cpi->common.allow_high_precision_mv = allow_high_precision_mv;
|
| if (cpi->common.allow_high_precision_mv) {
|
| @@ -145,8 +145,6 @@
|
|
|
| if (!init_done) {
|
| vp9_init_neighbors();
|
| - vp9_init_quant_tables();
|
| -
|
| vp9_coef_tree_initialize();
|
| vp9_tokenize_initialize();
|
| vp9_init_me_luts();
|
| @@ -176,10 +174,8 @@
|
| vp9_cyclic_refresh_free(cpi->cyclic_refresh);
|
| cpi->cyclic_refresh = NULL;
|
|
|
| - vpx_free(cpi->active_map);
|
| - cpi->active_map = NULL;
|
| -
|
| vp9_free_frame_buffers(cm);
|
| + vp9_free_context_buffers(cm);
|
|
|
| vp9_free_frame_buffer(&cpi->last_frame_uf);
|
| vp9_free_frame_buffer(&cpi->scaled_source);
|
| @@ -198,6 +194,18 @@
|
| lc->rc_twopass_stats_in.buf = NULL;
|
| lc->rc_twopass_stats_in.sz = 0;
|
| }
|
| +
|
| + if (cpi->source_diff_var != NULL) {
|
| + vpx_free(cpi->source_diff_var);
|
| + cpi->source_diff_var = NULL;
|
| + }
|
| +
|
| +#if CONFIG_FP_MB_STATS
|
| + if (cpi->use_fp_mb_stats) {
|
| + vpx_free(cpi->twopass.this_frame_mb_stats.mb_stats);
|
| + cpi->twopass.this_frame_mb_stats.mb_stats = NULL;
|
| + }
|
| +#endif
|
| }
|
|
|
| static void save_coding_context(VP9_COMP *cpi) {
|
| @@ -417,39 +425,46 @@
|
| "Failed to allocate altref buffer");
|
| }
|
|
|
| -void vp9_alloc_compressor_data(VP9_COMP *cpi) {
|
| - VP9_COMMON *cm = &cpi->common;
|
| -
|
| +static void alloc_ref_frame_buffers(VP9_COMP *cpi) {
|
| + VP9_COMMON *const cm = &cpi->common;
|
| if (vp9_alloc_frame_buffers(cm, cm->width, cm->height))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate frame buffers");
|
| +}
|
|
|
| - if (vp9_alloc_frame_buffer(&cpi->last_frame_uf,
|
| - cm->width, cm->height,
|
| - cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS))
|
| +static void alloc_util_frame_buffers(VP9_COMP *cpi) {
|
| + VP9_COMMON *const cm = &cpi->common;
|
| + if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
|
| + cm->width, cm->height,
|
| + cm->subsampling_x, cm->subsampling_y,
|
| + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate last frame buffer");
|
|
|
| - if (vp9_alloc_frame_buffer(&cpi->scaled_source,
|
| - cm->width, cm->height,
|
| - cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS))
|
| + if (vp9_realloc_frame_buffer(&cpi->scaled_source,
|
| + cm->width, cm->height,
|
| + cm->subsampling_x, cm->subsampling_y,
|
| + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate scaled source buffer");
|
|
|
| - if (vp9_alloc_frame_buffer(&cpi->scaled_last_source,
|
| - cm->width, cm->height,
|
| - cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS))
|
| + if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
|
| + cm->width, cm->height,
|
| + cm->subsampling_x, cm->subsampling_y,
|
| + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| "Failed to allocate scaled last source buffer");
|
| +}
|
|
|
| +void vp9_alloc_compressor_data(VP9_COMP *cpi) {
|
| + VP9_COMMON *cm = &cpi->common;
|
| +
|
| + vp9_alloc_context_buffers(cm, cm->width, cm->height);
|
| +
|
| vpx_free(cpi->tok);
|
|
|
| {
|
| unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols);
|
| -
|
| CHECK_MEM_ERROR(cm, cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
|
| }
|
|
|
| @@ -459,41 +474,7 @@
|
| static void update_frame_size(VP9_COMP *cpi) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
| -
|
| vp9_update_frame_size(cm);
|
| -
|
| - // Update size of buffers local to this frame
|
| - if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
|
| - cm->width, cm->height,
|
| - cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| - vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| - "Failed to reallocate last frame buffer");
|
| -
|
| - if (vp9_realloc_frame_buffer(&cpi->scaled_source,
|
| - cm->width, cm->height,
|
| - cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| - vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| - "Failed to reallocate scaled source buffer");
|
| -
|
| - if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
|
| - cm->width, cm->height,
|
| - cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
| - vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
| - "Failed to reallocate scaled last source buffer");
|
| -
|
| - {
|
| - int y_stride = cpi->scaled_source.y_stride;
|
| -
|
| - if (cpi->sf.mv.search_method == NSTEP) {
|
| - vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride);
|
| - } else if (cpi->sf.mv.search_method == DIAMOND) {
|
| - vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride);
|
| - }
|
| - }
|
| -
|
| init_macroblockd(cm, xd);
|
| }
|
|
|
| @@ -521,6 +502,12 @@
|
| cm->log2_tile_rows = cpi->oxcf.tile_rows;
|
| }
|
|
|
| +static void init_buffer_indices(VP9_COMP *cpi) {
|
| + cpi->lst_fb_idx = 0;
|
| + cpi->gld_fb_idx = 1;
|
| + cpi->alt_fb_idx = 2;
|
| +}
|
| +
|
| static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
|
| VP9_COMMON *const cm = &cpi->common;
|
|
|
| @@ -531,8 +518,6 @@
|
|
|
| cm->width = oxcf->width;
|
| cm->height = oxcf->height;
|
| - cm->subsampling_x = 0;
|
| - cm->subsampling_y = 0;
|
| vp9_alloc_compressor_data(cpi);
|
|
|
| // Spatial scalability.
|
| @@ -551,10 +536,9 @@
|
| vp9_change_config(cpi, oxcf);
|
|
|
| cpi->static_mb_pct = 0;
|
| + cpi->ref_frame_flags = 0;
|
|
|
| - cpi->lst_fb_idx = 0;
|
| - cpi->gld_fb_idx = 1;
|
| - cpi->alt_fb_idx = 2;
|
| + init_buffer_indices(cpi);
|
|
|
| set_tile_limits(cpi);
|
| }
|
| @@ -593,7 +577,6 @@
|
| cpi->pass = get_pass(cpi->oxcf.mode);
|
|
|
| rc->baseline_gf_interval = DEFAULT_GF_INTERVAL;
|
| - cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
|
|
|
| cpi->refresh_golden_frame = 0;
|
| cpi->refresh_last_frame = 1;
|
| @@ -601,7 +584,7 @@
|
| cm->reset_frame_context = 0;
|
|
|
| vp9_reset_segment_features(&cm->seg);
|
| - set_high_precision_mv(cpi, 0);
|
| + vp9_set_high_precision_mv(cpi, 0);
|
|
|
| {
|
| int i;
|
| @@ -666,11 +649,7 @@
|
| (int)cpi->oxcf.target_bandwidth);
|
| }
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| - vp9_zero(cpi->alt_ref_source);
|
| -#else
|
| cpi->alt_ref_source = NULL;
|
| -#endif
|
| rc->is_src_frame_alt_ref = 0;
|
|
|
| #if 0
|
| @@ -685,14 +664,11 @@
|
| cpi->ext_refresh_frame_context_pending = 0;
|
|
|
| #if CONFIG_DENOISING
|
| - vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
|
| - // TODO(tkopp) An unrelated bug causes
|
| - // cm->subsampling_{x,y} to be uninitialized at this point
|
| - // in execution. For now we assume YUV-420, which is x/y
|
| - // subsampling of 1.
|
| - 1, 1,
|
| - // cm->subsampling_x, cm->subsampling_y,
|
| - VP9_ENC_BORDER_IN_PIXELS);
|
| + if (cpi->oxcf.noise_sensitivity > 0) {
|
| + vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
|
| + cm->subsampling_x, cm->subsampling_y,
|
| + VP9_ENC_BORDER_IN_PIXELS);
|
| + }
|
| #endif
|
| }
|
|
|
| @@ -773,6 +749,8 @@
|
| cpi->alt_is_last = 0;
|
| cpi->gold_is_alt = 0;
|
|
|
| + cpi->skippable_frame = 0;
|
| +
|
| // Create the encoder segmentation map and set all entries to 0
|
| CHECK_MEM_ERROR(cm, cpi->segmentation_map,
|
| vpx_calloc(cm->mi_rows * cm->mi_cols, 1));
|
| @@ -790,10 +768,6 @@
|
| 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->active_map, vpx_calloc(cm->MBs, 1));
|
| - vpx_memset(cpi->active_map, 1, cm->MBs);
|
| - cpi->active_map_enabled = 0;
|
| -
|
| for (i = 0; i < (sizeof(cpi->mbgraph_stats) /
|
| sizeof(cpi->mbgraph_stats[0])); i++) {
|
| CHECK_MEM_ERROR(cm, cpi->mbgraph_stats[i].mb_stats,
|
| @@ -801,20 +775,37 @@
|
| sizeof(*cpi->mbgraph_stats[i].mb_stats), 1));
|
| }
|
|
|
| +#if CONFIG_FP_MB_STATS
|
| + cpi->use_fp_mb_stats = 0;
|
| + if (cpi->use_fp_mb_stats) {
|
| + // a place holder for the mb stats obtained from the first pass
|
| + CHECK_MEM_ERROR(cm, cpi->twopass.this_frame_mb_stats.mb_stats,
|
| + vpx_calloc(cm->MBs * sizeof(FIRSTPASS_MB_STATS), 1));
|
| + } else {
|
| + cpi->twopass.this_frame_mb_stats.mb_stats = NULL;
|
| + }
|
| +#endif
|
| +
|
| cpi->refresh_alt_ref_frame = 0;
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| - // Turn multiple ARF usage on/off. This is a quick hack for the initial test
|
| - // version. It should eventually be set via the codec API.
|
| - cpi->multi_arf_enabled = 1;
|
| -
|
| - if (cpi->multi_arf_enabled) {
|
| - cpi->sequence_number = 0;
|
| - cpi->frame_coding_order_period = 0;
|
| - vp9_zero(cpi->frame_coding_order);
|
| - vp9_zero(cpi->arf_buffer_idx);
|
| + // Note that at the moment multi_arf will not work with svc.
|
| + // For the current check in all the execution paths are defaulted to 0
|
| + // pending further tuning and testing. The code is left in place here
|
| + // as a place holder in regard to the required paths.
|
| + cpi->multi_arf_last_grp_enabled = 0;
|
| + if (cpi->pass == 2) {
|
| + if (cpi->use_svc) {
|
| + cpi->multi_arf_allowed = 0;
|
| + cpi->multi_arf_enabled = 0;
|
| + } else {
|
| + // Disable by default for now.
|
| + cpi->multi_arf_allowed = 0;
|
| + cpi->multi_arf_enabled = 0;
|
| + }
|
| + } else {
|
| + cpi->multi_arf_allowed = 0;
|
| + cpi->multi_arf_enabled = 0;
|
| }
|
| -#endif
|
|
|
| cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
|
| #if CONFIG_INTERNAL_STATS
|
| @@ -869,9 +860,13 @@
|
| cpi->mb.nmvsadcost_hp[1] = &cpi->mb.nmvsadcosts_hp[1][MV_MAX];
|
| cal_nmvsadcosts_hp(cpi->mb.nmvsadcost_hp);
|
|
|
| +#if CONFIG_DENOISING
|
| #ifdef OUTPUT_YUV_DENOISED
|
| - yuv_denoised_file = fopen("denoised.yuv", "ab");
|
| + if (cpi->oxcf.noise_sensitivity > 0) {
|
| + yuv_denoised_file = fopen("denoised.yuv", "ab");
|
| + }
|
| #endif
|
| +#endif
|
| #ifdef OUTPUT_YUV_SRC
|
| yuv_file = fopen("bd.yuv", "ab");
|
| #endif
|
| @@ -942,6 +937,12 @@
|
|
|
| set_speed_features(cpi);
|
|
|
| + // Allocate memory to store variances for a frame.
|
| + CHECK_MEM_ERROR(cm, cpi->source_diff_var,
|
| + vpx_calloc(cm->MBs, sizeof(diff)));
|
| + cpi->source_var_thresh = 0;
|
| + cpi->frames_till_next_var_check = 0;
|
| +
|
| // Default rd threshold factors for mode selection
|
| for (i = 0; i < BLOCK_SIZES; ++i) {
|
| for (j = 0; j < MAX_MODES; ++j)
|
| @@ -1103,7 +1104,9 @@
|
| }
|
|
|
| #if CONFIG_DENOISING
|
| - vp9_denoiser_free(&(cpi->denoiser));
|
| + if (cpi->oxcf.noise_sensitivity > 0) {
|
| + vp9_denoiser_free(&(cpi->denoiser));
|
| + }
|
| #endif
|
|
|
| dealloc_compressor_data(cpi);
|
| @@ -1117,9 +1120,13 @@
|
| vp9_remove_common(&cpi->common);
|
| vpx_free(cpi);
|
|
|
| +#if CONFIG_DENOISING
|
| #ifdef OUTPUT_YUV_DENOISED
|
| - fclose(yuv_denoised_file);
|
| + if (cpi->oxcf.noise_sensitivity > 0) {
|
| + fclose(yuv_denoised_file);
|
| + }
|
| #endif
|
| +#endif
|
| #ifdef OUTPUT_YUV_SRC
|
| fclose(yuv_file);
|
| #endif
|
| @@ -1301,7 +1308,7 @@
|
| }
|
|
|
|
|
| -#if defined(OUTPUT_YUV_SRC) || defined(OUTPUT_YUV_DENOISED)
|
| +#if defined(OUTPUT_YUV_SRC)
|
| void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s, FILE *f) {
|
| uint8_t *src = s->y_buffer;
|
| int h = s->y_height;
|
| @@ -1329,6 +1336,40 @@
|
| }
|
| #endif
|
|
|
| +#if CONFIG_DENOISING
|
| +#if defined(OUTPUT_YUV_DENOISED)
|
| +// The denoiser buffer is allocated as a YUV 440 buffer. This function writes it
|
| +// as YUV 420. We simply use the top-left pixels of the UV buffers, since we do
|
| +// not denoise the UV channels at this time. If ever we implement UV channel
|
| +// denoising we will have to modify this.
|
| +void vp9_write_yuv_frame_420(YV12_BUFFER_CONFIG *s, FILE *f) {
|
| + uint8_t *src = s->y_buffer;
|
| + int h = s->y_height;
|
| +
|
| + do {
|
| + fwrite(src, s->y_width, 1, f);
|
| + src += s->y_stride;
|
| + } while (--h);
|
| +
|
| + src = s->u_buffer;
|
| + h = s->uv_height / 2;
|
| +
|
| + do {
|
| + fwrite(src, s->uv_width / 2, 1, f);
|
| + src += s->uv_stride + s->uv_width / 2;
|
| + } while (--h);
|
| +
|
| + src = s->v_buffer;
|
| + h = s->uv_height / 2;
|
| +
|
| + do {
|
| + fwrite(src, s->uv_width / 2, 1, f);
|
| + src += s->uv_stride + s->uv_width / 2;
|
| + } while (--h);
|
| +}
|
| +#endif
|
| +#endif
|
| +
|
| #ifdef OUTPUT_YUV_REC
|
| void vp9_write_yuv_rec_frame(VP9_COMMON *cm) {
|
| YV12_BUFFER_CONFIG *s = cm->frame_to_show;
|
| @@ -1396,9 +1437,7 @@
|
| vp9_resize_plane(srcs[i], src_heights[i], src_widths[i], src_strides[i],
|
| dsts[i], dst_heights[i], dst_widths[i], dst_strides[i]);
|
|
|
| - // TODO(hkuang): Call C version explicitly
|
| - // as neon version only expand border size 32.
|
| - vp8_yv12_extend_frame_borders_c(dst);
|
| + vp9_extend_frame_borders(dst);
|
| }
|
|
|
| static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
|
| @@ -1438,9 +1477,7 @@
|
| }
|
| }
|
|
|
| - // TODO(hkuang): Call C version explicitly
|
| - // as neon version only expand border size 32.
|
| - vp8_yv12_extend_frame_borders_c(dst);
|
| + vp9_extend_frame_borders(dst);
|
| }
|
|
|
| #define WRITE_RECON_BUFFER 0
|
| @@ -1524,14 +1561,8 @@
|
| &cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
|
| ref_cnt_fb(cm->frame_bufs,
|
| &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
|
| - }
|
| -#if CONFIG_MULTIPLE_ARF
|
| - else if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
|
| - !cpi->refresh_alt_ref_frame) {
|
| -#else
|
| - else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame &&
|
| - !cpi->use_svc) {
|
| -#endif
|
| + } else if (!cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
|
| + cpi->rc.is_src_frame_alt_ref && !cpi->use_svc) {
|
| /* Preserve the previously existing golden frame and update the frame in
|
| * the alt ref slot instead. This is highly specific to the current use of
|
| * alt-ref as a forward reference, and this needs to be generalized as
|
| @@ -1549,14 +1580,14 @@
|
| tmp = cpi->alt_fb_idx;
|
| cpi->alt_fb_idx = cpi->gld_fb_idx;
|
| cpi->gld_fb_idx = tmp;
|
| - } else { /* For non key/golden frames */
|
| + } else { /* For non key/golden frames */
|
| if (cpi->refresh_alt_ref_frame) {
|
| int arf_idx = cpi->alt_fb_idx;
|
| -#if CONFIG_MULTIPLE_ARF
|
| - if (cpi->multi_arf_enabled) {
|
| - arf_idx = cpi->arf_buffer_idx[cpi->sequence_number + 1];
|
| + if ((cpi->pass == 2) && cpi->multi_arf_allowed) {
|
| + const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
| + arf_idx = gf_group->arf_update_idx[gf_group->index];
|
| }
|
| -#endif
|
| +
|
| ref_cnt_fb(cm->frame_bufs,
|
| &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
|
| }
|
| @@ -1572,12 +1603,14 @@
|
| &cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
|
| }
|
| #if CONFIG_DENOISING
|
| - vp9_denoiser_update_frame_info(&cpi->denoiser,
|
| - *cpi->Source,
|
| - cpi->common.frame_type,
|
| - cpi->refresh_alt_ref_frame,
|
| - cpi->refresh_golden_frame,
|
| - cpi->refresh_last_frame);
|
| + if (cpi->oxcf.noise_sensitivity > 0) {
|
| + vp9_denoiser_update_frame_info(&cpi->denoiser,
|
| + *cpi->Source,
|
| + cpi->common.frame_type,
|
| + cpi->refresh_alt_ref_frame,
|
| + cpi->refresh_golden_frame,
|
| + cpi->refresh_last_frame);
|
| + }
|
| #endif
|
| }
|
|
|
| @@ -1609,13 +1642,15 @@
|
| void vp9_scale_references(VP9_COMP *cpi) {
|
| VP9_COMMON *cm = &cpi->common;
|
| MV_REFERENCE_FRAME ref_frame;
|
| + const VP9_REFFRAME ref_mask[3] = {VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG};
|
|
|
| for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
|
| const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
|
| const YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf;
|
|
|
| - if (ref->y_crop_width != cm->width ||
|
| - ref->y_crop_height != cm->height) {
|
| + // Need to convert from VP9_REFFRAME to index into ref_mask (subtract 1).
|
| + if ((cpi->ref_frame_flags & ref_mask[ref_frame - 1]) &&
|
| + (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height)) {
|
| const int new_fb = get_free_fb(cm);
|
| vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
|
| cm->width, cm->height,
|
| @@ -2003,6 +2038,29 @@
|
| }
|
| }
|
|
|
| +static void configure_skippable_frame(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
|
| +
|
| + SVC *const svc = &cpi->svc;
|
| + const int is_spatial_svc = (svc->number_spatial_layers > 1) &&
|
| + (svc->number_temporal_layers == 1);
|
| + TWO_PASS *const twopass = is_spatial_svc ?
|
| + &svc->layer_context[svc->spatial_layer_id].twopass
|
| + : &cpi->twopass;
|
| +
|
| + cpi->skippable_frame = (!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
|
| + == 1 &&
|
| + (twopass->stats_in - 2)->pcnt_inter - (twopass->stats_in - 2)->pcnt_motion
|
| + == 1 &&
|
| + twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1);
|
| +}
|
| +
|
| static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
| size_t *size,
|
| uint8_t *dest,
|
| @@ -2098,6 +2156,13 @@
|
| if (cpi->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->pass == 2 &&
|
| + (!cpi->use_svc || cpi->svc.number_temporal_layers == 1)) {
|
| + configure_skippable_frame(cpi);
|
| + }
|
| +
|
| // For 1 pass CBR, check if we are dropping this frame.
|
| // Never drop on key frame.
|
| if (cpi->pass == 0 &&
|
| @@ -2137,23 +2202,28 @@
|
| }
|
| #endif
|
|
|
| -#ifdef OUTPUT_YUV_DENOISED
|
| - vp9_write_yuv_frame(&cpi->denoiser.running_avg_y[INTRA_FRAME],
|
| - yuv_denoised_file);
|
| -#endif
|
| #ifdef OUTPUT_YUV_SRC
|
| vp9_write_yuv_frame(cpi->Source, yuv_file);
|
| #endif
|
|
|
| set_speed_features(cpi);
|
|
|
| +#if CONFIG_DENOISING
|
| +#ifdef OUTPUT_YUV_DENOISED
|
| + if (cpi->oxcf.noise_sensitivity > 0) {
|
| + vp9_write_yuv_frame_420(&cpi->denoiser.running_avg_y[INTRA_FRAME],
|
| + yuv_denoised_file);
|
| + }
|
| +#endif
|
| +#endif
|
| +
|
| // Decide q and q bounds.
|
| q = vp9_rc_pick_q_and_bounds(cpi, &bottom_index, &top_index);
|
|
|
| if (!frame_is_intra_only(cm)) {
|
| cm->interp_filter = DEFAULT_INTERP_FILTER;
|
| /* TODO: Decide this more intelligently */
|
| - set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
|
| + vp9_set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
|
| }
|
|
|
| if (cpi->sf.recode_loop == DISALLOW_RECODE) {
|
| @@ -2241,31 +2311,8 @@
|
| if (cm->frame_type == KEY_FRAME) {
|
| // Tell the caller that the frame was coded as a key frame
|
| *frame_flags = cpi->frame_flags | FRAMEFLAGS_KEY;
|
| -
|
| -#if CONFIG_MULTIPLE_ARF
|
| - // Reset the sequence number.
|
| - if (cpi->multi_arf_enabled) {
|
| - cpi->sequence_number = 0;
|
| - cpi->frame_coding_order_period = cpi->new_frame_coding_order_period;
|
| - cpi->new_frame_coding_order_period = -1;
|
| - }
|
| -#endif
|
| } else {
|
| *frame_flags = cpi->frame_flags & ~FRAMEFLAGS_KEY;
|
| -
|
| -#if CONFIG_MULTIPLE_ARF
|
| - /* Increment position in the coded frame sequence. */
|
| - if (cpi->multi_arf_enabled) {
|
| - ++cpi->sequence_number;
|
| - if (cpi->sequence_number >= cpi->frame_coding_order_period) {
|
| - cpi->sequence_number = 0;
|
| - cpi->frame_coding_order_period = cpi->new_frame_coding_order_period;
|
| - cpi->new_frame_coding_order_period = -1;
|
| - }
|
| - cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number];
|
| - assert(cpi->this_frame_weight >= 0);
|
| - }
|
| -#endif
|
| }
|
|
|
| // Clear the one shot update flags for segmentation map and mode/ref loop
|
| @@ -2319,6 +2366,16 @@
|
| vp9_twopass_postencode_update(cpi);
|
| }
|
|
|
| +static void init_motion_estimation(VP9_COMP *cpi) {
|
| + int y_stride = cpi->scaled_source.y_stride;
|
| +
|
| + if (cpi->sf.mv.search_method == NSTEP) {
|
| + vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride);
|
| + } else if (cpi->sf.mv.search_method == DIAMOND) {
|
| + vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride);
|
| + }
|
| +}
|
| +
|
| static void check_initial_width(VP9_COMP *cpi, int subsampling_x,
|
| int subsampling_y) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| @@ -2326,7 +2383,13 @@
|
| if (!cpi->initial_width) {
|
| cm->subsampling_x = subsampling_x;
|
| cm->subsampling_y = subsampling_y;
|
| +
|
| alloc_raw_frame_buffers(cpi);
|
| + alloc_ref_frame_buffers(cpi);
|
| + alloc_util_frame_buffers(cpi);
|
| +
|
| + init_motion_estimation(cpi);
|
| +
|
| cpi->initial_width = cm->width;
|
| cpi->initial_height = cm->height;
|
| }
|
| @@ -2341,11 +2404,22 @@
|
| int res = 0;
|
| const int subsampling_x = sd->uv_width < sd->y_width;
|
| const int subsampling_y = sd->uv_height < sd->y_height;
|
| + const int is_spatial_svc = cpi->use_svc &&
|
| + (cpi->svc.number_temporal_layers == 1);
|
|
|
| check_initial_width(cpi, subsampling_x, subsampling_y);
|
| +
|
| vpx_usec_timer_start(&timer);
|
| - if (vp9_lookahead_push(cpi->lookahead,
|
| - sd, time_stamp, end_time, frame_flags))
|
| +
|
| +#ifdef CONFIG_SPATIAL_SVC
|
| + if (is_spatial_svc)
|
| + res = vp9_svc_lookahead_push(cpi, cpi->lookahead, sd, time_stamp, end_time,
|
| + frame_flags);
|
| + else
|
| +#endif
|
| + res = vp9_lookahead_push(cpi->lookahead,
|
| + sd, time_stamp, end_time, frame_flags);
|
| + if (res)
|
| res = -1;
|
| vpx_usec_timer_mark(&timer);
|
| cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
|
| @@ -2373,13 +2447,6 @@
|
| cm->seg.update_data;
|
| }
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| -int is_next_frame_arf(VP9_COMP *cpi) {
|
| - // Negative entry in frame_coding_order indicates an ARF at this position.
|
| - return cpi->frame_coding_order[cpi->sequence_number + 1] < 0 ? 1 : 0;
|
| -}
|
| -#endif
|
| -
|
| void adjust_frame_rate(VP9_COMP *cpi) {
|
| int64_t this_duration;
|
| int step = 0;
|
| @@ -2418,6 +2485,46 @@
|
| cpi->last_end_time_stamp_seen = cpi->source->ts_end;
|
| }
|
|
|
| +// Returns 0 if this is not an alt ref else the offset of the source frame
|
| +// used as the arf midpoint.
|
| +static int get_arf_src_index(VP9_COMP *cpi) {
|
| + RATE_CONTROL *const rc = &cpi->rc;
|
| + int arf_src_index = 0;
|
| + if (is_altref_enabled(&cpi->oxcf)) {
|
| + if (cpi->pass == 2) {
|
| + const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
| + if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
|
| + arf_src_index = gf_group->arf_src_offset[gf_group->index];
|
| + }
|
| + } else if (rc->source_alt_ref_pending) {
|
| + arf_src_index = rc->frames_till_gf_update_due;
|
| + }
|
| + }
|
| + return arf_src_index;
|
| +}
|
| +
|
| +static void check_src_altref(VP9_COMP *cpi) {
|
| + RATE_CONTROL *const rc = &cpi->rc;
|
| +
|
| + if (cpi->pass == 2) {
|
| + const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
| + rc->is_src_frame_alt_ref =
|
| + (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);
|
| + }
|
| +
|
| + if (rc->is_src_frame_alt_ref) {
|
| + // Current frame is an ARF overlay frame.
|
| + cpi->alt_ref_source = NULL;
|
| +
|
| + // Don't refresh the last buffer for an ARF overlay frame. It will
|
| + // become the GF so preserve last as an alternative prediction option.
|
| + cpi->refresh_last_frame = 0;
|
| + }
|
| +}
|
| +
|
| int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
| size_t *size, uint8_t *dest,
|
| int64_t *time_stamp, int64_t *time_end, int flush) {
|
| @@ -2427,11 +2534,16 @@
|
| struct vpx_usec_timer cmptimer;
|
| YV12_BUFFER_CONFIG *force_src_buffer = NULL;
|
| MV_REFERENCE_FRAME ref_frame;
|
| + int arf_src_index;
|
| + const int is_spatial_svc = cpi->use_svc &&
|
| + (cpi->svc.number_temporal_layers == 1) &&
|
| + (cpi->svc.number_spatial_layers > 1);
|
|
|
| if (!cpi)
|
| return -1;
|
|
|
| - if (cpi->svc.number_spatial_layers > 1 && cpi->pass == 2) {
|
| + if (is_spatial_svc && cpi->pass == 2) {
|
| + vp9_svc_lookahead_peek(cpi, cpi->lookahead, 0, 1);
|
| vp9_restore_layer_context(cpi);
|
| }
|
|
|
| @@ -2440,7 +2552,7 @@
|
| cpi->source = NULL;
|
| cpi->last_source = NULL;
|
|
|
| - set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
|
| + vp9_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
|
|
|
| // Normal defaults
|
| cm->reset_frame_context = 0;
|
| @@ -2449,35 +2561,26 @@
|
| cpi->refresh_golden_frame = 0;
|
| cpi->refresh_alt_ref_frame = 0;
|
|
|
| - // Should we code an alternate reference frame.
|
| - if (is_altref_enabled(&cpi->oxcf) && rc->source_alt_ref_pending) {
|
| - int frames_to_arf;
|
| + // Should we encode an arf frame.
|
| + arf_src_index = get_arf_src_index(cpi);
|
| + if (arf_src_index) {
|
| + assert(arf_src_index <= rc->frames_to_key);
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| - assert(!cpi->multi_arf_enabled ||
|
| - cpi->frame_coding_order[cpi->sequence_number] < 0);
|
| -
|
| - if (cpi->multi_arf_enabled && (cpi->pass == 2))
|
| - frames_to_arf = (-cpi->frame_coding_order[cpi->sequence_number])
|
| - - cpi->next_frame_in_order;
|
| +#ifdef CONFIG_SPATIAL_SVC
|
| + if (is_spatial_svc)
|
| + cpi->source = vp9_svc_lookahead_peek(cpi, cpi->lookahead,
|
| + arf_src_index, 1);
|
| else
|
| #endif
|
| - frames_to_arf = rc->frames_till_gf_update_due;
|
| -
|
| - assert(frames_to_arf <= rc->frames_to_key);
|
| -
|
| - if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, frames_to_arf))) {
|
| -#if CONFIG_MULTIPLE_ARF
|
| - cpi->alt_ref_source[cpi->arf_buffered] = cpi->source;
|
| -#else
|
| + cpi->source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
|
| + if (cpi->source != NULL) {
|
| cpi->alt_ref_source = cpi->source;
|
| -#endif
|
|
|
| if (cpi->oxcf.arnr_max_frames > 0) {
|
| // Produce the filtered ARF frame.
|
| // TODO(agrange) merge these two functions.
|
| - vp9_configure_arnr_filter(cpi, frames_to_arf, rc->gfu_boost);
|
| - vp9_temporal_filter_prepare(cpi, frames_to_arf);
|
| + vp9_configure_arnr_filter(cpi, arf_src_index, rc->gfu_boost);
|
| + vp9_temporal_filter_prepare(cpi, arf_src_index);
|
| vp9_extend_frame_borders(&cpi->alt_ref_buffer);
|
| force_src_buffer = &cpi->alt_ref_buffer;
|
| }
|
| @@ -2487,59 +2590,38 @@
|
| cpi->refresh_golden_frame = 0;
|
| cpi->refresh_last_frame = 0;
|
| rc->is_src_frame_alt_ref = 0;
|
| -
|
| -#if CONFIG_MULTIPLE_ARF
|
| - if (!cpi->multi_arf_enabled)
|
| -#endif
|
| - rc->source_alt_ref_pending = 0;
|
| + rc->source_alt_ref_pending = 0;
|
| } else {
|
| rc->source_alt_ref_pending = 0;
|
| }
|
| }
|
|
|
| if (!cpi->source) {
|
| -#if CONFIG_MULTIPLE_ARF
|
| - int i;
|
| -#endif
|
| -
|
| // Get last frame source.
|
| if (cm->current_video_frame > 0) {
|
| - if ((cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1)) == NULL)
|
| +#ifdef CONFIG_SPATIAL_SVC
|
| + if (is_spatial_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)
|
| return -1;
|
| }
|
|
|
| - if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) {
|
| + // Read in the source frame.
|
| +#ifdef CONFIG_SPATIAL_SVC
|
| + if (is_spatial_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) {
|
| cm->show_frame = 1;
|
| cm->intra_only = 0;
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| - // Is this frame the ARF overlay.
|
| - rc->is_src_frame_alt_ref = 0;
|
| - for (i = 0; i < cpi->arf_buffered; ++i) {
|
| - if (cpi->source == cpi->alt_ref_source[i]) {
|
| - rc->is_src_frame_alt_ref = 1;
|
| - cpi->refresh_golden_frame = 1;
|
| - break;
|
| - }
|
| - }
|
| -#else
|
| - rc->is_src_frame_alt_ref = cpi->alt_ref_source &&
|
| - (cpi->source == cpi->alt_ref_source);
|
| -#endif
|
| - if (rc->is_src_frame_alt_ref) {
|
| - // Current frame is an ARF overlay frame.
|
| -#if CONFIG_MULTIPLE_ARF
|
| - cpi->alt_ref_source[i] = NULL;
|
| -#else
|
| - cpi->alt_ref_source = NULL;
|
| -#endif
|
| - // Don't refresh the last buffer for an ARF overlay frame. It will
|
| - // become the GF so preserve last as an alternative prediction option.
|
| - cpi->refresh_last_frame = 0;
|
| - }
|
| -#if CONFIG_MULTIPLE_ARF
|
| - ++cpi->next_frame_in_order;
|
| -#endif
|
| + // Check to see if the frame should be encoded as an arf overlay.
|
| + check_src_altref(cpi);
|
| }
|
| }
|
|
|
| @@ -2547,20 +2629,17 @@
|
| cpi->un_scaled_source = cpi->Source = force_src_buffer ? force_src_buffer
|
| : &cpi->source->img;
|
|
|
| - if (cpi->last_source != NULL) {
|
| - cpi->unscaled_last_source = &cpi->last_source->img;
|
| - } else {
|
| - cpi->unscaled_last_source = NULL;
|
| - }
|
| + if (cpi->last_source != NULL) {
|
| + cpi->unscaled_last_source = &cpi->last_source->img;
|
| + } else {
|
| + cpi->unscaled_last_source = NULL;
|
| + }
|
|
|
| *time_stamp = cpi->source->ts_start;
|
| *time_end = cpi->source->ts_end;
|
| - *frame_flags = cpi->source->flags;
|
| + *frame_flags =
|
| + (cpi->source->flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| - if (cm->frame_type != KEY_FRAME && cpi->pass == 2)
|
| - rc->source_alt_ref_pending = is_next_frame_arf(cpi);
|
| -#endif
|
| } else {
|
| *size = 0;
|
| if (flush && cpi->pass == 1 && !cpi->twopass.first_pass_done) {
|
| @@ -2598,16 +2677,14 @@
|
| cm->frame_bufs[cm->new_fb_idx].ref_count--;
|
| cm->new_fb_idx = get_free_fb(cm);
|
|
|
| -#if CONFIG_MULTIPLE_ARF
|
| - /* Set up the correct ARF frame. */
|
| - if (cpi->refresh_alt_ref_frame) {
|
| - ++cpi->arf_buffered;
|
| + if (!cpi->use_svc && cpi->multi_arf_allowed) {
|
| + if (cm->frame_type == KEY_FRAME) {
|
| + init_buffer_indices(cpi);
|
| + } else if (cpi->pass == 2) {
|
| + const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
| + cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index];
|
| + }
|
| }
|
| - if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
|
| - (cpi->pass == 2)) {
|
| - cpi->alt_fb_idx = cpi->arf_buffer_idx[cpi->sequence_number];
|
| - }
|
| -#endif
|
|
|
| cpi->frame_flags = *frame_flags;
|
|
|
| @@ -2626,6 +2703,9 @@
|
| cm->subsampling_x, cm->subsampling_y,
|
| VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
|
|
|
| + alloc_util_frame_buffers(cpi);
|
| + init_motion_estimation(cpi);
|
| +
|
| for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
|
| const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
|
| YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf;
|
| @@ -2795,16 +2875,23 @@
|
|
|
| int vp9_set_active_map(VP9_COMP *cpi, unsigned char *map, int rows, int cols) {
|
| if (rows == cpi->common.mb_rows && cols == cpi->common.mb_cols) {
|
| + const int mi_rows = cpi->common.mi_rows;
|
| + const int mi_cols = cpi->common.mi_cols;
|
| if (map) {
|
| - vpx_memcpy(cpi->active_map, map, rows * cols);
|
| - cpi->active_map_enabled = 1;
|
| + int r, c;
|
| + for (r = 0; r < mi_rows; r++) {
|
| + for (c = 0; c < mi_cols; c++) {
|
| + cpi->segmentation_map[r * mi_cols + c] =
|
| + !map[(r >> 1) * cols + (c >> 1)];
|
| + }
|
| + }
|
| + vp9_enable_segfeature(&cpi->common.seg, 1, SEG_LVL_SKIP);
|
| + vp9_enable_segmentation(&cpi->common.seg);
|
| } else {
|
| - cpi->active_map_enabled = 0;
|
| + vp9_disable_segmentation(&cpi->common.seg);
|
| }
|
| -
|
| return 0;
|
| } else {
|
| - // cpi->active_map_enabled = 0;
|
| return -1;
|
| }
|
| }
|
| @@ -2883,3 +2970,42 @@
|
| int vp9_get_quantizer(VP9_COMP *cpi) {
|
| return cpi->common.base_qindex;
|
| }
|
| +
|
| +void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags) {
|
| + if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF |
|
| + VP8_EFLAG_NO_REF_ARF)) {
|
| + int ref = 7;
|
| +
|
| + if (flags & VP8_EFLAG_NO_REF_LAST)
|
| + ref ^= VP9_LAST_FLAG;
|
| +
|
| + if (flags & VP8_EFLAG_NO_REF_GF)
|
| + ref ^= VP9_GOLD_FLAG;
|
| +
|
| + if (flags & VP8_EFLAG_NO_REF_ARF)
|
| + ref ^= VP9_ALT_FLAG;
|
| +
|
| + vp9_use_as_reference(cpi, ref);
|
| + }
|
| +
|
| + if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
|
| + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF |
|
| + VP8_EFLAG_FORCE_ARF)) {
|
| + int upd = 7;
|
| +
|
| + if (flags & VP8_EFLAG_NO_UPD_LAST)
|
| + upd ^= VP9_LAST_FLAG;
|
| +
|
| + if (flags & VP8_EFLAG_NO_UPD_GF)
|
| + upd ^= VP9_GOLD_FLAG;
|
| +
|
| + if (flags & VP8_EFLAG_NO_UPD_ARF)
|
| + upd ^= VP9_ALT_FLAG;
|
| +
|
| + vp9_update_reference(cpi, upd);
|
| + }
|
| +
|
| + if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
|
| + vp9_update_entropy(cpi, 0);
|
| + }
|
| +}
|
|
|