diff options
-rw-r--r-- | vp8/encoder/firstpass.c | 185 | ||||
-rw-r--r-- | vp8/encoder/firstpass.h | 1 | ||||
-rw-r--r-- | vp8/encoder/onyx_if.c | 20 | ||||
-rw-r--r-- | vp8/encoder/onyx_int.h | 8 | ||||
-rw-r--r-- | vp8/vp8_cx_iface.c | 18 |
5 files changed, 114 insertions, 118 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; diff --git a/vp8/encoder/firstpass.h b/vp8/encoder/firstpass.h index c7f3e0e45..95e1e5463 100644 --- a/vp8/encoder/firstpass.h +++ b/vp8/encoder/firstpass.h @@ -20,4 +20,5 @@ extern void vp8_init_second_pass(VP8_COMP *cpi); extern void vp8_second_pass(VP8_COMP *cpi); extern void vp8_end_second_pass(VP8_COMP *cpi); +extern size_t vp8_firstpass_stats_sz(unsigned int mb_count); #endif diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 382a9de58..27964f97b 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -330,6 +330,8 @@ void vp8_dealloc_compressor_data(VP8_COMP *cpi) cpi->mb.pip = 0; + vpx_free(cpi->total_stats); + vpx_free(cpi->this_frame_stats); } static void enable_segmentation(VP8_PTR ptr) @@ -1392,6 +1394,12 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi) CHECK_MEM_ERROR(cpi->gf_active_flags, vpx_calloc(1, cm->mb_rows * cm->mb_cols)); cpi->gf_active_count = cm->mb_rows * cm->mb_cols; + + cpi->total_stats = vpx_calloc(1, vp8_firstpass_stats_sz(cpi->common.MBs)); + cpi->this_frame_stats = vpx_calloc(1, vp8_firstpass_stats_sz(cpi->common.MBs)); + if(!cpi->total_stats || !cpi->this_frame_stats) + vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, + "Failed to allocate firstpass stats"); } @@ -2290,10 +2298,12 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) } else if (cpi->pass == 2) { + size_t packet_sz = vp8_firstpass_stats_sz(cpi->common.MBs); + int packets = oxcf->two_pass_stats_in.sz / packet_sz; + cpi->stats_in = oxcf->two_pass_stats_in.buf; - cpi->stats_in_end = cpi->stats_in - + oxcf->two_pass_stats_in.sz / sizeof(FIRSTPASS_STATS) - - 1; + cpi->stats_in_end = (void*)((char *)cpi->stats_in + + (packets - 1) * packet_sz); vp8_init_second_pass(cpi); } @@ -3481,7 +3491,7 @@ static void apply_temporal_filter modifier = 16 - modifier; #endif modifier *= filter_weight; - + count[k] += modifier; accumulator[k] += modifier * pixel_value; @@ -3656,7 +3666,7 @@ static void vp8cx_temp_blur1_c YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index]; unsigned char *dst1, *dst2; DECLARE_ALIGNED(16, unsigned char, predictor[384]); - + // Save input state unsigned char *y_buffer = mbd->pre.y_buffer; unsigned char *u_buffer = mbd->pre.u_buffer; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 8a34a1f3a..51b62c6eb 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -461,14 +461,14 @@ typedef struct int target_bandwidth; long long bits_left; - FIRSTPASS_STATS total_stats; - FIRSTPASS_STATS this_frame_stats; + FIRSTPASS_STATS *total_stats; + FIRSTPASS_STATS *this_frame_stats; FIRSTPASS_STATS *stats_in, *stats_in_end; struct vpx_codec_pkt_list *output_pkt_list; int first_pass_done; unsigned char *fp_motion_map; - FILE *fp_motion_mapfile; - int fpmm_pos; + + unsigned char *fp_motion_map_stats, *fp_motion_map_stats_save; #if 0 // Experimental code for lagged and one pass diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index 499bc503a..b4bb679b5 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -14,6 +14,7 @@ #include "vpx_version.h" #include "onyx_int.h" #include "vpx/vp8e.h" +#include "vp8/encoder/firstpass.h" #include "onyx.h" #include <stdlib.h> #include <string.h> @@ -189,22 +190,25 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, if (cfg->g_pass == VPX_RC_LAST_PASS) { - int n_doubles = cfg->rc_twopass_stats_in.sz / sizeof(double); - int n_packets = cfg->rc_twopass_stats_in.sz / sizeof(FIRSTPASS_STATS); - double frames; + int mb_r = (cfg->g_h + 15) / 16; + int mb_c = (cfg->g_w + 15) / 16; + size_t packet_sz = vp8_firstpass_stats_sz(mb_r * mb_c); + int n_packets = cfg->rc_twopass_stats_in.sz / packet_sz; + FIRSTPASS_STATS *stats; if (!cfg->rc_twopass_stats_in.buf) ERROR("rc_twopass_stats_in.buf not set."); - if (cfg->rc_twopass_stats_in.sz % sizeof(FIRSTPASS_STATS)) + if (cfg->rc_twopass_stats_in.sz % packet_sz) ERROR("rc_twopass_stats_in.sz indicates truncated packet."); - if (cfg->rc_twopass_stats_in.sz < 2 * sizeof(FIRSTPASS_STATS)) + if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz) ERROR("rc_twopass_stats_in requires at least two packets."); - frames = ((double *)cfg->rc_twopass_stats_in.buf)[n_doubles - 1]; + stats = (void*)((char *)cfg->rc_twopass_stats_in.buf + + (n_packets - 1) * packet_sz); - if ((int)(frames + 0.5) != n_packets - 1) + if ((int)(stats->count + 0.5) != n_packets - 1) ERROR("rc_twopass_stats_in missing EOS stats packet"); } |