diff options
Diffstat (limited to 'vp8/encoder/firstpass.c')
-rw-r--r-- | vp8/encoder/firstpass.c | 185 |
1 files changed, 83 insertions, 102 deletions
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 13633e9a4..607c3d236 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -30,7 +30,6 @@ #include "encodemv.h" //#define OUTPUT_FPF 1 -#define FIRSTPASS_MM 1 #if CONFIG_RUNTIME_CPU_DETECT #define IF_RTCD(x) (x) @@ -108,15 +107,6 @@ static void reset_fpf_position(VP8_COMP *cpi, FIRSTPASS_STATS *Position) static int lookup_next_frame_stats(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame) { - /*FIRSTPASS_STATS * start_pos; - int ret_val; - - start_pos = cpi->stats_in; - ret_val = vp8_input_stats(cpi, next_frame); - reset_fpf_position(cpi, start_pos); - - return ret_val;*/ - if (cpi->stats_in >= cpi->stats_in_end) return EOF; @@ -127,7 +117,7 @@ static int lookup_next_frame_stats(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame) // Calculate a modified Error used in distributing bits between easier and harder frames static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) { - double av_err = cpi->total_stats.ssim_weighted_pred_err; + double av_err = cpi->total_stats->ssim_weighted_pred_err; double this_err = this_frame->ssim_weighted_pred_err; double modified_err; @@ -238,7 +228,7 @@ int frame_max_bits(VP8_COMP *cpi) else { // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user - max_bits = (int)(((double)cpi->bits_left / (cpi->total_stats.count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0)); + max_bits = (int)(((double)cpi->bits_left / (cpi->total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0)); } // Trap case where we are out of bits @@ -248,13 +238,31 @@ int frame_max_bits(VP8_COMP *cpi) return max_bits; } -void vp8_output_stats(struct vpx_codec_pkt_list *pktlist, + +extern size_t vp8_firstpass_stats_sz(unsigned int mb_count) +{ + /* Calculate the size of a stats packet, which is dependent on the frame + * resolution. The FIRSTPASS_STATS struct has a single element array, + * motion_map, which is virtually expanded to have one element per + * macroblock. + */ + size_t stats_sz; + FIRSTPASS_STATS stats; + + stats_sz = sizeof(FIRSTPASS_STATS) + mb_count; + stats_sz = (stats_sz + 7) & ~7; + return stats_sz; +} + + +void vp8_output_stats(const VP8_COMP *cpi, + struct vpx_codec_pkt_list *pktlist, FIRSTPASS_STATS *stats) { struct vpx_codec_cx_pkt pkt; pkt.kind = VPX_CODEC_STATS_PKT; pkt.data.twopass_stats.buf = stats; - pkt.data.twopass_stats.sz = sizeof(*stats); + pkt.data.twopass_stats.sz = vp8_firstpass_stats_sz(cpi->common.MBs); vpx_codec_pkt_list_add(pktlist, &pkt); // TEMP debug code @@ -280,16 +288,24 @@ void vp8_output_stats(struct vpx_codec_pkt_list *pktlist, stats->mv_in_out_count, stats->count); fclose(fpfile); + + + fpfile = fopen("fpmotionmap.stt", "a"); + fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, fpfile); + fclose(fpfile); } #endif } int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps) { + size_t stats_sz = vp8_firstpass_stats_sz(cpi->common.MBs); + if (cpi->stats_in >= cpi->stats_in_end) return EOF; - *fps = *cpi->stats_in++; + *fps = *cpi->stats_in; + cpi->stats_in = (void*)((char *)cpi->stats_in + stats_sz); return 1; } @@ -352,59 +368,47 @@ void vp8_avg_stats(FIRSTPASS_STATS *section) section->duration /= section->count; } -int vp8_fpmm_get_pos(VP8_COMP *cpi) +unsigned char *vp8_fpmm_get_pos(VP8_COMP *cpi) { - return ftell(cpi->fp_motion_mapfile); + return cpi->fp_motion_map_stats; } -void vp8_fpmm_reset_pos(VP8_COMP *cpi, int target_pos) +void vp8_fpmm_reset_pos(VP8_COMP *cpi, unsigned char *target_pos) { int Offset; - if (cpi->fp_motion_mapfile) - { - Offset = ftell(cpi->fp_motion_mapfile) - target_pos; - fseek(cpi->fp_motion_mapfile, (int) - Offset, SEEK_CUR); - } + cpi->fp_motion_map_stats = target_pos; } void vp8_advance_fpmm(VP8_COMP *cpi, int count) { -#if FIRSTPASS_MM - fseek(cpi->fp_motion_mapfile, (int)(count * cpi->common.MBs), SEEK_CUR); -#endif + cpi->fp_motion_map_stats = (void*)((char*)cpi->fp_motion_map_stats + + count * vp8_firstpass_stats_sz(cpi->common.MBs)); } void vp8_input_fpmm(VP8_COMP *cpi) { -#if FIRSTPASS_MM + unsigned char *fpmm = cpi->fp_motion_map; int MBs = cpi->common.MBs; int max_frames = cpi->active_arnr_frames; + int i; - if (!cpi->fp_motion_mapfile) - return; // Error - - // Read the specified number of frame motion maps - if (fread(cpi->fp_motion_map, 1, - max_frames * MBs, - cpi->fp_motion_mapfile) != max_frames*MBs) + for (i=0; i<max_frames; i++) { - // Read error - return; + char *motion_map = (char*)cpi->fp_motion_map_stats + + sizeof(FIRSTPASS_STATS); + + memcpy(fpmm, motion_map, MBs); + fpmm += MBs; + vp8_advance_fpmm(cpi, 1); } // Flag the use of weights in the temporal filter cpi->use_weighted_temporal_filter = 1; - -#endif } void vp8_init_first_pass(VP8_COMP *cpi) { - vp8_zero_stats(&cpi->total_stats); - -#ifdef FIRSTPASS_MM - cpi->fp_motion_mapfile = fopen("fpmotionmap.stt", "wb"); -#endif + vp8_zero_stats(cpi->total_stats); // TEMP debug code #ifdef OUTPUT_FPF @@ -412,6 +416,8 @@ void vp8_init_first_pass(VP8_COMP *cpi) FILE *fpfile; fpfile = fopen("firstpass.stt", "w"); fclose(fpfile); + fpfile = fopen("fpmotionmap.stt", "wb"); + fclose(fpfile); } #endif @@ -419,16 +425,10 @@ void vp8_init_first_pass(VP8_COMP *cpi) void vp8_end_first_pass(VP8_COMP *cpi) { - vp8_output_stats(cpi->output_pkt_list, &cpi->total_stats); - -#if FIRSTPASS_MM - - if (cpi->fp_motion_mapfile) - fclose(cpi->fp_motion_mapfile); + vp8_output_stats(cpi, cpi->output_pkt_list, cpi->total_stats); +} -#endif -} void vp8_zz_motion_search( VP8_COMP *cpi, MACROBLOCK * x, YV12_BUFFER_CONFIG * recon_buffer, int * best_motion_err, int recon_yoffset ) { MACROBLOCKD * const xd = & x->e_mbd; @@ -839,19 +839,20 @@ void vp8_first_pass(VP8_COMP *cpi) fps.duration = cpi->source_end_time_stamp - cpi->source_time_stamp; // don't want to do outputstats with a stack variable! - cpi->this_frame_stats = fps; - vp8_output_stats(cpi->output_pkt_list, &cpi->this_frame_stats); - vp8_accumulate_stats(&cpi->total_stats, &fps); - -#if FIRSTPASS_MM - fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, cpi->fp_motion_mapfile); -#endif + memcpy(cpi->this_frame_stats, + &fps, + sizeof(FIRSTPASS_STATS)); + memcpy((char*)cpi->this_frame_stats + sizeof(FIRSTPASS_STATS), + cpi->fp_motion_map, + sizeof(cpi->fp_motion_map[0]) * cpi->common.MBs); + vp8_output_stats(cpi, cpi->output_pkt_list, cpi->this_frame_stats); + vp8_accumulate_stats(cpi->total_stats, &fps); } // Copy the previous Last Frame into the GF buffer if specific conditions for doing so are met if ((cm->current_video_frame > 0) && - (cpi->this_frame_stats.pcnt_inter > 0.20) && - ((cpi->this_frame_stats.intra_error / cpi->this_frame_stats.coded_error) > 2.0)) + (cpi->this_frame_stats->pcnt_inter > 0.20) && + ((cpi->this_frame_stats->intra_error / cpi->this_frame_stats->coded_error) > 2.0)) { vp8_yv12_copy_frame_ptr(lst_yv12, gld_yv12); } @@ -1120,33 +1121,33 @@ void vp8_init_second_pass(VP8_COMP *cpi) double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100); - vp8_zero_stats(&cpi->total_stats); + vp8_zero_stats(cpi->total_stats); if (!cpi->stats_in_end) return; - cpi->total_stats = *cpi->stats_in_end; + *cpi->total_stats = *cpi->stats_in_end; - cpi->total_error_left = cpi->total_stats.ssim_weighted_pred_err; - cpi->total_intra_error_left = cpi->total_stats.intra_error; - cpi->total_coded_error_left = cpi->total_stats.coded_error; + cpi->total_error_left = cpi->total_stats->ssim_weighted_pred_err; + cpi->total_intra_error_left = cpi->total_stats->intra_error; + cpi->total_coded_error_left = cpi->total_stats->coded_error; cpi->start_tot_err_left = cpi->total_error_left; - //cpi->bits_left = (long long)(cpi->total_stats.count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); - //cpi->bits_left -= (long long)(cpi->total_stats.count * two_pass_min_rate / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); + //cpi->bits_left = (long long)(cpi->total_stats->count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); + //cpi->bits_left -= (long long)(cpi->total_stats->count * two_pass_min_rate / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); // each frame can have a different duration, as the frame rate in the source // isn't guaranteed to be constant. The frame rate prior to the first frame // encoded in the second pass is a guess. However the sum duration is not. // Its calculated based on the actual durations of all frames from the first // pass. - vp8_new_frame_rate(cpi, 10000000.0 * cpi->total_stats.count / cpi->total_stats.duration); + vp8_new_frame_rate(cpi, 10000000.0 * cpi->total_stats->count / cpi->total_stats->duration); cpi->output_frame_rate = cpi->oxcf.frame_rate; - cpi->bits_left = (long long)(cpi->total_stats.duration * cpi->oxcf.target_bandwidth / 10000000.0) ; - cpi->bits_left -= (long long)(cpi->total_stats.duration * two_pass_min_rate / 10000000.0); + cpi->bits_left = (long long)(cpi->total_stats->duration * cpi->oxcf.target_bandwidth / 10000000.0) ; + cpi->bits_left -= (long long)(cpi->total_stats->duration * two_pass_min_rate / 10000000.0); - vp8_avg_stats(&cpi->total_stats); + vp8_avg_stats(cpi->total_stats); // Scan the first pass file and calculate an average Intra / Inter error score ratio for the sequence { @@ -1162,7 +1163,7 @@ void vp8_init_second_pass(VP8_COMP *cpi) sum_iiratio += IIRatio; } - cpi->avg_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK((double)cpi->total_stats.count); + cpi->avg_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK((double)cpi->total_stats->count); // Reset file position reset_fpf_position(cpi, start_pos); @@ -1184,21 +1185,11 @@ void vp8_init_second_pass(VP8_COMP *cpi) } -#if FIRSTPASS_MM - cpi->fp_motion_mapfile = 0; - cpi->fp_motion_mapfile = fopen("fpmotionmap.stt", "rb"); -#endif - + cpi->fp_motion_map_stats = (unsigned char *)cpi->stats_in; } void vp8_end_second_pass(VP8_COMP *cpi) { -#if FIRSTPASS_MM - - if (cpi->fp_motion_mapfile) - fclose(cpi->fp_motion_mapfile); - -#endif } // Analyse and define a gf/arf group . @@ -1231,18 +1222,14 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) int max_bits = frame_max_bits(cpi); // Max for a single frame -#if FIRSTPASS_MM - int fpmm_pos; -#endif + unsigned char *fpmm_pos; cpi->gf_group_bits = 0; cpi->gf_decay_rate = 0; vp8_clear_system_state(); //__asm emms; -#if FIRSTPASS_MM fpmm_pos = vp8_fpmm_get_pos(cpi); -#endif start_pos = cpi->stats_in; @@ -1494,7 +1481,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) // Note: this_frame->frame has been updated in the loop // so it now points at the ARF frame. half_gf_int = cpi->baseline_gf_interval >> 1; - frames_after_arf = cpi->total_stats.count - this_frame->frame - 1; + frames_after_arf = cpi->total_stats->count - this_frame->frame - 1; switch (cpi->oxcf.arnr_type) { @@ -1531,12 +1518,11 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd; -#if FIRSTPASS_MM { // Advance to & read in the motion map for those frames // to be considered for filtering based on the position // of the ARF - vp8_fpmm_reset_pos(cpi, cpi->fpmm_pos); + vp8_fpmm_reset_pos(cpi, cpi->fp_motion_map_stats_save); // Position at the 'earliest' frame to be filtered vp8_advance_fpmm(cpi, @@ -1545,7 +1531,6 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) // Read / create a motion map for the region of interest vp8_input_fpmm(cpi); } -#endif } else { @@ -1581,7 +1566,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) // Now decide how many bits should be allocated to the GF group as a proportion of those remaining in the kf group. // The final key frame group in the clip is treated as a special case where cpi->kf_group_bits is tied to cpi->bits_left. // This is also important for short clips where there may only be one key frame. - if (cpi->frames_to_key >= (int)(cpi->total_stats.count - cpi->common.current_video_frame)) + if (cpi->frames_to_key >= (int)(cpi->total_stats->count - cpi->common.current_video_frame)) { cpi->kf_group_bits = (cpi->bits_left > 0) ? cpi->bits_left : 0; } @@ -1781,10 +1766,8 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) reset_fpf_position(cpi, start_pos); } -#if FIRSTPASS_MM // Reset the First pass motion map file position vp8_fpmm_reset_pos(cpi, fpmm_pos); -#endif } // Allocate bits to a normal frame that is neither a gf an arf or a key frame. @@ -1798,7 +1781,7 @@ static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) int max_bits = frame_max_bits(cpi); // Max for a single frame // The final few frames have special treatment - if (cpi->frames_till_gf_update_due >= (int)(cpi->total_stats.count - cpi->common.current_video_frame)) + if (cpi->frames_till_gf_update_due >= (int)(cpi->total_stats->count - cpi->common.current_video_frame)) { cpi->gf_group_bits = (cpi->bits_left > 0) ? cpi->bits_left : 0;; } @@ -1843,7 +1826,7 @@ static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) void vp8_second_pass(VP8_COMP *cpi) { int tmp_q; - int frames_left = (int)(cpi->total_stats.count - cpi->common.current_video_frame); + int frames_left = (int)(cpi->total_stats->count - cpi->common.current_video_frame); FIRSTPASS_STATS this_frame; FIRSTPASS_STATS this_frame_copy; @@ -1866,14 +1849,12 @@ void vp8_second_pass(VP8_COMP *cpi) if (EOF == vp8_input_stats(cpi, &this_frame)) return; -#if FIRSTPASS_MM vpx_memset(cpi->fp_motion_map, 0, cpi->oxcf.arnr_max_frames*cpi->common.MBs); - cpi->fpmm_pos = vp8_fpmm_get_pos(cpi); + cpi->fp_motion_map_stats_save = vp8_fpmm_get_pos(cpi); // Step over this frame's first pass motion map vp8_advance_fpmm(cpi, 1); -#endif this_frame_error = this_frame.ssim_weighted_pred_err; this_frame_intra_error = this_frame.intra_error; @@ -2562,7 +2543,7 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) cpi->common.vert_scale = NORMAL; // Calculate Average bits per frame. - //av_bits_per_frame = cpi->bits_left/(double)(cpi->total_stats.count - cpi->common.current_video_frame); + //av_bits_per_frame = cpi->bits_left/(double)(cpi->total_stats->count - cpi->common.current_video_frame); av_bits_per_frame = cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate); //if ( av_bits_per_frame < 0.0 ) // av_bits_per_frame = 0.0 @@ -2625,7 +2606,7 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) } else { - long long clip_bits = (long long)(cpi->total_stats.count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); + long long clip_bits = (long long)(cpi->total_stats->count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); long long over_spend = cpi->oxcf.starting_buffer_level - cpi->buffer_level; long long over_spend2 = cpi->oxcf.starting_buffer_level - projected_buffer_level; |