From aaabbd67b240e0dd581902b857fc040c94275190 Mon Sep 17 00:00:00 2001 From: Pengchong Jin Date: Mon, 30 Jun 2014 09:52:27 -0700 Subject: [PATCH] Store/read 16x16 block statistics obtained from the first pass Add a conditional compile flag for this feature. Also add a switch to enable the encoder to use these statistics in the second pass. Currently, the switch is turned off. Change-Id: Ia1c858c35ec90e36f19f5cffe156b97ddaa04922 --- configure | 1 + vp9/encoder/vp9_encoder.c | 18 ++++++++++ vp9/encoder/vp9_encoder.h | 4 +++ vp9/encoder/vp9_firstpass.c | 66 +++++++++++++++++++++++++++++++++++++ vp9/encoder/vp9_firstpass.h | 16 +++++++++ 5 files changed, 105 insertions(+) diff --git a/configure b/configure index 0dca4c33c..b98480ecb 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ EXPERIMENT_LIST=" multiple_arf spatial_svc denoising + fp_mb_stats " CONFIG_LIST=" external_build diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 54fb68bb6..4f17a15a9 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -199,6 +199,13 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { 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) { @@ -766,6 +773,17 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) { 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; // Note that at the moment multi_arf will not work with svc. diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 5e8430a91..b38f9c246 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -348,6 +348,10 @@ typedef struct VP9_COMP { uint64_t time_pick_lpf; uint64_t time_encode_sb_row; +#if CONFIG_FP_MB_STATS + int use_fp_mb_stats; +#endif + TWO_PASS twopass; YV12_BUFFER_CONFIG alt_ref_buffer; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 971b15931..f90c9df5e 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -106,6 +106,34 @@ static int read_frame_stats(const TWO_PASS *p, return 1; } +#if CONFIG_FP_MB_STATS +static int input_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats, + const VP9_COMMON *const cm) { + FILE *fpfile; + int ret; + + fpfile = fopen("firstpass_mb.stt", "r"); + fseek(fpfile, cm->current_video_frame * cm->MBs * sizeof(FIRSTPASS_MB_STATS), + SEEK_SET); + ret = fread(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs, + fpfile); + fclose(fpfile); + if (ret < cm->MBs) { + return EOF; + } + return 1; +} + +static void output_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats, + const VP9_COMMON *const cm) { + FILE *fpfile; + + fpfile = fopen("firstpass_mb.stt", "a"); + fwrite(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs, fpfile); + fclose(fpfile); +} +#endif + static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) { if (p->stats_in >= p->stats_in_end) return EOF; @@ -452,6 +480,10 @@ void vp9_first_pass(VP9_COMP *cpi) { const MV zero_mv = {0, 0}; const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12; +#if CONFIG_FP_MB_STATS + FIRSTPASS_FRAME_MB_STATS *this_frame_mb_stats = &twopass->this_frame_mb_stats; +#endif + vp9_clear_system_state(); set_first_pass_params(cpi); @@ -579,6 +611,17 @@ void vp9_first_pass(VP9_COMP *cpi) { // Accumulate the intra error. intra_error += (int64_t)this_error; +#if CONFIG_FP_MB_STATS + if (cpi->use_fp_mb_stats) { + this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode = + DC_PRED; + this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err = + this_error; + this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv.as_int + = 0; + } +#endif + // Set up limit values for motion vectors to prevent them extending // outside the UMV borders. x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16); @@ -704,6 +747,17 @@ void vp9_first_pass(VP9_COMP *cpi) { best_ref_mv.as_int = mv.as_int; +#if CONFIG_FP_MB_STATS + if (cpi->use_fp_mb_stats) { + this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode = + NEWMV; + this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err = + motion_error; + this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv. + as_int = mv.as_int; + } +#endif + if (mv.as_int) { ++mvcount; @@ -808,6 +862,12 @@ void vp9_first_pass(VP9_COMP *cpi) { twopass->this_frame_stats = fps; output_stats(&twopass->this_frame_stats, cpi->output_pkt_list); accumulate_stats(&twopass->total_stats, &fps); + +#if CONFIG_FP_MB_STATS + if (cpi->use_fp_mb_stats) { + output_mb_stats(this_frame_mb_stats, cm); + } +#endif } // Copy the previous Last Frame back into gf and and arf buffers if @@ -2167,6 +2227,12 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { // Update the total stats remaining structure. subtract_stats(&twopass->total_left_stats, &this_frame); + +#if CONFIG_FP_MB_STATS + if (cpi->use_fp_mb_stats) { + input_mb_stats(&twopass->this_frame_mb_stats, cm); + } +#endif } void vp9_twopass_postencode_update(VP9_COMP *cpi) { diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 1ee56a3a7..7e4c9ee20 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -18,6 +18,18 @@ extern "C" { #endif +#if CONFIG_FP_MB_STATS +typedef struct { + PREDICTION_MODE mode; + int err; + int_mv mv; +} FIRSTPASS_MB_STATS; + +typedef struct { + FIRSTPASS_MB_STATS *mb_stats; +} FIRSTPASS_FRAME_MB_STATS; +#endif + typedef struct { double frame; double intra_error; @@ -76,6 +88,10 @@ typedef struct { double kf_intra_err_min; double gf_intra_err_min; +#if CONFIG_FP_MB_STATS + FIRSTPASS_FRAME_MB_STATS this_frame_mb_stats; +#endif + // Projected total bits available for a key frame group of frames int64_t kf_group_bits; -- 2.40.0