Merge "Move firstpass motion map to stats packet"

This commit is contained in:
John Koleszar 2010-10-21 11:09:02 -07:00 committed by Code Review
commit 1ee3ebcd66
5 changed files with 115 additions and 119 deletions

View File

@ -30,7 +30,6 @@
#include "encodemv.h" #include "encodemv.h"
//#define OUTPUT_FPF 1 //#define OUTPUT_FPF 1
#define FIRSTPASS_MM 1
#if CONFIG_RUNTIME_CPU_DETECT #if CONFIG_RUNTIME_CPU_DETECT
#define IF_RTCD(x) (x) #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) 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) if (cpi->stats_in >= cpi->stats_in_end)
return EOF; 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 // 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) 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 this_err = this_frame->ssim_weighted_pred_err;
double modified_err; double modified_err;
@ -238,7 +228,7 @@ int frame_max_bits(VP8_COMP *cpi)
else else
{ {
// For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user // 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 // Trap case where we are out of bits
@ -248,13 +238,31 @@ int frame_max_bits(VP8_COMP *cpi)
return max_bits; 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) FIRSTPASS_STATS *stats)
{ {
struct vpx_codec_cx_pkt pkt; struct vpx_codec_cx_pkt pkt;
pkt.kind = VPX_CODEC_STATS_PKT; pkt.kind = VPX_CODEC_STATS_PKT;
pkt.data.twopass_stats.buf = stats; 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); vpx_codec_pkt_list_add(pktlist, &pkt);
// TEMP debug code // TEMP debug code
@ -280,16 +288,24 @@ void vp8_output_stats(struct vpx_codec_pkt_list *pktlist,
stats->mv_in_out_count, stats->mv_in_out_count,
stats->count); stats->count);
fclose(fpfile); fclose(fpfile);
fpfile = fopen("fpmotionmap.stt", "a");
fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, fpfile);
fclose(fpfile);
} }
#endif #endif
} }
int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps) 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) if (cpi->stats_in >= cpi->stats_in_end)
return EOF; return EOF;
*fps = *cpi->stats_in++; *fps = *cpi->stats_in;
cpi->stats_in = (void*)((char *)cpi->stats_in + stats_sz);
return 1; return 1;
} }
@ -352,59 +368,47 @@ void vp8_avg_stats(FIRSTPASS_STATS *section)
section->duration /= section->count; 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; int Offset;
if (cpi->fp_motion_mapfile) cpi->fp_motion_map_stats = target_pos;
{
Offset = ftell(cpi->fp_motion_mapfile) - target_pos;
fseek(cpi->fp_motion_mapfile, (int) - Offset, SEEK_CUR);
}
} }
void vp8_advance_fpmm(VP8_COMP *cpi, int count) void vp8_advance_fpmm(VP8_COMP *cpi, int count)
{ {
#if FIRSTPASS_MM cpi->fp_motion_map_stats = (void*)((char*)cpi->fp_motion_map_stats +
fseek(cpi->fp_motion_mapfile, (int)(count * cpi->common.MBs), SEEK_CUR); count * vp8_firstpass_stats_sz(cpi->common.MBs));
#endif
} }
void vp8_input_fpmm(VP8_COMP *cpi) void vp8_input_fpmm(VP8_COMP *cpi)
{ {
#if FIRSTPASS_MM unsigned char *fpmm = cpi->fp_motion_map;
int MBs = cpi->common.MBs; int MBs = cpi->common.MBs;
int max_frames = cpi->active_arnr_frames; int max_frames = cpi->active_arnr_frames;
int i;
if (!cpi->fp_motion_mapfile) for (i=0; i<max_frames; i++)
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)
{ {
// Read error char *motion_map = (char*)cpi->fp_motion_map_stats
return; + sizeof(FIRSTPASS_STATS);
memcpy(fpmm, motion_map, MBs);
fpmm += MBs;
vp8_advance_fpmm(cpi, 1);
} }
// Flag the use of weights in the temporal filter // Flag the use of weights in the temporal filter
cpi->use_weighted_temporal_filter = 1; cpi->use_weighted_temporal_filter = 1;
#endif
} }
void vp8_init_first_pass(VP8_COMP *cpi) void vp8_init_first_pass(VP8_COMP *cpi)
{ {
vp8_zero_stats(&cpi->total_stats); vp8_zero_stats(cpi->total_stats);
#ifdef FIRSTPASS_MM
cpi->fp_motion_mapfile = fopen("fpmotionmap.stt", "wb");
#endif
// TEMP debug code // TEMP debug code
#ifdef OUTPUT_FPF #ifdef OUTPUT_FPF
@ -412,6 +416,8 @@ void vp8_init_first_pass(VP8_COMP *cpi)
FILE *fpfile; FILE *fpfile;
fpfile = fopen("firstpass.stt", "w"); fpfile = fopen("firstpass.stt", "w");
fclose(fpfile); fclose(fpfile);
fpfile = fopen("fpmotionmap.stt", "wb");
fclose(fpfile);
} }
#endif #endif
@ -419,16 +425,10 @@ void vp8_init_first_pass(VP8_COMP *cpi)
void vp8_end_first_pass(VP8_COMP *cpi) void vp8_end_first_pass(VP8_COMP *cpi)
{ {
vp8_output_stats(cpi->output_pkt_list, &cpi->total_stats); vp8_output_stats(cpi, cpi->output_pkt_list, cpi->total_stats);
#if FIRSTPASS_MM
if (cpi->fp_motion_mapfile)
fclose(cpi->fp_motion_mapfile);
#endif
} }
void vp8_zz_motion_search( VP8_COMP *cpi, MACROBLOCK * x, YV12_BUFFER_CONFIG * recon_buffer, int * best_motion_err, int recon_yoffset ) 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; 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; fps.duration = cpi->source_end_time_stamp - cpi->source_time_stamp;
// don't want to do outputstats with a stack variable! // don't want to do outputstats with a stack variable!
cpi->this_frame_stats = fps; memcpy(cpi->this_frame_stats,
vp8_output_stats(cpi->output_pkt_list, &cpi->this_frame_stats); &fps,
vp8_accumulate_stats(&cpi->total_stats, &fps); sizeof(FIRSTPASS_STATS));
memcpy((char*)cpi->this_frame_stats + sizeof(FIRSTPASS_STATS),
#if FIRSTPASS_MM cpi->fp_motion_map,
fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, cpi->fp_motion_mapfile); sizeof(cpi->fp_motion_map[0]) * cpi->common.MBs);
#endif 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 // Copy the previous Last Frame into the GF buffer if specific conditions for doing so are met
if ((cm->current_video_frame > 0) && if ((cm->current_video_frame > 0) &&
(cpi->this_frame_stats.pcnt_inter > 0.20) && (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->intra_error / cpi->this_frame_stats->coded_error) > 2.0))
{ {
vp8_yv12_copy_frame_ptr(lst_yv12, gld_yv12); 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); 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) if (!cpi->stats_in_end)
return; 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_error_left = cpi->total_stats->ssim_weighted_pred_err;
cpi->total_intra_error_left = cpi->total_stats.intra_error; cpi->total_intra_error_left = cpi->total_stats->intra_error;
cpi->total_coded_error_left = cpi->total_stats.coded_error; cpi->total_coded_error_left = cpi->total_stats->coded_error;
cpi->start_tot_err_left = cpi->total_error_left; 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 * 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 * 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 // 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 // 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. // 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 // Its calculated based on the actual durations of all frames from the first
// pass. // 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->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 * 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 * 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 // 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; 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 file position
reset_fpf_position(cpi, start_pos); reset_fpf_position(cpi, start_pos);
@ -1184,21 +1185,11 @@ void vp8_init_second_pass(VP8_COMP *cpi)
} }
#if FIRSTPASS_MM cpi->fp_motion_map_stats = (unsigned char *)cpi->stats_in;
cpi->fp_motion_mapfile = 0;
cpi->fp_motion_mapfile = fopen("fpmotionmap.stt", "rb");
#endif
} }
void vp8_end_second_pass(VP8_COMP *cpi) 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 . // 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 int max_bits = frame_max_bits(cpi); // Max for a single frame
#if FIRSTPASS_MM unsigned char *fpmm_pos;
int fpmm_pos;
#endif
cpi->gf_group_bits = 0; cpi->gf_group_bits = 0;
cpi->gf_decay_rate = 0; cpi->gf_decay_rate = 0;
vp8_clear_system_state(); //__asm emms; vp8_clear_system_state(); //__asm emms;
#if FIRSTPASS_MM
fpmm_pos = vp8_fpmm_get_pos(cpi); fpmm_pos = vp8_fpmm_get_pos(cpi);
#endif
start_pos = cpi->stats_in; 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 // Note: this_frame->frame has been updated in the loop
// so it now points at the ARF frame. // so it now points at the ARF frame.
half_gf_int = cpi->baseline_gf_interval >> 1; 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) 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; cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
#if FIRSTPASS_MM
{ {
// Advance to & read in the motion map for those frames // Advance to & read in the motion map for those frames
// to be considered for filtering based on the position // to be considered for filtering based on the position
// of the ARF // 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 // Position at the 'earliest' frame to be filtered
vp8_advance_fpmm(cpi, 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 // Read / create a motion map for the region of interest
vp8_input_fpmm(cpi); vp8_input_fpmm(cpi);
} }
#endif
} }
else 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. // 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. // 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. // 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; 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); reset_fpf_position(cpi, start_pos);
} }
#if FIRSTPASS_MM
// Reset the First pass motion map file position // Reset the First pass motion map file position
vp8_fpmm_reset_pos(cpi, fpmm_pos); 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. // 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 int max_bits = frame_max_bits(cpi); // Max for a single frame
// The final few frames have special treatment // 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;; 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) void vp8_second_pass(VP8_COMP *cpi)
{ {
int tmp_q; 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;
FIRSTPASS_STATS this_frame_copy; FIRSTPASS_STATS this_frame_copy;
@ -1866,14 +1849,12 @@ void vp8_second_pass(VP8_COMP *cpi)
if (EOF == vp8_input_stats(cpi, &this_frame)) if (EOF == vp8_input_stats(cpi, &this_frame))
return; return;
#if FIRSTPASS_MM
vpx_memset(cpi->fp_motion_map, 0, vpx_memset(cpi->fp_motion_map, 0,
cpi->oxcf.arnr_max_frames*cpi->common.MBs); 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 // Step over this frame's first pass motion map
vp8_advance_fpmm(cpi, 1); vp8_advance_fpmm(cpi, 1);
#endif
this_frame_error = this_frame.ssim_weighted_pred_err; this_frame_error = this_frame.ssim_weighted_pred_err;
this_frame_intra_error = this_frame.intra_error; 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; cpi->common.vert_scale = NORMAL;
// Calculate Average bits per frame. // 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); av_bits_per_frame = cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate);
//if ( av_bits_per_frame < 0.0 ) //if ( av_bits_per_frame < 0.0 )
// 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 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_spend = cpi->oxcf.starting_buffer_level - cpi->buffer_level;
long long over_spend2 = cpi->oxcf.starting_buffer_level - projected_buffer_level; long long over_spend2 = cpi->oxcf.starting_buffer_level - projected_buffer_level;

View File

@ -20,4 +20,5 @@ extern void vp8_init_second_pass(VP8_COMP *cpi);
extern void vp8_second_pass(VP8_COMP *cpi); extern void vp8_second_pass(VP8_COMP *cpi);
extern void vp8_end_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 #endif

View File

@ -330,6 +330,8 @@ void vp8_dealloc_compressor_data(VP8_COMP *cpi)
cpi->mb.pip = 0; cpi->mb.pip = 0;
vpx_free(cpi->total_stats);
vpx_free(cpi->this_frame_stats);
} }
static void enable_segmentation(VP8_PTR ptr) 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)); 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->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) 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 = oxcf->two_pass_stats_in.buf;
cpi->stats_in_end = cpi->stats_in cpi->stats_in_end = (void*)((char *)cpi->stats_in
+ oxcf->two_pass_stats_in.sz / sizeof(FIRSTPASS_STATS) + (packets - 1) * packet_sz);
- 1;
vp8_init_second_pass(cpi); vp8_init_second_pass(cpi);
} }
@ -3481,7 +3491,7 @@ static void apply_temporal_filter
modifier = 16 - modifier; modifier = 16 - modifier;
#endif #endif
modifier *= filter_weight; modifier *= filter_weight;
count[k] += modifier; count[k] += modifier;
accumulator[k] += modifier * pixel_value; accumulator[k] += modifier * pixel_value;
@ -3656,7 +3666,7 @@ static void vp8cx_temp_blur1_c
YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index]; YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
unsigned char *dst1, *dst2; unsigned char *dst1, *dst2;
DECLARE_ALIGNED(16, unsigned char, predictor[384]); DECLARE_ALIGNED(16, unsigned char, predictor[384]);
// Save input state // Save input state
unsigned char *y_buffer = mbd->pre.y_buffer; unsigned char *y_buffer = mbd->pre.y_buffer;
unsigned char *u_buffer = mbd->pre.u_buffer; unsigned char *u_buffer = mbd->pre.u_buffer;

View File

@ -461,14 +461,14 @@ typedef struct
int target_bandwidth; int target_bandwidth;
long long bits_left; long long bits_left;
FIRSTPASS_STATS total_stats; FIRSTPASS_STATS *total_stats;
FIRSTPASS_STATS this_frame_stats; FIRSTPASS_STATS *this_frame_stats;
FIRSTPASS_STATS *stats_in, *stats_in_end; FIRSTPASS_STATS *stats_in, *stats_in_end;
struct vpx_codec_pkt_list *output_pkt_list; struct vpx_codec_pkt_list *output_pkt_list;
int first_pass_done; int first_pass_done;
unsigned char *fp_motion_map; 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 #if 0
// Experimental code for lagged and one pass // Experimental code for lagged and one pass

View File

@ -14,6 +14,7 @@
#include "vpx_version.h" #include "vpx_version.h"
#include "onyx_int.h" #include "onyx_int.h"
#include "vpx/vp8e.h" #include "vpx/vp8e.h"
#include "vp8/encoder/firstpass.h"
#include "onyx.h" #include "onyx.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.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) if (cfg->g_pass == VPX_RC_LAST_PASS)
{ {
int n_doubles = cfg->rc_twopass_stats_in.sz / sizeof(double); int mb_r = (cfg->g_h + 15) / 16;
int n_packets = cfg->rc_twopass_stats_in.sz / sizeof(FIRSTPASS_STATS); int mb_c = (cfg->g_w + 15) / 16;
double frames; 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) if (!cfg->rc_twopass_stats_in.buf)
ERROR("rc_twopass_stats_in.buf not set."); 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."); 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."); 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"); ERROR("rc_twopass_stats_in missing EOS stats packet");
} }