2010-05-18 19:58:33 +04:00
/*
2010-09-09 16:16:39 +04:00
* Copyright ( c ) 2010 The WebM project authors . All Rights Reserved .
2010-05-18 19:58:33 +04:00
*
2010-06-18 20:39:21 +04:00
* Use of this source code is governed by a BSD - style license
2010-06-05 00:19:40 +04:00
* that can be found in the LICENSE file in the root of the source
* tree . An additional intellectual property rights grant can be found
2010-06-18 20:39:21 +04:00
* in the file PATENTS . All contributing project authors may
2010-06-05 00:19:40 +04:00
* be found in the AUTHORS file in the root of the source tree .
2010-05-18 19:58:33 +04:00
*/
# include "math.h"
# include "limits.h"
# include "block.h"
# include "onyx_int.h"
# include "variance.h"
# include "encodeintra.h"
2011-02-10 22:41:38 +03:00
# include "vp8/common/setupintrarecon.h"
2010-05-18 19:58:33 +04:00
# include "mcomp.h"
2011-06-28 20:29:47 +04:00
# include "firstpass.h"
2010-05-18 19:58:33 +04:00
# include "vpx_scale/vpxscale.h"
# include "encodemb.h"
2011-02-10 22:41:38 +03:00
# include "vp8/common/extend.h"
# include "vp8/common/systemdependent.h"
2010-05-18 19:58:33 +04:00
# include "vpx_scale/yv12extend.h"
# include "vpx_mem/vpx_mem.h"
2011-02-10 22:41:38 +03:00
# include "vp8/common/swapyv12buffer.h"
2010-05-18 19:58:33 +04:00
# include <stdio.h>
# include "rdopt.h"
2011-02-10 22:41:38 +03:00
# include "vp8/common/quant_common.h"
2010-05-18 19:58:33 +04:00
# include "encodemv.h"
//#define OUTPUT_FPF 1
extern void vp8_build_block_offsets ( MACROBLOCK * x ) ;
extern void vp8_setup_block_ptrs ( MACROBLOCK * x ) ;
extern void vp8cx_frame_init_quantizer ( VP8_COMP * cpi ) ;
2011-05-12 18:50:16 +04:00
extern void vp8_set_mbmode_and_mvs ( MACROBLOCK * x , MB_PREDICTION_MODE mb , int_mv * mv ) ;
2010-05-18 19:58:33 +04:00
extern void vp8_alloc_compressor_data ( VP8_COMP * cpi ) ;
//#define GFQ_ADJUSTMENT (40 + ((15*Q)/10))
//#define GFQ_ADJUSTMENT (80 + ((15*Q)/10))
# define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
extern int vp8_kf_boost_qadjustment [ QINDEX_RANGE ] ;
extern const int vp8_gf_boost_qadjustment [ QINDEX_RANGE ] ;
2011-06-28 20:29:47 +04:00
# define IIFACTOR 1.5
2010-05-18 19:58:33 +04:00
# define IIKFACTOR1 1.40
# define IIKFACTOR2 1.5
2011-01-04 20:55:49 +03:00
# define RMAX 14.0
# define GF_RMAX 48.0
2010-05-18 19:58:33 +04:00
2011-01-04 20:55:49 +03:00
# define KF_MB_INTRA_MIN 300
# define GF_MB_INTRA_MIN 200
2011-01-07 21:29:37 +03:00
2010-05-18 19:58:33 +04:00
# define DOUBLE_DIVIDE_CHECK(X) ((X)<0?(X)-.000001:(X)+.000001)
# define POW1 (double)cpi->oxcf.two_pass_vbrbias / 100.0
# define POW2 (double)cpi->oxcf.two_pass_vbrbias / 100.0
2011-06-28 20:29:47 +04:00
# define NEW_BOOST 1
2010-05-18 19:58:33 +04:00
static int vscale_lookup [ 7 ] = { 0 , 1 , 1 , 2 , 2 , 3 , 3 } ;
static int hscale_lookup [ 7 ] = { 0 , 0 , 1 , 1 , 2 , 2 , 3 } ;
2011-01-07 21:29:37 +03:00
2011-03-18 00:07:59 +03:00
static const int cq_level [ QINDEX_RANGE ] =
2011-01-07 21:29:37 +03:00
{
0 , 0 , 1 , 1 , 2 , 3 , 3 , 4 , 4 , 5 , 6 , 6 , 7 , 8 , 8 , 9 ,
9 , 10 , 11 , 11 , 12 , 13 , 13 , 14 , 15 , 15 , 16 , 17 , 17 , 18 , 19 , 20 ,
20 , 21 , 22 , 22 , 23 , 24 , 24 , 25 , 26 , 27 , 27 , 28 , 29 , 30 , 30 , 31 ,
32 , 33 , 33 , 34 , 35 , 36 , 36 , 37 , 38 , 39 , 39 , 40 , 41 , 42 , 42 , 43 ,
44 , 45 , 46 , 46 , 47 , 48 , 49 , 50 , 50 , 51 , 52 , 53 , 54 , 55 , 55 , 56 ,
57 , 58 , 59 , 60 , 60 , 61 , 62 , 63 , 64 , 65 , 66 , 67 , 67 , 68 , 69 , 70 ,
71 , 72 , 73 , 74 , 75 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 ,
86 , 86 , 87 , 88 , 89 , 90 , 91 , 92 , 93 , 94 , 95 , 96 , 97 , 98 , 99 , 100
} ;
2011-03-18 00:07:59 +03:00
static void find_next_key_frame ( VP8_COMP * cpi , FIRSTPASS_STATS * this_frame ) ;
2010-05-18 19:58:33 +04:00
// Resets the first pass file to the given position using a relative seek from the current position
static void reset_fpf_position ( VP8_COMP * cpi , FIRSTPASS_STATS * Position )
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . stats_in = Position ;
2010-05-18 19:58:33 +04:00
}
static int lookup_next_frame_stats ( VP8_COMP * cpi , FIRSTPASS_STATS * next_frame )
{
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . stats_in > = cpi - > twopass . stats_in_end )
2010-05-18 19:58:33 +04:00
return EOF ;
2011-05-20 01:16:39 +04:00
* next_frame = * cpi - > twopass . stats_in ;
2010-05-18 19:58:33 +04:00
return 1 ;
}
2011-06-28 20:29:47 +04:00
// Read frame stats at an offset from the current position
static int read_frame_stats ( VP8_COMP * cpi ,
FIRSTPASS_STATS * frame_stats ,
int offset )
{
FIRSTPASS_STATS * fps_ptr = cpi - > twopass . stats_in ;
// Check legality of offset
if ( offset > = 0 )
{
if ( & fps_ptr [ offset ] > = cpi - > twopass . stats_in_end )
return EOF ;
}
else if ( offset < 0 )
{
if ( & fps_ptr [ offset ] < cpi - > twopass . stats_in_start )
return EOF ;
}
* frame_stats = fps_ptr [ offset ] ;
return 1 ;
}
static int input_stats ( VP8_COMP * cpi , FIRSTPASS_STATS * fps )
{
if ( cpi - > twopass . stats_in > = cpi - > twopass . stats_in_end )
return EOF ;
* fps = * cpi - > twopass . stats_in ;
cpi - > twopass . stats_in =
( void * ) ( ( char * ) cpi - > twopass . stats_in + sizeof ( FIRSTPASS_STATS ) ) ;
return 1 ;
}
static void 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 ( FIRSTPASS_STATS ) ;
vpx_codec_pkt_list_add ( pktlist , & pkt ) ;
// TEMP debug code
# if OUTPUT_FPF
{
FILE * fpfile ;
fpfile = fopen ( " firstpass.stt " , " a " ) ;
fprintf ( fpfile , " %12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f "
" %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f "
2011-09-15 17:36:24 +04:00
" %12.0f %12.0f %12.4f \n " ,
2011-06-28 20:29:47 +04:00
stats - > frame ,
stats - > intra_error ,
stats - > coded_error ,
stats - > ssim_weighted_pred_err ,
stats - > pcnt_inter ,
stats - > pcnt_motion ,
stats - > pcnt_second_ref ,
stats - > pcnt_neutral ,
stats - > MVr ,
stats - > mvr_abs ,
stats - > MVc ,
stats - > mvc_abs ,
stats - > MVrv ,
stats - > MVcv ,
stats - > mv_in_out_count ,
2011-09-15 17:36:24 +04:00
stats - > new_mv_count ,
2011-06-28 20:29:47 +04:00
stats - > count ,
stats - > duration ) ;
fclose ( fpfile ) ;
}
# endif
}
static void zero_stats ( FIRSTPASS_STATS * section )
{
section - > frame = 0.0 ;
section - > intra_error = 0.0 ;
section - > coded_error = 0.0 ;
section - > ssim_weighted_pred_err = 0.0 ;
section - > pcnt_inter = 0.0 ;
section - > pcnt_motion = 0.0 ;
section - > pcnt_second_ref = 0.0 ;
section - > pcnt_neutral = 0.0 ;
section - > MVr = 0.0 ;
section - > mvr_abs = 0.0 ;
section - > MVc = 0.0 ;
section - > mvc_abs = 0.0 ;
section - > MVrv = 0.0 ;
section - > MVcv = 0.0 ;
section - > mv_in_out_count = 0.0 ;
2011-09-15 17:36:24 +04:00
section - > new_mv_count = 0.0 ;
2011-06-28 20:29:47 +04:00
section - > count = 0.0 ;
section - > duration = 1.0 ;
}
static void accumulate_stats ( FIRSTPASS_STATS * section , FIRSTPASS_STATS * frame )
{
section - > frame + = frame - > frame ;
section - > intra_error + = frame - > intra_error ;
section - > coded_error + = frame - > coded_error ;
section - > ssim_weighted_pred_err + = frame - > ssim_weighted_pred_err ;
section - > pcnt_inter + = frame - > pcnt_inter ;
section - > pcnt_motion + = frame - > pcnt_motion ;
section - > pcnt_second_ref + = frame - > pcnt_second_ref ;
section - > pcnt_neutral + = frame - > pcnt_neutral ;
section - > MVr + = frame - > MVr ;
section - > mvr_abs + = frame - > mvr_abs ;
section - > MVc + = frame - > MVc ;
section - > mvc_abs + = frame - > mvc_abs ;
section - > MVrv + = frame - > MVrv ;
section - > MVcv + = frame - > MVcv ;
section - > mv_in_out_count + = frame - > mv_in_out_count ;
2011-09-15 17:36:24 +04:00
section - > new_mv_count + = frame - > new_mv_count ;
2011-06-28 20:29:47 +04:00
section - > count + = frame - > count ;
section - > duration + = frame - > duration ;
}
2011-09-15 17:36:24 +04:00
static void subtract_stats ( FIRSTPASS_STATS * section , FIRSTPASS_STATS * frame )
{
section - > frame - = frame - > frame ;
section - > intra_error - = frame - > intra_error ;
section - > coded_error - = frame - > coded_error ;
section - > ssim_weighted_pred_err - = frame - > ssim_weighted_pred_err ;
section - > pcnt_inter - = frame - > pcnt_inter ;
section - > pcnt_motion - = frame - > pcnt_motion ;
section - > pcnt_second_ref - = frame - > pcnt_second_ref ;
section - > pcnt_neutral - = frame - > pcnt_neutral ;
section - > MVr - = frame - > MVr ;
section - > mvr_abs - = frame - > mvr_abs ;
section - > MVc - = frame - > MVc ;
section - > mvc_abs - = frame - > mvc_abs ;
section - > MVrv - = frame - > MVrv ;
section - > MVcv - = frame - > MVcv ;
section - > mv_in_out_count - = frame - > mv_in_out_count ;
section - > new_mv_count - = frame - > new_mv_count ;
section - > count - = frame - > count ;
section - > duration - = frame - > duration ;
}
2011-06-28 20:29:47 +04:00
static void avg_stats ( FIRSTPASS_STATS * section )
{
if ( section - > count < 1.0 )
return ;
section - > intra_error / = section - > count ;
section - > coded_error / = section - > count ;
section - > ssim_weighted_pred_err / = section - > count ;
section - > pcnt_inter / = section - > count ;
section - > pcnt_second_ref / = section - > count ;
section - > pcnt_neutral / = section - > count ;
section - > pcnt_motion / = section - > count ;
section - > MVr / = section - > count ;
section - > mvr_abs / = section - > count ;
section - > MVc / = section - > count ;
section - > mvc_abs / = section - > count ;
section - > MVrv / = section - > count ;
section - > MVcv / = section - > count ;
section - > mv_in_out_count / = section - > count ;
section - > duration / = section - > count ;
}
2010-05-18 19:58:33 +04:00
// 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 )
{
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
double av_err = ( cpi - > twopass . total_stats . ssim_weighted_pred_err /
cpi - > twopass . total_stats . count ) ;
2010-05-18 19:58:33 +04:00
double this_err = this_frame - > ssim_weighted_pred_err ;
double modified_err ;
if ( this_err > av_err )
modified_err = av_err * pow ( ( this_err / DOUBLE_DIVIDE_CHECK ( av_err ) ) , POW1 ) ;
else
modified_err = av_err * pow ( ( this_err / DOUBLE_DIVIDE_CHECK ( av_err ) ) , POW2 ) ;
return modified_err ;
}
2011-01-27 00:42:56 +03:00
static const double weight_table [ 256 ] = {
0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 ,
0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 ,
0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 ,
0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 , 0.020000 ,
0.020000 , 0.031250 , 0.062500 , 0.093750 , 0.125000 , 0.156250 , 0.187500 , 0.218750 ,
0.250000 , 0.281250 , 0.312500 , 0.343750 , 0.375000 , 0.406250 , 0.437500 , 0.468750 ,
0.500000 , 0.531250 , 0.562500 , 0.593750 , 0.625000 , 0.656250 , 0.687500 , 0.718750 ,
0.750000 , 0.781250 , 0.812500 , 0.843750 , 0.875000 , 0.906250 , 0.937500 , 0.968750 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 ,
1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000 , 1.000000
} ;
2011-03-18 00:07:59 +03:00
static double simple_weight ( YV12_BUFFER_CONFIG * source )
2010-05-18 19:58:33 +04:00
{
int i , j ;
unsigned char * src = source - > y_buffer ;
double sum_weights = 0.0 ;
// Loop throught the Y plane raw examining levels and creating a weight for the image
2011-01-27 00:42:56 +03:00
i = source - > y_height ;
do
2010-05-18 19:58:33 +04:00
{
2011-01-27 00:42:56 +03:00
j = source - > y_width ;
do
2010-05-18 19:58:33 +04:00
{
2011-01-27 00:42:56 +03:00
sum_weights + = weight_table [ * src ] ;
src + + ;
} while ( - - j ) ;
src - = source - > y_width ;
2010-05-18 19:58:33 +04:00
src + = source - > y_stride ;
2011-01-27 00:42:56 +03:00
} while ( - - i ) ;
2010-05-18 19:58:33 +04:00
sum_weights / = ( source - > y_height * source - > y_width ) ;
return sum_weights ;
}
2011-01-27 00:42:56 +03:00
2010-05-18 19:58:33 +04:00
// This function returns the current per frame maximum bitrate target
2011-03-18 00:07:59 +03:00
static int frame_max_bits ( VP8_COMP * cpi )
2010-05-18 19:58:33 +04:00
{
// Max allocation for a single frame based on the max section guidelines passed in and how many bits are left
int max_bits ;
// For CBR we need to also consider buffer fullness.
2011-08-12 22:51:36 +04:00
// If we are running below the optimal level then we need to gradually tighten up on max_bits.
2010-05-18 19:58:33 +04:00
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
2011-08-12 22:51:36 +04:00
double buffer_fullness_ratio = ( double ) cpi - > buffer_level / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > oxcf . optimal_buffer_level ) ;
2010-05-18 19:58:33 +04:00
2011-08-12 22:51:36 +04:00
// For CBR base this on the target average bits per frame plus the maximum sedction rate passed in by the user
max_bits = ( int ) ( cpi - > av_per_frame_bandwidth * ( ( double ) cpi - > oxcf . two_pass_vbrmax_section / 100.0 ) ) ;
2010-05-18 19:58:33 +04:00
2011-08-12 22:51:36 +04:00
// If our buffer is below the optimum level
if ( buffer_fullness_ratio < 1.0 )
{
// The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4.
int min_max_bits = ( ( cpi - > av_per_frame_bandwidth > > 2 ) < ( max_bits > > 2 ) ) ? cpi - > av_per_frame_bandwidth > > 2 : max_bits > > 2 ;
2010-05-18 19:58:33 +04:00
2011-08-12 22:51:36 +04:00
max_bits = ( int ) ( max_bits * buffer_fullness_ratio ) ;
2010-05-18 19:58:33 +04:00
2011-08-12 22:51:36 +04:00
if ( max_bits < min_max_bits )
max_bits = min_max_bits ; // Lowest value we will set ... which should allow the buffer to refil.
2010-05-18 19:58:33 +04:00
}
}
2011-08-12 22:51:36 +04:00
// VBR
2010-05-18 19:58:33 +04:00
else
{
// For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
max_bits = ( int ) ( ( ( double ) cpi - > twopass . bits_left / ( cpi - > twopass . total_stats . count - ( double ) cpi - > common . current_video_frame ) ) * ( ( double ) cpi - > oxcf . two_pass_vbrmax_section / 100.0 ) ) ;
2010-05-18 19:58:33 +04:00
}
// Trap case where we are out of bits
if ( max_bits < 0 )
max_bits = 0 ;
return max_bits ;
}
void vp8_init_first_pass ( VP8_COMP * cpi )
{
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
zero_stats ( & cpi - > twopass . total_stats ) ;
2010-05-18 19:58:33 +04:00
}
void vp8_end_first_pass ( VP8_COMP * cpi )
{
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
output_stats ( cpi , cpi - > output_pkt_list , & cpi - > twopass . total_stats ) ;
2010-10-15 00:40:12 +04:00
}
2010-05-18 19:58:33 +04:00
2011-03-18 00:07:59 +03:00
static void zz_motion_search ( VP8_COMP * cpi , MACROBLOCK * x , YV12_BUFFER_CONFIG * recon_buffer , int * best_motion_err , int recon_yoffset )
2010-05-18 19:58:33 +04:00
{
MACROBLOCKD * const xd = & x - > e_mbd ;
BLOCK * b = & x - > block [ 0 ] ;
BLOCKD * d = & x - > e_mbd . block [ 0 ] ;
unsigned char * src_ptr = ( * ( b - > base_src ) + b - > src ) ;
int src_stride = b - > src_stride ;
unsigned char * ref_ptr ;
2012-01-20 22:52:16 +04:00
int ref_stride = x - > e_mbd . pre . y_stride ;
2010-05-18 19:58:33 +04:00
// Set up pointers for this macro block recon buffer
xd - > pre . y_buffer = recon_buffer - > y_buffer + recon_yoffset ;
2012-01-20 22:52:16 +04:00
ref_ptr = ( unsigned char * ) ( xd - > pre . y_buffer + d - > offset ) ;
2010-05-18 19:58:33 +04:00
2012-01-13 04:55:44 +04:00
vp8_mse16x16 ( src_ptr , src_stride , ref_ptr , ref_stride , ( unsigned int * ) ( best_motion_err ) ) ;
2010-05-18 19:58:33 +04:00
}
2011-05-12 18:50:16 +04:00
static void first_pass_motion_search ( VP8_COMP * cpi , MACROBLOCK * x ,
int_mv * ref_mv , MV * best_mv ,
YV12_BUFFER_CONFIG * recon_buffer ,
int * best_motion_err , int recon_yoffset )
2010-05-18 19:58:33 +04:00
{
MACROBLOCKD * const xd = & x - > e_mbd ;
BLOCK * b = & x - > block [ 0 ] ;
BLOCKD * d = & x - > e_mbd . block [ 0 ] ;
int num00 ;
2011-05-12 18:50:16 +04:00
int_mv tmp_mv ;
2011-07-07 19:21:41 +04:00
int_mv ref_mv_full ;
2010-05-18 19:58:33 +04:00
int tmp_err ;
int step_param = 3 ; //3; // Dont search over full range for first pass
int further_steps = ( MAX_MVSEARCH_STEPS - 1 ) - step_param ; //3;
int n ;
2010-10-26 23:34:16 +04:00
vp8_variance_fn_ptr_t v_fn_ptr = cpi - > fn_ptr [ BLOCK_16X16 ] ;
2010-05-18 19:58:33 +04:00
int new_mv_mode_penalty = 256 ;
2010-10-26 23:34:16 +04:00
// override the default variance function to use MSE
2012-01-13 04:55:44 +04:00
v_fn_ptr . vf = vp8_mse16x16 ;
2010-05-18 19:58:33 +04:00
// Set up pointers for this macro block recon buffer
xd - > pre . y_buffer = recon_buffer - > y_buffer + recon_yoffset ;
// Initial step/diamond search centred on best mv
2011-05-12 18:50:16 +04:00
tmp_mv . as_int = 0 ;
2011-07-07 19:21:41 +04:00
ref_mv_full . as_mv . col = ref_mv - > as_mv . col > > 3 ;
ref_mv_full . as_mv . row = ref_mv - > as_mv . row > > 3 ;
tmp_err = cpi - > diamond_search_sad ( x , b , d , & ref_mv_full , & tmp_mv , step_param ,
2011-06-01 22:41:05 +04:00
x - > sadperbit16 , & num00 , & v_fn_ptr ,
x - > mvcost , ref_mv ) ;
2010-05-18 19:58:33 +04:00
if ( tmp_err < INT_MAX - new_mv_mode_penalty )
tmp_err + = new_mv_mode_penalty ;
if ( tmp_err < * best_motion_err )
{
* best_motion_err = tmp_err ;
2011-05-12 18:50:16 +04:00
best_mv - > row = tmp_mv . as_mv . row ;
best_mv - > col = tmp_mv . as_mv . col ;
2010-05-18 19:58:33 +04:00
}
// Further step/diamond searches as necessary
n = num00 ;
num00 = 0 ;
while ( n < further_steps )
{
n + + ;
if ( num00 )
num00 - - ;
else
{
2011-07-07 19:21:41 +04:00
tmp_err = cpi - > diamond_search_sad ( x , b , d , & ref_mv_full , & tmp_mv ,
2011-06-01 22:41:05 +04:00
step_param + n , x - > sadperbit16 ,
& num00 , & v_fn_ptr , x - > mvcost ,
ref_mv ) ;
2010-05-18 19:58:33 +04:00
if ( tmp_err < INT_MAX - new_mv_mode_penalty )
tmp_err + = new_mv_mode_penalty ;
if ( tmp_err < * best_motion_err )
{
* best_motion_err = tmp_err ;
2011-05-12 18:50:16 +04:00
best_mv - > row = tmp_mv . as_mv . row ;
best_mv - > col = tmp_mv . as_mv . col ;
2010-05-18 19:58:33 +04:00
}
}
}
}
void vp8_first_pass ( VP8_COMP * cpi )
{
int mb_row , mb_col ;
MACROBLOCK * const x = & cpi - > mb ;
VP8_COMMON * const cm = & cpi - > common ;
MACROBLOCKD * const xd = & x - > e_mbd ;
int recon_yoffset , recon_uvoffset ;
2010-07-22 16:07:32 +04:00
YV12_BUFFER_CONFIG * lst_yv12 = & cm - > yv12_fb [ cm - > lst_fb_idx ] ;
YV12_BUFFER_CONFIG * new_yv12 = & cm - > yv12_fb [ cm - > new_fb_idx ] ;
YV12_BUFFER_CONFIG * gld_yv12 = & cm - > yv12_fb [ cm - > gld_fb_idx ] ;
int recon_y_stride = lst_yv12 - > y_stride ;
int recon_uv_stride = lst_yv12 - > uv_stride ;
2011-07-26 05:44:59 +04:00
int64_t intra_error = 0 ;
int64_t coded_error = 0 ;
2010-05-18 19:58:33 +04:00
int sum_mvr = 0 , sum_mvc = 0 ;
int sum_mvr_abs = 0 , sum_mvc_abs = 0 ;
int sum_mvrs = 0 , sum_mvcs = 0 ;
int mvcount = 0 ;
int intercount = 0 ;
int second_ref_count = 0 ;
int intrapenalty = 256 ;
2011-03-07 18:58:07 +03:00
int neutral_count = 0 ;
2011-09-15 17:36:24 +04:00
int new_mv_count = 0 ;
2010-05-18 19:58:33 +04:00
int sum_in_vectors = 0 ;
2011-09-15 17:36:24 +04:00
uint32_t lastmv_as_int = 0 ;
2010-05-18 19:58:33 +04:00
2011-05-12 18:50:16 +04:00
int_mv zero_ref_mv ;
zero_ref_mv . as_int = 0 ;
2010-05-18 19:58:33 +04:00
vp8_clear_system_state ( ) ; //__asm emms;
x - > src = * cpi - > Source ;
2010-07-22 16:07:32 +04:00
xd - > pre = * lst_yv12 ;
xd - > dst = * new_yv12 ;
2010-05-18 19:58:33 +04:00
2010-09-03 00:17:52 +04:00
x - > partition_info = x - > pi ;
2010-08-13 00:25:43 +04:00
xd - > mode_info_context = cm - > mi ;
2010-05-18 19:58:33 +04:00
vp8_build_block_offsets ( x ) ;
vp8_setup_block_dptrs ( & x - > e_mbd ) ;
vp8_setup_block_ptrs ( x ) ;
// set up frame new frame for intra coded blocks
2010-07-22 16:07:32 +04:00
vp8_setup_intra_recon ( new_yv12 ) ;
2010-05-18 19:58:33 +04:00
vp8cx_frame_init_quantizer ( cpi ) ;
// Initialise the MV cost table to the defaults
//if( cm->current_video_frame == 0)
//if ( 0 )
{
int flag [ 2 ] = { 1 , 1 } ;
vp8_initialize_rd_consts ( cpi , vp8_dc_quant ( cm - > base_qindex , cm - > y1dc_delta_q ) ) ;
vpx_memcpy ( cm - > fc . mvc , vp8_default_mv_context , sizeof ( vp8_default_mv_context ) ) ;
2011-04-02 00:41:58 +04:00
vp8_build_component_cost_table ( cpi - > mb . mvcost , ( const MV_CONTEXT * ) cm - > fc . mvc , flag ) ;
2010-05-18 19:58:33 +04:00
}
// for each macroblock row in image
for ( mb_row = 0 ; mb_row < cm - > mb_rows ; mb_row + + )
{
2011-01-27 00:42:56 +03:00
int_mv best_ref_mv ;
best_ref_mv . as_int = 0 ;
2010-05-18 19:58:33 +04:00
// reset above block coeffs
xd - > up_available = ( mb_row ! = 0 ) ;
recon_yoffset = ( mb_row * recon_y_stride * 16 ) ;
recon_uvoffset = ( mb_row * recon_uv_stride * 8 ) ;
2011-01-27 00:42:56 +03:00
// Set up limit values for motion vectors to prevent them extending outside the UMV borders
x - > mv_row_min = - ( ( mb_row * 16 ) + ( VP8BORDERINPIXELS - 16 ) ) ;
x - > mv_row_max = ( ( cm - > mb_rows - 1 - mb_row ) * 16 ) + ( VP8BORDERINPIXELS - 16 ) ;
2010-05-18 19:58:33 +04:00
// for each macroblock col in image
for ( mb_col = 0 ; mb_col < cm - > mb_cols ; mb_col + + )
{
int this_error ;
int gf_motion_error = INT_MAX ;
int use_dc_pred = ( mb_col | | mb_row ) & & ( ! mb_col | | ! mb_row ) ;
2010-07-22 16:07:32 +04:00
xd - > dst . y_buffer = new_yv12 - > y_buffer + recon_yoffset ;
xd - > dst . u_buffer = new_yv12 - > u_buffer + recon_uvoffset ;
xd - > dst . v_buffer = new_yv12 - > v_buffer + recon_uvoffset ;
2010-05-18 19:58:33 +04:00
xd - > left_available = ( mb_col ! = 0 ) ;
2011-06-23 21:54:02 +04:00
//Copy current mb to a buffer
2012-01-13 04:55:44 +04:00
vp8_copy_mem16x16 ( x - > src . y_buffer , x - > src . y_stride , x - > thismb , 16 ) ;
2011-06-23 21:54:02 +04:00
2010-05-18 19:58:33 +04:00
// do intra 16x16 prediction
2011-06-14 14:39:06 +04:00
this_error = vp8_encode_intra ( cpi , x , use_dc_pred ) ;
2010-05-18 19:58:33 +04:00
// "intrapenalty" below deals with situations where the intra and inter error scores are very low (eg a plain black frame)
// We do not have special cases in first pass for 0,0 and nearest etc so all inter modes carry an overhead cost estimate fot the mv.
// When the error score is very low this causes us to pick all or lots of INTRA modes and throw lots of key frames.
// This penalty adds a cost matching that of a 0,0 mv to the intra case.
this_error + = intrapenalty ;
// Cumulative intra error total
2011-07-26 05:44:59 +04:00
intra_error + = ( int64_t ) this_error ;
2010-05-18 19:58:33 +04:00
// Set up limit values for motion vectors to prevent them extending outside the UMV borders
x - > mv_col_min = - ( ( mb_col * 16 ) + ( VP8BORDERINPIXELS - 16 ) ) ;
x - > mv_col_max = ( ( cm - > mb_cols - 1 - mb_col ) * 16 ) + ( VP8BORDERINPIXELS - 16 ) ;
// Other than for the first frame do a motion search
if ( cm - > current_video_frame > 0 )
{
BLOCKD * d = & x - > e_mbd . block [ 0 ] ;
MV tmp_mv = { 0 , 0 } ;
int tmp_err ;
int motion_error = INT_MAX ;
// Simple 0,0 motion with no mv overhead
2011-03-18 00:07:59 +03:00
zz_motion_search ( cpi , x , lst_yv12 , & motion_error , recon_yoffset ) ;
2010-05-18 19:58:33 +04:00
d - > bmi . mv . as_mv . row = 0 ;
d - > bmi . mv . as_mv . col = 0 ;
2010-07-01 17:17:04 +04:00
// Test last reference frame using the previous best mv as the
// starting point (best reference) for the search
2011-05-12 18:50:16 +04:00
first_pass_motion_search ( cpi , x , & best_ref_mv ,
2010-07-22 16:07:32 +04:00
& d - > bmi . mv . as_mv , lst_yv12 ,
2010-07-01 17:17:04 +04:00
& motion_error , recon_yoffset ) ;
2010-05-18 19:58:33 +04:00
// If the current best reference mv is not centred on 0,0 then do a 0,0 based search as well
2011-01-27 00:42:56 +03:00
if ( best_ref_mv . as_int )
2010-05-18 19:58:33 +04:00
{
tmp_err = INT_MAX ;
2011-03-18 00:07:59 +03:00
first_pass_motion_search ( cpi , x , & zero_ref_mv , & tmp_mv ,
2010-07-22 16:07:32 +04:00
lst_yv12 , & tmp_err , recon_yoffset ) ;
2010-05-18 19:58:33 +04:00
if ( tmp_err < motion_error )
{
motion_error = tmp_err ;
d - > bmi . mv . as_mv . row = tmp_mv . row ;
d - > bmi . mv . as_mv . col = tmp_mv . col ;
}
}
// Experimental search in a second reference frame ((0,0) based only)
if ( cm - > current_video_frame > 1 )
{
2011-03-18 00:07:59 +03:00
first_pass_motion_search ( cpi , x , & zero_ref_mv , & tmp_mv , gld_yv12 , & gf_motion_error , recon_yoffset ) ;
2010-05-18 19:58:33 +04:00
if ( ( gf_motion_error < motion_error ) & & ( gf_motion_error < this_error ) )
{
second_ref_count + + ;
//motion_error = gf_motion_error;
//d->bmi.mv.as_mv.row = tmp_mv.row;
//d->bmi.mv.as_mv.col = tmp_mv.col;
}
/*else
{
xd - > pre . y_buffer = cm - > last_frame . y_buffer + recon_yoffset ;
xd - > pre . u_buffer = cm - > last_frame . u_buffer + recon_uvoffset ;
xd - > pre . v_buffer = cm - > last_frame . v_buffer + recon_uvoffset ;
} */
// Reset to last frame as reference buffer
2010-07-22 16:07:32 +04:00
xd - > pre . y_buffer = lst_yv12 - > y_buffer + recon_yoffset ;
xd - > pre . u_buffer = lst_yv12 - > u_buffer + recon_uvoffset ;
xd - > pre . v_buffer = lst_yv12 - > v_buffer + recon_uvoffset ;
2010-05-18 19:58:33 +04:00
}
2011-01-27 00:42:56 +03:00
/* Intra assumed best */
best_ref_mv . as_int = 0 ;
2010-05-18 19:58:33 +04:00
if ( motion_error < = this_error )
{
2011-03-07 18:58:07 +03:00
// Keep a count of cases where the inter and intra were
// very close and very low. This helps with scene cut
// detection for example in cropped clips with black bars
// at the sides or top and bottom.
if ( ( ( ( this_error - intrapenalty ) * 9 ) < =
( motion_error * 10 ) ) & &
( this_error < ( 2 * intrapenalty ) ) )
{
neutral_count + + ;
}
2010-05-18 19:58:33 +04:00
d - > bmi . mv . as_mv . row < < = 3 ;
d - > bmi . mv . as_mv . col < < = 3 ;
this_error = motion_error ;
2011-05-12 18:50:16 +04:00
vp8_set_mbmode_and_mvs ( x , NEWMV , & d - > bmi . mv ) ;
2012-01-13 04:55:44 +04:00
vp8_encode_inter16x16y ( x ) ;
2010-05-18 19:58:33 +04:00
sum_mvr + = d - > bmi . mv . as_mv . row ;
sum_mvr_abs + = abs ( d - > bmi . mv . as_mv . row ) ;
sum_mvc + = d - > bmi . mv . as_mv . col ;
sum_mvc_abs + = abs ( d - > bmi . mv . as_mv . col ) ;
sum_mvrs + = d - > bmi . mv . as_mv . row * d - > bmi . mv . as_mv . row ;
sum_mvcs + = d - > bmi . mv . as_mv . col * d - > bmi . mv . as_mv . col ;
intercount + + ;
2011-01-27 00:42:56 +03:00
best_ref_mv . as_int = d - > bmi . mv . as_int ;
2010-05-18 19:58:33 +04:00
// Was the vector non-zero
2011-01-27 00:42:56 +03:00
if ( d - > bmi . mv . as_int )
2010-05-18 19:58:33 +04:00
{
mvcount + + ;
2011-09-15 17:36:24 +04:00
// Was it different from the last non zero vector
if ( d - > bmi . mv . as_int ! = lastmv_as_int )
new_mv_count + + ;
lastmv_as_int = d - > bmi . mv . as_int ;
2010-05-18 19:58:33 +04:00
// Does the Row vector point inwards or outwards
if ( mb_row < cm - > mb_rows / 2 )
{
if ( d - > bmi . mv . as_mv . row > 0 )
sum_in_vectors - - ;
else if ( d - > bmi . mv . as_mv . row < 0 )
sum_in_vectors + + ;
}
else if ( mb_row > cm - > mb_rows / 2 )
{
if ( d - > bmi . mv . as_mv . row > 0 )
sum_in_vectors + + ;
else if ( d - > bmi . mv . as_mv . row < 0 )
sum_in_vectors - - ;
}
// Does the Row vector point inwards or outwards
if ( mb_col < cm - > mb_cols / 2 )
{
if ( d - > bmi . mv . as_mv . col > 0 )
sum_in_vectors - - ;
else if ( d - > bmi . mv . as_mv . col < 0 )
sum_in_vectors + + ;
}
else if ( mb_col > cm - > mb_cols / 2 )
{
if ( d - > bmi . mv . as_mv . col > 0 )
sum_in_vectors + + ;
else if ( d - > bmi . mv . as_mv . col < 0 )
sum_in_vectors - - ;
}
2010-09-28 18:23:41 +04:00
}
2010-05-18 19:58:33 +04:00
}
}
2011-07-26 05:44:59 +04:00
coded_error + = ( int64_t ) this_error ;
2010-05-18 19:58:33 +04:00
// adjust to the next column of macroblocks
x - > src . y_buffer + = 16 ;
x - > src . u_buffer + = 8 ;
x - > src . v_buffer + = 8 ;
recon_yoffset + = 16 ;
recon_uvoffset + = 8 ;
}
// adjust to the next row of mbs
x - > src . y_buffer + = 16 * x - > src . y_stride - 16 * cm - > mb_cols ;
x - > src . u_buffer + = 8 * x - > src . uv_stride - 8 * cm - > mb_cols ;
x - > src . v_buffer + = 8 * x - > src . uv_stride - 8 * cm - > mb_cols ;
//extend the recon for intra prediction
2010-07-22 16:07:32 +04:00
vp8_extend_mb_row ( new_yv12 , xd - > dst . y_buffer + 16 , xd - > dst . u_buffer + 8 , xd - > dst . v_buffer + 8 ) ;
2010-05-18 19:58:33 +04:00
vp8_clear_system_state ( ) ; //__asm emms;
}
vp8_clear_system_state ( ) ; //__asm emms;
{
double weight = 0.0 ;
FIRSTPASS_STATS fps ;
fps . frame = cm - > current_video_frame ;
fps . intra_error = intra_error > > 8 ;
fps . coded_error = coded_error > > 8 ;
2011-03-18 00:07:59 +03:00
weight = simple_weight ( cpi - > Source ) ;
2010-05-18 19:58:33 +04:00
2011-01-27 00:42:56 +03:00
2010-05-18 19:58:33 +04:00
if ( weight < 0.1 )
weight = 0.1 ;
fps . ssim_weighted_pred_err = fps . coded_error * weight ;
fps . pcnt_inter = 0.0 ;
fps . pcnt_motion = 0.0 ;
fps . MVr = 0.0 ;
fps . mvr_abs = 0.0 ;
fps . MVc = 0.0 ;
fps . mvc_abs = 0.0 ;
fps . MVrv = 0.0 ;
fps . MVcv = 0.0 ;
fps . mv_in_out_count = 0.0 ;
2011-10-04 17:50:40 +04:00
fps . new_mv_count = 0.0 ;
2010-05-18 19:58:33 +04:00
fps . count = 1.0 ;
fps . pcnt_inter = 1.0 * ( double ) intercount / cm - > MBs ;
fps . pcnt_second_ref = 1.0 * ( double ) second_ref_count / cm - > MBs ;
2011-03-07 18:58:07 +03:00
fps . pcnt_neutral = 1.0 * ( double ) neutral_count / cm - > MBs ;
2010-05-18 19:58:33 +04:00
if ( mvcount > 0 )
{
fps . MVr = ( double ) sum_mvr / ( double ) mvcount ;
fps . mvr_abs = ( double ) sum_mvr_abs / ( double ) mvcount ;
fps . MVc = ( double ) sum_mvc / ( double ) mvcount ;
fps . mvc_abs = ( double ) sum_mvc_abs / ( double ) mvcount ;
fps . MVrv = ( ( double ) sum_mvrs - ( fps . MVr * fps . MVr / ( double ) mvcount ) ) / ( double ) mvcount ;
fps . MVcv = ( ( double ) sum_mvcs - ( fps . MVc * fps . MVc / ( double ) mvcount ) ) / ( double ) mvcount ;
fps . mv_in_out_count = ( double ) sum_in_vectors / ( double ) ( mvcount * 2 ) ;
2011-09-15 17:36:24 +04:00
fps . new_mv_count = new_mv_count ;
2010-05-18 19:58:33 +04:00
fps . pcnt_motion = 1.0 * ( double ) mvcount / cpi - > common . MBs ;
}
// TODO: handle the case when duration is set to 0, or something less
// than the full time between subsequent cpi->source_time_stamp s .
2011-04-13 22:00:18 +04:00
fps . duration = cpi - > source - > ts_end
- cpi - > source - > ts_start ;
2010-05-18 19:58:33 +04:00
2011-03-10 22:32:48 +03:00
// don't want to do output stats with a stack variable!
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
memcpy ( & cpi - > twopass . this_frame_stats ,
2010-10-15 00:40:12 +04:00
& fps ,
sizeof ( FIRSTPASS_STATS ) ) ;
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
output_stats ( cpi , cpi - > output_pkt_list , & cpi - > twopass . this_frame_stats ) ;
accumulate_stats ( & cpi - > twopass . total_stats , & fps ) ;
2010-05-18 19:58:33 +04:00
}
// Copy the previous Last Frame into the GF buffer if specific conditions for doing so are met
if ( ( cm - > current_video_frame > 0 ) & &
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
( cpi - > twopass . this_frame_stats . pcnt_inter > 0.20 ) & &
( ( cpi - > twopass . this_frame_stats . intra_error / cpi - > twopass . this_frame_stats . coded_error ) > 2.0 ) )
2010-05-18 19:58:33 +04:00
{
2010-07-22 16:07:32 +04:00
vp8_yv12_copy_frame_ptr ( lst_yv12 , gld_yv12 ) ;
2010-05-18 19:58:33 +04:00
}
// swap frame pointers so last frame refers to the frame we just compressed
2010-07-22 16:07:32 +04:00
vp8_swap_yv12_buffer ( lst_yv12 , new_yv12 ) ;
vp8_yv12_extend_frame_borders ( lst_yv12 ) ;
2010-05-18 19:58:33 +04:00
// Special case for the first frame. Copy into the GF buffer as a second reference.
if ( cm - > current_video_frame = = 0 )
{
2010-07-22 16:07:32 +04:00
vp8_yv12_copy_frame_ptr ( lst_yv12 , gld_yv12 ) ;
2010-05-18 19:58:33 +04:00
}
// use this to see what the first pass reconstruction looks like
if ( 0 )
{
char filename [ 512 ] ;
FILE * recon_file ;
sprintf ( filename , " enc%04d.yuv " , ( int ) cm - > current_video_frame ) ;
if ( cm - > current_video_frame = = 0 )
recon_file = fopen ( filename , " wb " ) ;
else
recon_file = fopen ( filename , " ab " ) ;
2010-10-28 03:04:02 +04:00
if ( fwrite ( lst_yv12 - > buffer_alloc , lst_yv12 - > frame_size , 1 , recon_file ) ) ;
2010-05-18 19:58:33 +04:00
fclose ( recon_file ) ;
}
cm - > current_video_frame + + ;
}
extern const int vp8_bits_per_mb [ 2 ] [ QINDEX_RANGE ] ;
2011-09-15 17:36:24 +04:00
// Estimate a cost per mb attributable to overheads such as the coding of
// modes and motion vectors.
// Currently simplistic in its assumptions for testing.
//
double bitcost ( double prob )
{
return - ( log ( prob ) / log ( 2.0 ) ) ;
}
2011-12-22 02:21:29 +04:00
static int64_t estimate_modemvcost ( VP8_COMP * cpi ,
2011-09-15 17:36:24 +04:00
FIRSTPASS_STATS * fpstats )
{
int mv_cost ;
int mode_cost ;
double av_pct_inter = fpstats - > pcnt_inter / fpstats - > count ;
double av_pct_motion = fpstats - > pcnt_motion / fpstats - > count ;
double av_intra = ( 1.0 - av_pct_inter ) ;
double zz_cost ;
double motion_cost ;
double intra_cost ;
zz_cost = bitcost ( av_pct_inter - av_pct_motion ) ;
motion_cost = bitcost ( av_pct_motion ) ;
intra_cost = bitcost ( av_intra ) ;
// Estimate of extra bits per mv overhead for mbs
// << 9 is the normalization to the (bits * 512) used in vp8_bits_per_mb
mv_cost = ( ( int ) ( fpstats - > new_mv_count / fpstats - > count ) * 8 ) < < 9 ;
// Crude estimate of overhead cost from modes
// << 9 is the normalization to (bits * 512) used in vp8_bits_per_mb
mode_cost =
( int ) ( ( ( ( av_pct_inter - av_pct_motion ) * zz_cost ) +
( av_pct_motion * motion_cost ) +
( av_intra * intra_cost ) ) * cpi - > common . MBs ) < < 9 ;
return mv_cost + mode_cost ;
}
static double calc_correction_factor ( double err_per_mb ,
double err_devisor ,
double pt_low ,
double pt_high ,
int Q )
{
double power_term ;
double error_term = err_per_mb / err_devisor ;
double correction_factor ;
// Adjustment based on Q to power term.
power_term = pt_low + ( Q * 0.01 ) ;
power_term = ( power_term > pt_high ) ? pt_high : power_term ;
// Adjustments to error term
// TBD
// Calculate correction factor
correction_factor = pow ( error_term , power_term ) ;
// Clip range
correction_factor =
( correction_factor < 0.05 )
? 0.05 : ( correction_factor > 5.0 ) ? 5.0 : correction_factor ;
return correction_factor ;
}
static int estimate_max_q ( VP8_COMP * cpi ,
FIRSTPASS_STATS * fpstats ,
int section_target_bandwitdh ,
int overhead_bits )
2010-05-18 19:58:33 +04:00
{
int Q ;
2011-03-10 19:13:44 +03:00
int num_mbs = cpi - > common . MBs ;
2010-05-18 19:58:33 +04:00
int target_norm_bits_per_mb ;
2011-09-15 17:36:24 +04:00
double section_err = ( fpstats - > coded_error / fpstats - > count ) ;
2010-05-18 19:58:33 +04:00
double err_per_mb = section_err / num_mbs ;
2011-09-15 17:36:24 +04:00
double err_correction_factor ;
2010-05-18 19:58:33 +04:00
double speed_correction = 1.0 ;
2011-09-15 17:36:24 +04:00
int overhead_bits_per_mb ;
2010-05-18 19:58:33 +04:00
if ( section_target_bandwitdh < = 0 )
2011-05-20 01:16:39 +04:00
return cpi - > twopass . maxq_max_limit ; // Highest value allowed
2010-05-18 19:58:33 +04:00
2011-09-15 17:36:24 +04:00
target_norm_bits_per_mb =
( section_target_bandwitdh < ( 1 < < 20 ) )
? ( 512 * section_target_bandwitdh ) / num_mbs
: 512 * ( section_target_bandwitdh / num_mbs ) ;
2010-05-18 19:58:33 +04:00
2011-09-15 17:36:24 +04:00
// Calculate a corrective factor based on a rolling ratio of bits spent
// vs target bits
if ( ( cpi - > rolling_target_bits > 0 ) & &
( cpi - > active_worst_quality < cpi - > worst_quality ) )
2010-05-18 19:58:33 +04:00
{
2011-08-17 17:14:23 +04:00
double rolling_ratio ;
2011-09-15 17:36:24 +04:00
rolling_ratio = ( double ) cpi - > rolling_actual_bits /
( double ) cpi - > rolling_target_bits ;
2010-05-18 19:58:33 +04:00
if ( rolling_ratio < 0.95 )
2011-05-20 01:16:39 +04:00
cpi - > twopass . est_max_qcorrection_factor - = 0.005 ;
2010-05-18 19:58:33 +04:00
else if ( rolling_ratio > 1.05 )
2011-05-20 01:16:39 +04:00
cpi - > twopass . est_max_qcorrection_factor + = 0.005 ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
cpi - > twopass . est_max_qcorrection_factor =
( cpi - > twopass . est_max_qcorrection_factor < 0.1 )
? 0.1
: ( cpi - > twopass . est_max_qcorrection_factor > 10.0 )
? 10.0 : cpi - > twopass . est_max_qcorrection_factor ;
2010-05-18 19:58:33 +04:00
}
2011-09-15 17:36:24 +04:00
// Corrections for higher compression speed settings
// (reduced compression expected)
2010-05-18 19:58:33 +04:00
if ( ( cpi - > compressor_speed = = 3 ) | | ( cpi - > compressor_speed = = 1 ) )
{
if ( cpi - > oxcf . cpu_used < = 5 )
speed_correction = 1.04 + ( cpi - > oxcf . cpu_used * 0.04 ) ;
else
speed_correction = 1.25 ;
}
2011-09-15 17:36:24 +04:00
// Estimate of overhead bits per mb
// Correction to overhead bits for min allowed Q.
overhead_bits_per_mb = overhead_bits / num_mbs ;
overhead_bits_per_mb * = pow ( 0.98 , ( double ) cpi - > twopass . maxq_min_limit ) ;
2010-05-18 19:58:33 +04:00
2011-01-07 21:29:37 +03:00
// Try and pick a max Q that will be high enough to encode the
2011-01-07 19:33:59 +03:00
// content at the given rate.
2011-05-20 01:16:39 +04:00
for ( Q = cpi - > twopass . maxq_min_limit ; Q < cpi - > twopass . maxq_max_limit ; Q + + )
2010-05-18 19:58:33 +04:00
{
int bits_per_mb_at_this_q ;
2011-09-15 17:36:24 +04:00
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor ( err_per_mb , 150.0 , 0.40 , 0.90 , Q ) ;
2010-05-18 19:58:33 +04:00
2011-09-15 17:36:24 +04:00
bits_per_mb_at_this_q =
vp8_bits_per_mb [ INTER_FRAME ] [ Q ] + overhead_bits_per_mb ;
bits_per_mb_at_this_q = ( int ) ( .5 + err_correction_factor
2011-05-20 01:16:39 +04:00
* speed_correction * cpi - > twopass . est_max_qcorrection_factor
* cpi - > twopass . section_max_qfactor
2011-09-15 17:36:24 +04:00
* ( double ) bits_per_mb_at_this_q ) ;
// Mode and motion overhead
// As Q rises in real encode loop rd code will force overhead down
// We make a crude adjustment for this here as *.98 per Q step.
overhead_bits_per_mb = ( int ) ( ( double ) overhead_bits_per_mb * 0.98 ) ;
2010-05-18 19:58:33 +04:00
if ( bits_per_mb_at_this_q < = target_norm_bits_per_mb )
break ;
}
2011-01-07 21:29:37 +03:00
// Restriction on active max q for constrained quality mode.
if ( ( cpi - > oxcf . end_usage = = USAGE_CONSTRAINED_QUALITY ) & &
( Q < cpi - > cq_target_quality ) )
{
Q = cpi - > cq_target_quality ;
}
2011-01-10 19:41:53 +03:00
// Adjust maxq_min_limit and maxq_max_limit limits based on
// averaga q observed in clip for non kf/gf.arf frames
// Give average a chance to settle though.
if ( ( cpi - > ni_frames >
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
( ( unsigned int ) cpi - > twopass . total_stats . count > > 8 ) ) & &
2011-01-10 19:41:53 +03:00
( cpi - > ni_frames > 150 ) )
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . maxq_max_limit = ( ( cpi - > ni_av_qi + 32 ) < cpi - > worst_quality )
2011-01-10 19:41:53 +03:00
? ( cpi - > ni_av_qi + 32 ) : cpi - > worst_quality ;
2011-05-20 01:16:39 +04:00
cpi - > twopass . maxq_min_limit = ( ( cpi - > ni_av_qi - 32 ) > cpi - > best_quality )
2011-01-10 19:41:53 +03:00
? ( cpi - > ni_av_qi - 32 ) : cpi - > best_quality ;
}
2010-05-18 19:58:33 +04:00
return Q ;
}
2011-09-15 17:36:24 +04:00
// For cq mode estimate a cq level that matches the observed
// complexity and data rate.
static int estimate_cq ( VP8_COMP * cpi ,
FIRSTPASS_STATS * fpstats ,
int section_target_bandwitdh ,
int overhead_bits )
{
int Q ;
int num_mbs = cpi - > common . MBs ;
int target_norm_bits_per_mb ;
double section_err = ( fpstats - > coded_error / fpstats - > count ) ;
double err_per_mb = section_err / num_mbs ;
double err_correction_factor ;
double speed_correction = 1.0 ;
double clip_iiratio ;
double clip_iifactor ;
int overhead_bits_per_mb ;
if ( 0 )
{
FILE * f = fopen ( " epmp.stt " , " a " ) ;
fprintf ( f , " %10.2f \n " , err_per_mb ) ;
fclose ( f ) ;
}
target_norm_bits_per_mb = ( section_target_bandwitdh < ( 1 < < 20 ) )
? ( 512 * section_target_bandwitdh ) / num_mbs
: 512 * ( section_target_bandwitdh / num_mbs ) ;
// Estimate of overhead bits per mb
overhead_bits_per_mb = overhead_bits / num_mbs ;
// Corrections for higher compression speed settings
// (reduced compression expected)
if ( ( cpi - > compressor_speed = = 3 ) | | ( cpi - > compressor_speed = = 1 ) )
{
if ( cpi - > oxcf . cpu_used < = 5 )
speed_correction = 1.04 + ( cpi - > oxcf . cpu_used * 0.04 ) ;
else
speed_correction = 1.25 ;
}
// II ratio correction factor for clip as a whole
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
clip_iiratio = cpi - > twopass . total_stats . intra_error /
DOUBLE_DIVIDE_CHECK ( cpi - > twopass . total_stats . coded_error ) ;
2011-09-15 17:36:24 +04:00
clip_iifactor = 1.0 - ( ( clip_iiratio - 10.0 ) * 0.025 ) ;
if ( clip_iifactor < 0.80 )
clip_iifactor = 0.80 ;
// Try and pick a Q that can encode the content at the given rate.
for ( Q = 0 ; Q < MAXQ ; Q + + )
{
int bits_per_mb_at_this_q ;
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor ( err_per_mb , 100.0 , 0.40 , 0.90 , Q ) ;
bits_per_mb_at_this_q =
vp8_bits_per_mb [ INTER_FRAME ] [ Q ] + overhead_bits_per_mb ;
bits_per_mb_at_this_q =
( int ) ( .5 + err_correction_factor *
speed_correction *
clip_iifactor *
( double ) bits_per_mb_at_this_q ) ;
// Mode and motion overhead
// As Q rises in real encode loop rd code will force overhead down
// We make a crude adjustment for this here as *.98 per Q step.
overhead_bits_per_mb = ( int ) ( ( double ) overhead_bits_per_mb * 0.98 ) ;
if ( bits_per_mb_at_this_q < = target_norm_bits_per_mb )
break ;
}
// Clip value to range "best allowed to (worst allowed - 1)"
Q = cq_level [ Q ] ;
if ( Q > = cpi - > worst_quality )
Q = cpi - > worst_quality - 1 ;
if ( Q < cpi - > best_quality )
Q = cpi - > best_quality ;
return Q ;
}
2011-03-10 19:13:44 +03:00
static int estimate_q ( VP8_COMP * cpi , double section_err , int section_target_bandwitdh )
2010-05-18 19:58:33 +04:00
{
int Q ;
2011-03-10 19:13:44 +03:00
int num_mbs = cpi - > common . MBs ;
2010-05-18 19:58:33 +04:00
int target_norm_bits_per_mb ;
double err_per_mb = section_err / num_mbs ;
2011-09-15 17:36:24 +04:00
double err_correction_factor ;
2010-05-18 19:58:33 +04:00
double speed_correction = 1.0 ;
target_norm_bits_per_mb = ( section_target_bandwitdh < ( 1 < < 20 ) ) ? ( 512 * section_target_bandwitdh ) / num_mbs : 512 * ( section_target_bandwitdh / num_mbs ) ;
// Corrections for higher compression speed settings (reduced compression expected)
if ( ( cpi - > compressor_speed = = 3 ) | | ( cpi - > compressor_speed = = 1 ) )
{
if ( cpi - > oxcf . cpu_used < = 5 )
speed_correction = 1.04 + ( cpi - > oxcf . cpu_used * 0.04 ) ;
else
speed_correction = 1.25 ;
}
// Try and pick a Q that can encode the content at the given rate.
for ( Q = 0 ; Q < MAXQ ; Q + + )
{
int bits_per_mb_at_this_q ;
2011-09-15 17:36:24 +04:00
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor ( err_per_mb , 150.0 , 0.40 , 0.90 , Q ) ;
2010-05-18 19:58:33 +04:00
2011-09-15 17:36:24 +04:00
bits_per_mb_at_this_q =
( int ) ( .5 + ( err_correction_factor *
speed_correction *
cpi - > twopass . est_max_qcorrection_factor *
( double ) vp8_bits_per_mb [ INTER_FRAME ] [ Q ] / 1.0 ) ) ;
2010-05-18 19:58:33 +04:00
if ( bits_per_mb_at_this_q < = target_norm_bits_per_mb )
break ;
}
return Q ;
}
// Estimate a worst case Q for a KF group
2011-03-10 19:13:44 +03:00
static int estimate_kf_group_q ( VP8_COMP * cpi , double section_err , int section_target_bandwitdh , double group_iiratio )
2010-05-18 19:58:33 +04:00
{
int Q ;
2011-03-10 19:13:44 +03:00
int num_mbs = cpi - > common . MBs ;
2010-05-18 19:58:33 +04:00
int target_norm_bits_per_mb = ( 512 * section_target_bandwitdh ) / num_mbs ;
int bits_per_mb_at_this_q ;
double err_per_mb = section_err / num_mbs ;
double err_correction_factor ;
double speed_correction = 1.0 ;
double current_spend_ratio = 1.0 ;
double pow_highq = ( POW1 < 0.6 ) ? POW1 + 0.3 : 0.90 ;
double pow_lowq = ( POW1 < 0.7 ) ? POW1 + 0.1 : 0.80 ;
double iiratio_correction_factor = 1.0 ;
double combined_correction_factor ;
// Trap special case where the target is <= 0
if ( target_norm_bits_per_mb < = 0 )
return MAXQ * 2 ;
// Calculate a corrective factor based on a rolling ratio of bits spent vs target bits
// This is clamped to the range 0.1 to 10.0
if ( cpi - > long_rolling_target_bits < = 0 )
current_spend_ratio = 10.0 ;
else
{
current_spend_ratio = ( double ) cpi - > long_rolling_actual_bits / ( double ) cpi - > long_rolling_target_bits ;
current_spend_ratio = ( current_spend_ratio > 10.0 ) ? 10.0 : ( current_spend_ratio < 0.1 ) ? 0.1 : current_spend_ratio ;
}
// Calculate a correction factor based on the quality of prediction in the sequence as indicated by intra_inter error score ratio (IIRatio)
// The idea here is to favour subsampling in the hardest sections vs the easyest.
iiratio_correction_factor = 1.0 - ( ( group_iiratio - 6.0 ) * 0.1 ) ;
if ( iiratio_correction_factor < 0.5 )
iiratio_correction_factor = 0.5 ;
// Corrections for higher compression speed settings (reduced compression expected)
if ( ( cpi - > compressor_speed = = 3 ) | | ( cpi - > compressor_speed = = 1 ) )
{
if ( cpi - > oxcf . cpu_used < = 5 )
speed_correction = 1.04 + ( cpi - > oxcf . cpu_used * 0.04 ) ;
else
speed_correction = 1.25 ;
}
// Combine the various factors calculated above
combined_correction_factor = speed_correction * iiratio_correction_factor * current_spend_ratio ;
// Try and pick a Q that should be high enough to encode the content at the given rate.
for ( Q = 0 ; Q < MAXQ ; Q + + )
{
2011-09-15 17:36:24 +04:00
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor ( err_per_mb , 150.0 , pow_lowq , pow_highq , Q ) ;
2010-05-18 19:58:33 +04:00
2011-09-15 17:36:24 +04:00
bits_per_mb_at_this_q =
( int ) ( .5 + ( err_correction_factor *
combined_correction_factor *
( double ) vp8_bits_per_mb [ INTER_FRAME ] [ Q ] ) ) ;
2010-05-18 19:58:33 +04:00
if ( bits_per_mb_at_this_q < = target_norm_bits_per_mb )
break ;
}
// If we could not hit the target even at Max Q then estimate what Q would have bee required
while ( ( bits_per_mb_at_this_q > target_norm_bits_per_mb ) & & ( Q < ( MAXQ * 2 ) ) )
{
bits_per_mb_at_this_q = ( int ) ( 0.96 * bits_per_mb_at_this_q ) ;
Q + + ;
}
if ( 0 )
{
FILE * f = fopen ( " estkf_q.stt " , " a " ) ;
fprintf ( f , " %8d %8d %8d %8.2f %8.3f %8.2f %8.3f %8.3f %8.3f %8d \n " , cpi - > common . current_video_frame , bits_per_mb_at_this_q ,
target_norm_bits_per_mb , err_per_mb , err_correction_factor ,
current_spend_ratio , group_iiratio , iiratio_correction_factor ,
( double ) cpi - > buffer_level / ( double ) cpi - > oxcf . optimal_buffer_level , Q ) ;
fclose ( f ) ;
}
return Q ;
}
2011-01-07 21:29:37 +03:00
2010-05-18 19:58:33 +04:00
extern void vp8_new_frame_rate ( VP8_COMP * cpi , double framerate ) ;
void vp8_init_second_pass ( VP8_COMP * cpi )
{
FIRSTPASS_STATS this_frame ;
FIRSTPASS_STATS * start_pos ;
double two_pass_min_rate = ( double ) ( cpi - > oxcf . target_bandwidth * cpi - > oxcf . two_pass_vbrmin_section / 100 ) ;
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
zero_stats ( & cpi - > twopass . total_stats ) ;
zero_stats ( & cpi - > twopass . total_left_stats ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( ! cpi - > twopass . stats_in_end )
2010-05-18 19:58:33 +04:00
return ;
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
cpi - > twopass . total_stats = * cpi - > twopass . stats_in_end ;
cpi - > twopass . total_left_stats = cpi - > twopass . total_stats ;
2010-05-18 19:58:33 +04:00
// 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.
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
vp8_new_frame_rate ( cpi , 10000000.0 * cpi - > twopass . total_stats . count / cpi - > twopass . total_stats . duration ) ;
2010-05-18 19:58:33 +04:00
2011-11-11 22:47:20 +04:00
cpi - > output_frame_rate = cpi - > frame_rate ;
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
cpi - > twopass . bits_left = ( int64_t ) ( cpi - > twopass . total_stats . duration * cpi - > oxcf . target_bandwidth / 10000000.0 ) ;
cpi - > twopass . bits_left - = ( int64_t ) ( cpi - > twopass . total_stats . duration * two_pass_min_rate / 10000000.0 ) ;
2010-05-18 19:58:33 +04:00
2011-01-04 20:55:49 +03:00
// Calculate a minimum intra value to be used in determining the IIratio
// scores used in the second pass. We have this minimum to make sure
// that clips that are static but "low complexity" in the intra domain
// are still boosted appropriately for KF/GF/ARF
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_intra_err_min = KF_MB_INTRA_MIN * cpi - > common . MBs ;
cpi - > twopass . gf_intra_err_min = GF_MB_INTRA_MIN * cpi - > common . MBs ;
2011-01-04 20:55:49 +03:00
2010-05-18 19:58:33 +04:00
// Scan the first pass file and calculate an average Intra / Inter error score ratio for the sequence
{
double sum_iiratio = 0.0 ;
double IIRatio ;
2011-05-20 01:16:39 +04:00
start_pos = cpi - > twopass . stats_in ; // Note starting "file" position
2010-05-18 19:58:33 +04:00
2011-03-18 00:07:59 +03:00
while ( input_stats ( cpi , & this_frame ) ! = EOF )
2010-05-18 19:58:33 +04:00
{
IIRatio = this_frame . intra_error / DOUBLE_DIVIDE_CHECK ( this_frame . coded_error ) ;
IIRatio = ( IIRatio < 1.0 ) ? 1.0 : ( IIRatio > 20.0 ) ? 20.0 : IIRatio ;
sum_iiratio + = IIRatio ;
}
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
cpi - > twopass . avg_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > twopass . total_stats . count ) ;
2010-05-18 19:58:33 +04:00
// Reset file position
reset_fpf_position ( cpi , start_pos ) ;
}
// Scan the first pass file and calculate a modified total error based upon the bias/power function
// used to allocate bits
{
2011-05-20 01:16:39 +04:00
start_pos = cpi - > twopass . stats_in ; // Note starting "file" position
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
cpi - > twopass . modified_error_total = 0.0 ;
cpi - > twopass . modified_error_used = 0.0 ;
2010-05-18 19:58:33 +04:00
2011-03-18 00:07:59 +03:00
while ( input_stats ( cpi , & this_frame ) ! = EOF )
2010-05-18 19:58:33 +04:00
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . modified_error_total + = calculate_modified_err ( cpi , & this_frame ) ;
2010-05-18 19:58:33 +04:00
}
2011-05-20 01:16:39 +04:00
cpi - > twopass . modified_error_left = cpi - > twopass . modified_error_total ;
2010-05-18 19:58:33 +04:00
reset_fpf_position ( cpi , start_pos ) ; // Reset file position
}
}
void vp8_end_second_pass ( VP8_COMP * cpi )
{
}
2011-01-21 20:52:00 +03:00
// This function gives and estimate of how badly we believe
2011-03-10 22:32:48 +03:00
// the prediction quality is decaying from frame to frame.
2011-03-18 00:07:59 +03:00
static double get_prediction_decay_rate ( VP8_COMP * cpi , FIRSTPASS_STATS * next_frame )
2011-01-21 20:52:00 +03:00
{
double prediction_decay_rate ;
double motion_decay ;
double motion_pct = next_frame - > pcnt_motion ;
// Initial basis is the % mbs inter coded
prediction_decay_rate = next_frame - > pcnt_inter ;
// High % motion -> somewhat higher decay rate
motion_decay = ( 1.0 - ( motion_pct / 20.0 ) ) ;
if ( motion_decay < prediction_decay_rate )
prediction_decay_rate = motion_decay ;
// Adjustment to decay rate based on speed of motion
{
double this_mv_rabs ;
double this_mv_cabs ;
double distance_factor ;
this_mv_rabs = fabs ( next_frame - > mvr_abs * motion_pct ) ;
this_mv_cabs = fabs ( next_frame - > mvc_abs * motion_pct ) ;
distance_factor = sqrt ( ( this_mv_rabs * this_mv_rabs ) +
( this_mv_cabs * this_mv_cabs ) ) / 250.0 ;
distance_factor = ( ( distance_factor > 1.0 )
? 0.0 : ( 1.0 - distance_factor ) ) ;
if ( distance_factor < prediction_decay_rate )
prediction_decay_rate = distance_factor ;
}
return prediction_decay_rate ;
}
2011-03-07 18:58:07 +03:00
2011-03-08 17:46:22 +03:00
// Function to test for a condition where a complex transition is followed
2011-03-07 18:11:09 +03:00
// by a static section. For example in slide shows where there is a fade
// between slides. This is to help with more optimal kf and gf positioning.
2011-03-18 00:07:59 +03:00
static int detect_transition_to_still (
2011-03-07 18:11:09 +03:00
VP8_COMP * cpi ,
int frame_interval ,
int still_interval ,
double loop_decay_rate ,
double decay_accumulator )
{
2011-12-22 02:21:29 +04:00
int trans_to_still = 0 ;
2011-03-07 18:11:09 +03:00
// Break clause to detect very still sections after motion
2011-03-08 17:46:22 +03:00
// For example a static image after a fade or other transition
2011-03-07 18:11:09 +03:00
// instead of a clean scene cut.
if ( ( frame_interval > MIN_GF_INTERVAL ) & &
( loop_decay_rate > = 0.999 ) & &
( decay_accumulator < 0.9 ) )
{
int j ;
2011-05-20 01:16:39 +04:00
FIRSTPASS_STATS * position = cpi - > twopass . stats_in ;
2011-03-07 18:11:09 +03:00
FIRSTPASS_STATS tmp_next_frame ;
double decay_rate ;
// Look ahead a few frames to see if static condition
// persists...
for ( j = 0 ; j < still_interval ; j + + )
{
2011-03-18 00:07:59 +03:00
if ( EOF = = input_stats ( cpi , & tmp_next_frame ) )
2011-03-07 18:11:09 +03:00
break ;
decay_rate = get_prediction_decay_rate ( cpi , & tmp_next_frame ) ;
if ( decay_rate < 0.999 )
break ;
}
// Reset file position
reset_fpf_position ( cpi , position ) ;
// Only if it does do we signal a transition to still
if ( j = = still_interval )
2011-12-22 02:21:29 +04:00
trans_to_still = 1 ;
2011-03-07 18:11:09 +03:00
}
return trans_to_still ;
}
2011-01-21 20:52:00 +03:00
2011-06-28 20:29:47 +04:00
// This function detects a flash through the high relative pcnt_second_ref
// score in the frame following a flash frame. The offset passed in should
// reflect this
2011-12-22 02:21:29 +04:00
static int detect_flash ( VP8_COMP * cpi , int offset )
2011-06-28 20:29:47 +04:00
{
FIRSTPASS_STATS next_frame ;
2011-12-22 02:21:29 +04:00
int flash_detected = 0 ;
2011-06-28 20:29:47 +04:00
// Read the frame data.
2011-12-22 02:21:29 +04:00
// The return is 0 (no flash detected) if not a valid frame
2011-06-28 20:29:47 +04:00
if ( read_frame_stats ( cpi , & next_frame , offset ) ! = EOF )
{
// What we are looking for here is a situation where there is a
// brief break in prediction (such as a flash) but subsequent frames
// are reasonably well predicted by an earlier (pre flash) frame.
// The recovery after a flash is indicated by a high pcnt_second_ref
// comapred to pcnt_inter.
if ( ( next_frame . pcnt_second_ref > next_frame . pcnt_inter ) & &
( next_frame . pcnt_second_ref > = 0.5 ) )
{
2011-12-22 02:21:29 +04:00
flash_detected = 1 ;
2011-06-28 20:29:47 +04:00
/*if (1)
{
FILE * f = fopen ( " flash.stt " , " a " ) ;
fprintf ( f , " %8.0f %6.2f %6.2f \n " ,
next_frame . frame ,
next_frame . pcnt_inter ,
next_frame . pcnt_second_ref ) ;
fclose ( f ) ;
} */
}
}
return flash_detected ;
}
// Update the motion related elements to the GF arf boost calculation
static void accumulate_frame_motion_stats (
VP8_COMP * cpi ,
FIRSTPASS_STATS * this_frame ,
double * this_frame_mv_in_out ,
double * mv_in_out_accumulator ,
double * abs_mv_in_out_accumulator ,
double * mv_ratio_accumulator )
{
//double this_frame_mv_in_out;
double this_frame_mvr_ratio ;
double this_frame_mvc_ratio ;
double motion_pct ;
// Accumulate motion stats.
motion_pct = this_frame - > pcnt_motion ;
// Accumulate Motion In/Out of frame stats
* this_frame_mv_in_out = this_frame - > mv_in_out_count * motion_pct ;
* mv_in_out_accumulator + = this_frame - > mv_in_out_count * motion_pct ;
* abs_mv_in_out_accumulator + =
fabs ( this_frame - > mv_in_out_count * motion_pct ) ;
// Accumulate a measure of how uniform (or conversely how random)
// the motion field is. (A ratio of absmv / mv)
if ( motion_pct > 0.05 )
{
this_frame_mvr_ratio = fabs ( this_frame - > mvr_abs ) /
DOUBLE_DIVIDE_CHECK ( fabs ( this_frame - > MVr ) ) ;
this_frame_mvc_ratio = fabs ( this_frame - > mvc_abs ) /
DOUBLE_DIVIDE_CHECK ( fabs ( this_frame - > MVc ) ) ;
* mv_ratio_accumulator + =
( this_frame_mvr_ratio < this_frame - > mvr_abs )
? ( this_frame_mvr_ratio * motion_pct )
: this_frame - > mvr_abs * motion_pct ;
* mv_ratio_accumulator + =
( this_frame_mvc_ratio < this_frame - > mvc_abs )
? ( this_frame_mvc_ratio * motion_pct )
: this_frame - > mvc_abs * motion_pct ;
}
}
// Calculate a baseline boost number for the current frame.
static double calc_frame_boost (
VP8_COMP * cpi ,
FIRSTPASS_STATS * this_frame ,
double this_frame_mv_in_out )
{
double frame_boost ;
// Underlying boost factor is based on inter intra error ratio
if ( this_frame - > intra_error > cpi - > twopass . gf_intra_err_min )
frame_boost = ( IIFACTOR * this_frame - > intra_error /
DOUBLE_DIVIDE_CHECK ( this_frame - > coded_error ) ) ;
else
frame_boost = ( IIFACTOR * cpi - > twopass . gf_intra_err_min /
DOUBLE_DIVIDE_CHECK ( this_frame - > coded_error ) ) ;
// Increase boost for frames where new data coming into frame
// (eg zoom out). Slightly reduce boost if there is a net balance
// of motion out of the frame (zoom in).
// The range for this_frame_mv_in_out is -1.0 to +1.0
if ( this_frame_mv_in_out > 0.0 )
frame_boost + = frame_boost * ( this_frame_mv_in_out * 2.0 ) ;
// In extreme case boost is halved
else
frame_boost + = frame_boost * ( this_frame_mv_in_out / 2.0 ) ;
// Clip to maximum
if ( frame_boost > GF_RMAX )
frame_boost = GF_RMAX ;
return frame_boost ;
}
# if NEW_BOOST
static int calc_arf_boost (
VP8_COMP * cpi ,
int offset ,
int f_frames ,
int b_frames ,
int * f_boost ,
int * b_boost )
{
FIRSTPASS_STATS this_frame ;
int i ;
double boost_score = 0.0 ;
double mv_ratio_accumulator = 0.0 ;
double decay_accumulator = 1.0 ;
double this_frame_mv_in_out = 0.0 ;
double mv_in_out_accumulator = 0.0 ;
double abs_mv_in_out_accumulator = 0.0 ;
double r ;
2011-12-22 02:21:29 +04:00
int flash_detected = 0 ;
2011-06-28 20:29:47 +04:00
// Search forward from the proposed arf/next gf position
for ( i = 0 ; i < f_frames ; i + + )
{
if ( read_frame_stats ( cpi , & this_frame , ( i + offset ) ) = = EOF )
break ;
// Update the motion related elements to the boost calculation
accumulate_frame_motion_stats ( cpi , & this_frame ,
& this_frame_mv_in_out , & mv_in_out_accumulator ,
& abs_mv_in_out_accumulator , & mv_ratio_accumulator ) ;
// Calculate the baseline boost number for this frame
r = calc_frame_boost ( cpi , & this_frame , this_frame_mv_in_out ) ;
// We want to discount the the flash frame itself and the recovery
// frame that follows as both will have poor scores.
flash_detected = detect_flash ( cpi , ( i + offset ) ) | |
detect_flash ( cpi , ( i + offset + 1 ) ) ;
// Cumulative effect of prediction quality decay
if ( ! flash_detected )
{
decay_accumulator =
decay_accumulator *
get_prediction_decay_rate ( cpi , & this_frame ) ;
decay_accumulator =
decay_accumulator < 0.1 ? 0.1 : decay_accumulator ;
}
boost_score + = ( decay_accumulator * r ) ;
// Break out conditions.
if ( ( ! flash_detected ) & &
( ( mv_ratio_accumulator > 100.0 ) | |
( abs_mv_in_out_accumulator > 3.0 ) | |
( mv_in_out_accumulator < - 2.0 ) ) )
{
break ;
}
}
* f_boost = ( int ) ( boost_score * 100.0 ) > > 4 ;
// Reset for backward looking loop
boost_score = 0.0 ;
mv_ratio_accumulator = 0.0 ;
decay_accumulator = 1.0 ;
this_frame_mv_in_out = 0.0 ;
mv_in_out_accumulator = 0.0 ;
abs_mv_in_out_accumulator = 0.0 ;
// Search forward from the proposed arf/next gf position
for ( i = - 1 ; i > = - b_frames ; i - - )
{
if ( read_frame_stats ( cpi , & this_frame , ( i + offset ) ) = = EOF )
break ;
// Update the motion related elements to the boost calculation
accumulate_frame_motion_stats ( cpi , & this_frame ,
& this_frame_mv_in_out , & mv_in_out_accumulator ,
& abs_mv_in_out_accumulator , & mv_ratio_accumulator ) ;
// Calculate the baseline boost number for this frame
r = calc_frame_boost ( cpi , & this_frame , this_frame_mv_in_out ) ;
// We want to discount the the flash frame itself and the recovery
// frame that follows as both will have poor scores.
flash_detected = detect_flash ( cpi , ( i + offset ) ) | |
detect_flash ( cpi , ( i + offset + 1 ) ) ;
// Cumulative effect of prediction quality decay
if ( ! flash_detected )
{
decay_accumulator =
decay_accumulator *
get_prediction_decay_rate ( cpi , & this_frame ) ;
decay_accumulator =
decay_accumulator < 0.1 ? 0.1 : decay_accumulator ;
}
boost_score + = ( decay_accumulator * r ) ;
// Break out conditions.
if ( ( ! flash_detected ) & &
( ( mv_ratio_accumulator > 100.0 ) | |
( abs_mv_in_out_accumulator > 3.0 ) | |
( mv_in_out_accumulator < - 2.0 ) ) )
{
break ;
}
}
* b_boost = ( int ) ( boost_score * 100.0 ) > > 4 ;
return ( * f_boost + * b_boost ) ;
}
# endif
2010-05-18 19:58:33 +04:00
// Analyse and define a gf/arf group .
static void define_gf_group ( VP8_COMP * cpi , FIRSTPASS_STATS * this_frame )
{
FIRSTPASS_STATS next_frame ;
FIRSTPASS_STATS * start_pos ;
int i ;
2011-06-28 20:29:47 +04:00
double r ;
2010-05-18 19:58:33 +04:00
double boost_score = 0.0 ;
double old_boost_score = 0.0 ;
double gf_group_err = 0.0 ;
double gf_first_frame_err = 0.0 ;
double mod_frame_err = 0.0 ;
double mv_ratio_accumulator = 0.0 ;
double decay_accumulator = 1.0 ;
2011-01-20 21:01:20 +03:00
double loop_decay_rate = 1.00 ; // Starting decay rate
2010-05-18 19:58:33 +04:00
double this_frame_mv_in_out = 0.0 ;
double mv_in_out_accumulator = 0.0 ;
double abs_mv_in_out_accumulator = 0.0 ;
double mod_err_per_mb_accumulator = 0.0 ;
2011-08-12 22:51:36 +04:00
int max_bits = frame_max_bits ( cpi ) ; // Max for a single frame
2010-05-18 19:58:33 +04:00
2011-01-20 21:01:20 +03:00
unsigned int allow_alt_ref =
cpi - > oxcf . play_alternate & & cpi - > oxcf . lag_in_frames ;
2011-06-28 20:29:47 +04:00
int alt_boost = 0 ;
int f_boost = 0 ;
int b_boost = 0 ;
2011-12-22 02:21:29 +04:00
int flash_detected ;
2011-06-28 20:29:47 +04:00
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_group_bits = 0 ;
cpi - > twopass . gf_decay_rate = 0 ;
2010-05-18 19:58:33 +04:00
vp8_clear_system_state ( ) ; //__asm emms;
2011-05-20 01:16:39 +04:00
start_pos = cpi - > twopass . stats_in ;
2010-05-18 19:58:33 +04:00
2010-06-11 22:33:49 +04:00
vpx_memset ( & next_frame , 0 , sizeof ( next_frame ) ) ; // assure clean
2011-06-28 20:29:47 +04:00
// Load stats for the current frame.
2010-05-18 19:58:33 +04:00
mod_frame_err = calculate_modified_err ( cpi , this_frame ) ;
2011-01-20 21:01:20 +03:00
// Note the error of the frame at the start of the group (this will be
// the GF frame error if we code a normal gf
2010-05-18 19:58:33 +04:00
gf_first_frame_err = mod_frame_err ;
2011-01-20 21:01:20 +03:00
// Special treatment if the current frame is a key frame (which is also
// a gf). If it is then its error score (and hence bit allocation) need
// to be subtracted out from the calculation for the GF group
2010-05-18 19:58:33 +04:00
if ( cpi - > common . frame_type = = KEY_FRAME )
gf_group_err - = gf_first_frame_err ;
2011-01-20 21:01:20 +03:00
// Scan forward to try and work out how many frames the next gf group
// should contain and what level of boost is appropriate for the GF
// or ARF that will be coded with the group
2010-05-18 19:58:33 +04:00
i = 0 ;
2011-05-20 01:16:39 +04:00
while ( ( ( i < cpi - > twopass . static_scene_max_gf_interval ) | |
( ( cpi - > twopass . frames_to_key - i ) < MIN_GF_INTERVAL ) ) & &
( i < cpi - > twopass . frames_to_key ) )
2010-05-18 19:58:33 +04:00
{
2011-01-20 21:01:20 +03:00
i + + ; // Increment the loop counter
2010-05-18 19:58:33 +04:00
// Accumulate error score of frames in this gf group
mod_frame_err = calculate_modified_err ( cpi , this_frame ) ;
gf_group_err + = mod_frame_err ;
2011-01-20 21:01:20 +03:00
mod_err_per_mb_accumulator + =
mod_frame_err / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > common . MBs ) ;
2010-05-18 19:58:33 +04:00
2011-03-18 00:07:59 +03:00
if ( EOF = = input_stats ( cpi , & next_frame ) )
2010-05-18 19:58:33 +04:00
break ;
2011-06-28 20:29:47 +04:00
// Test for the case where there is a brief flash but the prediction
// quality back to an earlier frame is then restored.
flash_detected = detect_flash ( cpi , 0 ) ;
2010-10-02 20:31:46 +04:00
2011-06-28 20:29:47 +04:00
// Update the motion related elements to the boost calculation
accumulate_frame_motion_stats ( cpi , & next_frame ,
& this_frame_mv_in_out , & mv_in_out_accumulator ,
& abs_mv_in_out_accumulator , & mv_ratio_accumulator ) ;
2010-10-02 20:31:46 +04:00
2011-06-28 20:29:47 +04:00
// Calculate a baseline boost number for this frame
r = calc_frame_boost ( cpi , & next_frame , this_frame_mv_in_out ) ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
// Cumulative effect of prediction quality decay
if ( ! flash_detected )
2010-05-18 19:58:33 +04:00
{
2011-06-28 20:29:47 +04:00
loop_decay_rate = get_prediction_decay_rate ( cpi , & next_frame ) ;
decay_accumulator = decay_accumulator * loop_decay_rate ;
decay_accumulator =
decay_accumulator < 0.1 ? 0.1 : decay_accumulator ;
2010-05-18 19:58:33 +04:00
}
boost_score + = ( decay_accumulator * r ) ;
2011-01-20 21:01:20 +03:00
// Break clause to detect very still sections after motion
2011-03-07 18:11:09 +03:00
// For example a staic image after a fade or other transition.
if ( detect_transition_to_still ( cpi , i , 5 ,
2011-06-28 20:29:47 +04:00
loop_decay_rate ,
decay_accumulator ) )
2011-01-20 21:01:20 +03:00
{
2011-12-22 02:21:29 +04:00
allow_alt_ref = 0 ;
2011-03-07 18:11:09 +03:00
boost_score = old_boost_score ;
break ;
2011-01-20 21:01:20 +03:00
}
2010-05-18 19:58:33 +04:00
// Break out conditions.
2011-06-28 20:29:47 +04:00
if (
2011-01-18 18:19:05 +03:00
// Break at cpi->max_gf_interval unless almost totally static
2011-01-20 21:01:20 +03:00
( i > = cpi - > max_gf_interval & & ( decay_accumulator < 0.995 ) ) | |
2010-05-18 19:58:33 +04:00
(
2011-01-18 18:19:05 +03:00
// Dont break out with a very short interval
( i > MIN_GF_INTERVAL ) & &
// Dont break out very close to a key frame
2011-05-20 01:16:39 +04:00
( ( cpi - > twopass . frames_to_key - i ) > = MIN_GF_INTERVAL ) & &
2010-05-18 19:58:33 +04:00
( ( boost_score > 20.0 ) | | ( next_frame . pcnt_inter < 0.75 ) ) & &
2011-06-28 20:29:47 +04:00
( ! flash_detected ) & &
2010-05-18 19:58:33 +04:00
( ( mv_ratio_accumulator > 100.0 ) | |
( abs_mv_in_out_accumulator > 3.0 ) | |
( mv_in_out_accumulator < - 2.0 ) | |
2011-01-18 18:19:05 +03:00
( ( boost_score - old_boost_score ) < 2.0 ) )
) )
2010-05-18 19:58:33 +04:00
{
boost_score = old_boost_score ;
break ;
}
vpx_memcpy ( this_frame , & next_frame , sizeof ( * this_frame ) ) ;
old_boost_score = boost_score ;
}
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_decay_rate =
2011-01-20 21:01:20 +03:00
( i > 0 ) ? ( int ) ( 100.0 * ( 1.0 - decay_accumulator ) ) / i : 0 ;
2010-05-18 19:58:33 +04:00
// When using CBR apply additional buffer related upper limits
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
double max_boost ;
// For cbr apply buffer related limits
if ( cpi - > drop_frames_allowed )
{
2011-01-20 21:01:20 +03:00
int df_buffer_level = cpi - > oxcf . drop_frames_water_mark *
( cpi - > oxcf . optimal_buffer_level / 100 ) ;
2010-05-18 19:58:33 +04:00
if ( cpi - > buffer_level > df_buffer_level )
max_boost = ( ( double ) ( ( cpi - > buffer_level - df_buffer_level ) * 2 / 3 ) * 16.0 ) / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > av_per_frame_bandwidth ) ;
else
max_boost = 0.0 ;
}
else if ( cpi - > buffer_level > 0 )
{
max_boost = ( ( double ) ( cpi - > buffer_level * 2 / 3 ) * 16.0 ) / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > av_per_frame_bandwidth ) ;
}
else
{
max_boost = 0.0 ;
}
if ( boost_score > max_boost )
boost_score = max_boost ;
}
2011-06-02 20:14:51 +04:00
// Dont allow conventional gf too near the next kf
if ( ( cpi - > twopass . frames_to_key - i ) < MIN_GF_INTERVAL )
{
while ( i < cpi - > twopass . frames_to_key )
{
i + + ;
if ( EOF = = input_stats ( cpi , this_frame ) )
break ;
if ( i < cpi - > twopass . frames_to_key )
{
mod_frame_err = calculate_modified_err ( cpi , this_frame ) ;
gf_group_err + = mod_frame_err ;
}
}
}
2011-06-28 20:29:47 +04:00
cpi - > gfu_boost = ( int ) ( boost_score * 100.0 ) > > 4 ;
# if NEW_BOOST
// Alterrnative boost calculation for alt ref
alt_boost = calc_arf_boost ( cpi , 0 , ( i - 1 ) , ( i - 1 ) , & f_boost , & b_boost ) ;
# endif
2010-05-18 19:58:33 +04:00
// Should we use the alternate refernce frame
2011-01-20 21:01:20 +03:00
if ( allow_alt_ref & &
2010-05-18 19:58:33 +04:00
( i > = MIN_GF_INTERVAL ) & &
2011-01-20 21:01:20 +03:00
// dont use ARF very near next kf
2011-05-20 01:16:39 +04:00
( i < = ( cpi - > twopass . frames_to_key - MIN_GF_INTERVAL ) ) & &
2011-06-28 20:29:47 +04:00
# if NEW_BOOST
( ( next_frame . pcnt_inter > 0.75 ) | |
( next_frame . pcnt_second_ref > 0.5 ) ) & &
( ( mv_in_out_accumulator / ( double ) i > - 0.2 ) | |
( mv_in_out_accumulator > - 2.0 ) ) & &
( b_boost > 100 ) & &
( f_boost > 100 ) )
# else
( next_frame . pcnt_inter > 0.75 ) & &
( ( mv_in_out_accumulator / ( double ) i > - 0.2 ) | |
( mv_in_out_accumulator > - 2.0 ) ) & &
( cpi - > gfu_boost > 100 ) & &
( cpi - > twopass . gf_decay_rate < =
( ARF_DECAY_THRESH + ( cpi - > gfu_boost / 200 ) ) ) )
# endif
2010-05-18 19:58:33 +04:00
{
int Boost ;
int allocation_chunks ;
2011-06-28 20:29:47 +04:00
int Q = ( cpi - > oxcf . fixed_q < 0 )
? cpi - > last_q [ INTER_FRAME ] : cpi - > oxcf . fixed_q ;
2010-05-18 19:58:33 +04:00
int tmp_q ;
int arf_frame_bits = 0 ;
int group_bits ;
2011-06-28 20:29:47 +04:00
# if NEW_BOOST
cpi - > gfu_boost = alt_boost ;
# endif
2010-05-18 19:58:33 +04:00
// Estimate the bits to be allocated to the group as a whole
2011-06-28 20:29:47 +04:00
if ( ( cpi - > twopass . kf_group_bits > 0 ) & &
( cpi - > twopass . kf_group_error_left > 0 ) )
{
group_bits = ( int ) ( ( double ) cpi - > twopass . kf_group_bits *
( gf_group_err / ( double ) cpi - > twopass . kf_group_error_left ) ) ;
}
2010-05-18 19:58:33 +04:00
else
group_bits = 0 ;
// Boost for arf frame
2011-06-28 20:29:47 +04:00
# if NEW_BOOST
Boost = ( alt_boost * GFQ_ADJUSTMENT ) / 100 ;
# else
2010-05-18 19:58:33 +04:00
Boost = ( cpi - > gfu_boost * 3 * GFQ_ADJUSTMENT ) / ( 2 * 100 ) ;
2011-06-28 20:29:47 +04:00
# endif
2010-11-10 13:09:45 +03:00
Boost + = ( i * 50 ) ;
2011-06-28 20:29:47 +04:00
// Set max and minimum boost and hence minimum allocation
if ( Boost > ( ( cpi - > baseline_gf_interval + 1 ) * 200 ) )
Boost = ( ( cpi - > baseline_gf_interval + 1 ) * 200 ) ;
else if ( Boost < 125 )
Boost = 125 ;
2010-05-18 19:58:33 +04:00
allocation_chunks = ( i * 100 ) + Boost ;
// Normalize Altboost and allocations chunck down to prevent overflow
while ( Boost > 1000 )
{
Boost / = 2 ;
allocation_chunks / = 2 ;
}
2011-06-28 20:29:47 +04:00
// Calculate the number of bits to be spent on the arf based on the
// boost number
arf_frame_bits = ( int ) ( ( double ) Boost * ( group_bits /
( double ) allocation_chunks ) ) ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
// Estimate if there are enough bits available to make worthwhile use
// of an arf.
2011-03-10 19:13:44 +03:00
tmp_q = estimate_q ( cpi , mod_frame_err , ( int ) arf_frame_bits ) ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
// Only use an arf if it is likely we will be able to code
// it at a lower Q than the surrounding frames.
2010-05-18 19:58:33 +04:00
if ( tmp_q < cpi - > worst_quality )
{
2010-09-28 18:23:41 +04:00
int half_gf_int ;
int frames_after_arf ;
int frames_bwd = cpi - > oxcf . arnr_max_frames - 1 ;
int frames_fwd = cpi - > oxcf . arnr_max_frames - 1 ;
2011-12-22 02:21:29 +04:00
cpi - > source_alt_ref_pending = 1 ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
// For alt ref frames the error score for the end frame of the
// group (the alt ref frame) should not contribute to the group
// total and hence the number of bit allocated to the group.
// Rather it forms part of the next group (it is the GF at the
// start of the next group)
// gf_group_err -= mod_frame_err;
// For alt ref frames alt ref frame is technically part of the
// GF frame for the next group but we always base the error
// calculation and bit allocation on the current group of frames.
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
// Set the interval till the next gf or arf.
// For ARFs this is the number of frames to be coded before the
// future frame that is coded as an ARF.
2010-05-18 19:58:33 +04:00
// The future frame itself is part of the next group
2011-06-28 20:29:47 +04:00
cpi - > baseline_gf_interval = i ;
2010-05-18 19:58:33 +04:00
2010-09-28 18:23:41 +04:00
// Define the arnr filter width for this group of frames:
// We only filter frames that lie within a distance of half
// the GF interval from the ARF frame. We also have to trap
// cases where the filter extends beyond the end of clip.
// 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 ;
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
frames_after_arf = cpi - > twopass . total_stats . count -
2011-06-28 20:29:47 +04:00
this_frame - > frame - 1 ;
2010-09-28 18:23:41 +04:00
switch ( cpi - > oxcf . arnr_type )
2010-05-18 19:58:33 +04:00
{
2010-09-28 18:23:41 +04:00
case 1 : // Backward filter
frames_fwd = 0 ;
if ( frames_bwd > half_gf_int )
frames_bwd = half_gf_int ;
break ;
case 2 : // Forward filter
if ( frames_fwd > half_gf_int )
frames_fwd = half_gf_int ;
if ( frames_fwd > frames_after_arf )
frames_fwd = frames_after_arf ;
frames_bwd = 0 ;
break ;
case 3 : // Centered filter
default :
frames_fwd > > = 1 ;
if ( frames_fwd > frames_after_arf )
frames_fwd = frames_after_arf ;
if ( frames_fwd > half_gf_int )
frames_fwd = half_gf_int ;
frames_bwd = frames_fwd ;
// For even length filter there is one more frame backward
// than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
if ( frames_bwd < half_gf_int )
frames_bwd + = ( cpi - > oxcf . arnr_max_frames + 1 ) & 0x1 ;
break ;
}
cpi - > active_arnr_frames = frames_bwd + 1 + frames_fwd ;
2010-05-18 19:58:33 +04:00
}
else
{
2011-12-22 02:21:29 +04:00
cpi - > source_alt_ref_pending = 0 ;
2010-05-18 19:58:33 +04:00
cpi - > baseline_gf_interval = i ;
}
}
else
{
2011-12-22 02:21:29 +04:00
cpi - > source_alt_ref_pending = 0 ;
2010-05-18 19:58:33 +04:00
cpi - > baseline_gf_interval = i ;
}
2011-06-28 20:29:47 +04:00
// 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->twopass.kf_group_bits is tied to cpi->twopass.bits_left.
// This is also important for short clips where there may only be one
// key frame.
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
if ( cpi - > twopass . frames_to_key > = ( int ) ( cpi - > twopass . total_stats . count -
2011-06-28 20:29:47 +04:00
cpi - > common . current_video_frame ) )
2010-05-18 19:58:33 +04:00
{
2011-06-28 20:29:47 +04:00
cpi - > twopass . kf_group_bits =
( cpi - > twopass . bits_left > 0 ) ? cpi - > twopass . bits_left : 0 ;
2010-05-18 19:58:33 +04:00
}
// Calculate the bits to be allocated to the group as a whole
2011-06-28 20:29:47 +04:00
if ( ( cpi - > twopass . kf_group_bits > 0 ) & &
( cpi - > twopass . kf_group_error_left > 0 ) )
{
cpi - > twopass . gf_group_bits =
( int ) ( ( double ) cpi - > twopass . kf_group_bits *
( gf_group_err / ( double ) cpi - > twopass . kf_group_error_left ) ) ;
}
2010-05-18 19:58:33 +04:00
else
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_group_bits = 0 ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
cpi - > twopass . gf_group_bits =
( cpi - > twopass . gf_group_bits < 0 )
? 0
: ( cpi - > twopass . gf_group_bits > cpi - > twopass . kf_group_bits )
? cpi - > twopass . kf_group_bits : cpi - > twopass . gf_group_bits ;
2010-05-18 19:58:33 +04:00
2011-06-28 20:29:47 +04:00
// Clip cpi->twopass.gf_group_bits based on user supplied data rate
// variability limit (cpi->oxcf.two_pass_vbrmax_section)
2011-08-12 22:51:36 +04:00
if ( cpi - > twopass . gf_group_bits > max_bits * cpi - > baseline_gf_interval )
cpi - > twopass . gf_group_bits = max_bits * cpi - > baseline_gf_interval ;
2010-05-18 19:58:33 +04:00
// Reset the file position
reset_fpf_position ( cpi , start_pos ) ;
2010-11-12 14:35:30 +03:00
// Update the record of error used so far (only done once per gf group)
2011-05-20 01:16:39 +04:00
cpi - > twopass . modified_error_used + = gf_group_err ;
2010-11-12 14:35:30 +03:00
2010-05-18 19:58:33 +04:00
// Assign bits to the arf or gf.
2011-06-16 21:01:27 +04:00
for ( i = 0 ; i < = ( cpi - > source_alt_ref_pending & & cpi - > common . frame_type ! = KEY_FRAME ) ; i + + ) {
2010-05-18 19:58:33 +04:00
int Boost ;
int allocation_chunks ;
int Q = ( cpi - > oxcf . fixed_q < 0 ) ? cpi - > last_q [ INTER_FRAME ] : cpi - > oxcf . fixed_q ;
2011-06-16 21:01:27 +04:00
int gf_bits ;
2010-05-18 19:58:33 +04:00
// For ARF frames
2011-06-16 21:01:27 +04:00
if ( cpi - > source_alt_ref_pending & & i = = 0 )
2010-05-18 19:58:33 +04:00
{
2011-06-28 20:29:47 +04:00
# if NEW_BOOST
Boost = ( alt_boost * GFQ_ADJUSTMENT ) / 100 ;
# else
2010-05-18 19:58:33 +04:00
Boost = ( cpi - > gfu_boost * 3 * GFQ_ADJUSTMENT ) / ( 2 * 100 ) ;
2011-06-28 20:29:47 +04:00
# endif
2010-05-18 19:58:33 +04:00
Boost + = ( cpi - > baseline_gf_interval * 50 ) ;
// Set max and minimum boost and hence minimum allocation
if ( Boost > ( ( cpi - > baseline_gf_interval + 1 ) * 200 ) )
Boost = ( ( cpi - > baseline_gf_interval + 1 ) * 200 ) ;
else if ( Boost < 125 )
Boost = 125 ;
2011-06-28 20:29:47 +04:00
allocation_chunks =
( ( cpi - > baseline_gf_interval + 1 ) * 100 ) + Boost ;
2010-05-18 19:58:33 +04:00
}
// Else for standard golden frames
else
{
// boost based on inter / intra ratio of subsequent frames
Boost = ( cpi - > gfu_boost * GFQ_ADJUSTMENT ) / 100 ;
// Set max and minimum boost and hence minimum allocation
if ( Boost > ( cpi - > baseline_gf_interval * 150 ) )
Boost = ( cpi - > baseline_gf_interval * 150 ) ;
else if ( Boost < 125 )
Boost = 125 ;
2011-06-28 20:29:47 +04:00
allocation_chunks =
( cpi - > baseline_gf_interval * 100 ) + ( Boost - 100 ) ;
2010-05-18 19:58:33 +04:00
}
// Normalize Altboost and allocations chunck down to prevent overflow
while ( Boost > 1000 )
{
Boost / = 2 ;
allocation_chunks / = 2 ;
}
2011-06-28 20:29:47 +04:00
// Calculate the number of bits to be spent on the gf or arf based on
// the boost number
gf_bits = ( int ) ( ( double ) Boost *
( cpi - > twopass . gf_group_bits /
( double ) allocation_chunks ) ) ;
2010-05-18 19:58:33 +04:00
2010-07-23 20:01:12 +04:00
// If the frame that is to be boosted is simpler than the average for
// the gf/arf group then use an alternative calculation
2010-05-18 19:58:33 +04:00
// based on the error score of the frame itself
if ( mod_frame_err < gf_group_err / ( double ) cpi - > baseline_gf_interval )
{
double alt_gf_grp_bits ;
int alt_gf_bits ;
2010-07-23 20:01:12 +04:00
alt_gf_grp_bits =
2011-05-20 01:16:39 +04:00
( double ) cpi - > twopass . kf_group_bits *
2010-07-23 20:01:12 +04:00
( mod_frame_err * ( double ) cpi - > baseline_gf_interval ) /
2011-05-20 01:16:39 +04:00
DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > twopass . kf_group_error_left ) ;
2010-07-23 20:01:12 +04:00
alt_gf_bits = ( int ) ( ( double ) Boost * ( alt_gf_grp_bits /
( double ) allocation_chunks ) ) ;
2010-05-18 19:58:33 +04:00
2011-06-16 21:01:27 +04:00
if ( gf_bits > alt_gf_bits )
2010-05-18 19:58:33 +04:00
{
2011-06-16 21:01:27 +04:00
gf_bits = alt_gf_bits ;
2010-05-18 19:58:33 +04:00
}
}
2010-07-23 20:01:12 +04:00
// Else if it is harder than other frames in the group make sure it at
// least receives an allocation in keeping with its relative error
// score, otherwise it may be worse off than an "un-boosted" frame
2010-05-18 19:58:33 +04:00
else
{
2010-07-23 20:01:12 +04:00
int alt_gf_bits =
2011-05-20 01:16:39 +04:00
( int ) ( ( double ) cpi - > twopass . kf_group_bits *
2010-07-23 20:01:12 +04:00
mod_frame_err /
2011-05-20 01:16:39 +04:00
DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > twopass . kf_group_error_left ) ) ;
2010-05-18 19:58:33 +04:00
2011-06-16 21:01:27 +04:00
if ( alt_gf_bits > gf_bits )
2010-05-18 19:58:33 +04:00
{
2011-06-16 21:01:27 +04:00
gf_bits = alt_gf_bits ;
2010-05-18 19:58:33 +04:00
}
}
2011-08-12 22:51:36 +04:00
// Apply an additional limit for CBR
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
if ( cpi - > twopass . gf_bits > ( cpi - > buffer_level > > 1 ) )
cpi - > twopass . gf_bits = cpi - > buffer_level > > 1 ;
}
2010-05-18 19:58:33 +04:00
// Dont allow a negative value for gf_bits
2011-06-16 21:01:27 +04:00
if ( gf_bits < 0 )
gf_bits = 0 ;
gf_bits + = cpi - > min_frame_bandwidth ; // Add in minimum for a frame
2010-05-18 19:58:33 +04:00
2011-06-16 21:01:27 +04:00
if ( i = = 0 )
{
cpi - > twopass . gf_bits = gf_bits ;
}
if ( i = = 1 | | ( ! cpi - > source_alt_ref_pending & & ( cpi - > common . frame_type ! = KEY_FRAME ) ) )
{
cpi - > per_frame_bandwidth = gf_bits ; // Per frame bit target for this frame
}
}
{
2010-05-18 19:58:33 +04:00
// Adjust KF group bits and error remainin
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_error_left - = gf_group_err ;
cpi - > twopass . kf_group_bits - = cpi - > twopass . gf_group_bits ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . kf_group_bits < 0 )
cpi - > twopass . kf_group_bits = 0 ;
2010-05-18 19:58:33 +04:00
// Note the error score left in the remaining frames of the group.
// For normal GFs we want to remove the error score for the first frame of the group (except in Key frame case where this has already happened)
if ( ! cpi - > source_alt_ref_pending & & cpi - > common . frame_type ! = KEY_FRAME )
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_group_error_left = gf_group_err - gf_first_frame_err ;
2010-05-18 19:58:33 +04:00
else
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_group_error_left = gf_group_err ;
2010-05-18 19:58:33 +04:00
2011-06-16 21:01:27 +04:00
cpi - > twopass . gf_group_bits - = cpi - > twopass . gf_bits - cpi - > min_frame_bandwidth ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . gf_group_bits < 0 )
cpi - > twopass . gf_group_bits = 0 ;
2010-05-18 19:58:33 +04:00
2011-08-17 17:14:23 +04:00
// This condition could fail if there are two kfs very close together
// despite (MIN_GF_INTERVAL) and would cause a devide by 0 in the
// calculation of cpi->twopass.alt_extra_bits.
if ( cpi - > baseline_gf_interval > = 3 )
2010-05-18 19:58:33 +04:00
{
2011-06-28 20:29:47 +04:00
# if NEW_BOOST
int boost = ( cpi - > source_alt_ref_pending )
? b_boost : cpi - > gfu_boost ;
# else
int boost = cpi - > gfu_boost ;
# endif
2011-08-17 17:14:23 +04:00
if ( boost > = 150 )
2011-06-28 20:29:47 +04:00
{
2011-08-17 17:14:23 +04:00
int pct_extra ;
2010-05-18 19:58:33 +04:00
2011-08-17 17:14:23 +04:00
pct_extra = ( boost - 100 ) / 50 ;
pct_extra = ( pct_extra > 20 ) ? 20 : pct_extra ;
cpi - > twopass . alt_extra_bits =
2011-06-28 20:29:47 +04:00
( cpi - > twopass . gf_group_bits * pct_extra ) / 100 ;
2011-08-17 17:14:23 +04:00
cpi - > twopass . gf_group_bits - = cpi - > twopass . alt_extra_bits ;
cpi - > twopass . alt_extra_bits / =
( ( cpi - > baseline_gf_interval - 1 ) > > 1 ) ;
2011-06-28 20:29:47 +04:00
}
else
2011-08-17 17:14:23 +04:00
cpi - > twopass . alt_extra_bits = 0 ;
2010-05-18 19:58:33 +04:00
}
2011-08-17 17:14:23 +04:00
else
cpi - > twopass . alt_extra_bits = 0 ;
2010-05-18 19:58:33 +04:00
}
2011-09-15 17:36:24 +04:00
// Adjustments based on a measure of complexity of the section
2010-05-18 19:58:33 +04:00
if ( cpi - > common . frame_type ! = KEY_FRAME )
{
FIRSTPASS_STATS sectionstats ;
double Ratio ;
2011-03-18 00:07:59 +03:00
zero_stats ( & sectionstats ) ;
2010-05-18 19:58:33 +04:00
reset_fpf_position ( cpi , start_pos ) ;
for ( i = 0 ; i < cpi - > baseline_gf_interval ; i + + )
{
2011-03-18 00:07:59 +03:00
input_stats ( cpi , & next_frame ) ;
accumulate_stats ( & sectionstats , & next_frame ) ;
2010-05-18 19:58:33 +04:00
}
2011-03-18 00:07:59 +03:00
avg_stats ( & sectionstats ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
cpi - > twopass . section_intra_rating =
2011-01-07 21:29:37 +03:00
sectionstats . intra_error /
DOUBLE_DIVIDE_CHECK ( sectionstats . coded_error ) ;
2010-05-18 19:58:33 +04:00
Ratio = sectionstats . intra_error / DOUBLE_DIVIDE_CHECK ( sectionstats . coded_error ) ;
//if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
//{
2011-05-20 01:16:39 +04:00
cpi - > twopass . section_max_qfactor = 1.0 - ( ( Ratio - 10.0 ) * 0.025 ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . section_max_qfactor < 0.80 )
cpi - > twopass . section_max_qfactor = 0.80 ;
2010-05-18 19:58:33 +04:00
//}
//else
2011-05-20 01:16:39 +04:00
// cpi->twopass.section_max_qfactor = 1.0;
2010-05-18 19:58:33 +04:00
reset_fpf_position ( cpi , start_pos ) ;
}
}
// Allocate bits to a normal frame that is neither a gf an arf or a key frame.
static void assign_std_frame_bits ( VP8_COMP * cpi , FIRSTPASS_STATS * this_frame )
{
int target_frame_size ; // gf_group_error_left
double modified_err ;
double err_fraction ; // What portion of the remaining GF group error is used by this frame
int max_bits = frame_max_bits ( cpi ) ; // Max for a single frame
// Calculate modified prediction error used in bit allocation
modified_err = calculate_modified_err ( cpi , this_frame ) ;
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . gf_group_error_left > 0 )
err_fraction = modified_err / cpi - > twopass . gf_group_error_left ; // What portion of the remaining GF group error is used by this frame
2010-05-18 19:58:33 +04:00
else
err_fraction = 0.0 ;
2011-05-20 01:16:39 +04:00
target_frame_size = ( int ) ( ( double ) cpi - > twopass . gf_group_bits * err_fraction ) ; // How many of those bits available for allocation should we give it?
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
// Clip to target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at the top end.
2010-05-18 19:58:33 +04:00
if ( target_frame_size < 0 )
target_frame_size = 0 ;
else
{
if ( target_frame_size > max_bits )
target_frame_size = max_bits ;
2011-05-20 01:16:39 +04:00
if ( target_frame_size > cpi - > twopass . gf_group_bits )
target_frame_size = cpi - > twopass . gf_group_bits ;
2010-05-18 19:58:33 +04:00
}
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_group_error_left - = modified_err ; // Adjust error remaining
cpi - > twopass . gf_group_bits - = target_frame_size ; // Adjust bits remaining
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . gf_group_bits < 0 )
cpi - > twopass . gf_group_bits = 0 ;
2010-05-18 19:58:33 +04:00
target_frame_size + = cpi - > min_frame_bandwidth ; // Add in the minimum number of bits that is set aside for every frame.
2011-08-17 17:14:23 +04:00
// Every other frame gets a few extra bits
if ( ( cpi - > common . frames_since_golden & 0x01 ) & &
( cpi - > frames_till_gf_update_due > 0 ) )
{
target_frame_size + = cpi - > twopass . alt_extra_bits ;
}
2010-05-18 19:58:33 +04:00
cpi - > per_frame_bandwidth = target_frame_size ; // Per frame bit target for this frame
}
void vp8_second_pass ( VP8_COMP * cpi )
{
int tmp_q ;
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
int frames_left = ( int ) ( cpi - > twopass . total_stats . count - cpi - > common . current_video_frame ) ;
2010-05-18 19:58:33 +04:00
2011-10-04 17:50:40 +04:00
FIRSTPASS_STATS this_frame = { 0 } ;
2010-05-18 19:58:33 +04:00
FIRSTPASS_STATS this_frame_copy ;
double this_frame_error ;
double this_frame_intra_error ;
double this_frame_coded_error ;
FIRSTPASS_STATS * start_pos ;
2011-09-15 17:36:24 +04:00
int overhead_bits ;
2011-05-20 01:16:39 +04:00
if ( ! cpi - > twopass . stats_in )
2010-05-18 19:58:33 +04:00
{
return ;
}
vp8_clear_system_state ( ) ;
2011-03-18 00:07:59 +03:00
if ( EOF = = input_stats ( cpi , & this_frame ) )
2010-05-18 19:58:33 +04:00
return ;
this_frame_error = this_frame . ssim_weighted_pred_err ;
this_frame_intra_error = this_frame . intra_error ;
this_frame_coded_error = this_frame . coded_error ;
2011-05-20 01:16:39 +04:00
start_pos = cpi - > twopass . stats_in ;
2010-05-18 19:58:33 +04:00
// keyframe and section processing !
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . frames_to_key = = 0 )
2010-05-18 19:58:33 +04:00
{
// Define next KF group and assign bits to it
vpx_memcpy ( & this_frame_copy , & this_frame , sizeof ( this_frame ) ) ;
2011-03-18 00:07:59 +03:00
find_next_key_frame ( cpi , & this_frame_copy ) ;
2010-05-18 19:58:33 +04:00
// Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
// outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
// This is temporary code till we decide what should really happen in this case.
if ( cpi - > oxcf . error_resilient_mode )
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . gf_group_bits = cpi - > twopass . kf_group_bits ;
cpi - > twopass . gf_group_error_left = cpi - > twopass . kf_group_error_left ;
cpi - > baseline_gf_interval = cpi - > twopass . frames_to_key ;
2010-05-18 19:58:33 +04:00
cpi - > frames_till_gf_update_due = cpi - > baseline_gf_interval ;
2011-12-22 02:21:29 +04:00
cpi - > source_alt_ref_pending = 0 ;
2010-05-18 19:58:33 +04:00
}
}
// Is this a GF / ARF (Note that a KF is always also a GF)
if ( cpi - > frames_till_gf_update_due = = 0 )
{
// Define next gf group and assign bits to it
vpx_memcpy ( & this_frame_copy , & this_frame , sizeof ( this_frame ) ) ;
define_gf_group ( cpi , & this_frame_copy ) ;
// If we are going to code an altref frame at the end of the group and the current frame is not a key frame....
// If the previous group used an arf this frame has already benefited from that arf boost and it should not be given extra bits
// If the previous group was NOT coded using arf we may want to apply some boost to this GF as well
if ( cpi - > source_alt_ref_pending & & ( cpi - > common . frame_type ! = KEY_FRAME ) )
{
// Assign a standard frames worth of bits from those allocated to the GF group
2011-06-16 21:01:27 +04:00
int bak = cpi - > per_frame_bandwidth ;
2010-05-18 19:58:33 +04:00
vpx_memcpy ( & this_frame_copy , & this_frame , sizeof ( this_frame ) ) ;
assign_std_frame_bits ( cpi , & this_frame_copy ) ;
2011-06-16 21:01:27 +04:00
cpi - > per_frame_bandwidth = bak ;
2010-05-18 19:58:33 +04:00
}
}
// Otherwise this is an ordinary frame
else
{
// Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
// outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
// This is temporary code till we decide what should really happen in this case.
if ( cpi - > oxcf . error_resilient_mode )
{
2011-05-20 01:16:39 +04:00
cpi - > frames_till_gf_update_due = cpi - > twopass . frames_to_key ;
2010-05-18 19:58:33 +04:00
if ( cpi - > common . frame_type ! = KEY_FRAME )
{
// Assign bits from those allocated to the GF group
vpx_memcpy ( & this_frame_copy , & this_frame , sizeof ( this_frame ) ) ;
assign_std_frame_bits ( cpi , & this_frame_copy ) ;
}
}
else
{
// Assign bits from those allocated to the GF group
vpx_memcpy ( & this_frame_copy , & this_frame , sizeof ( this_frame ) ) ;
assign_std_frame_bits ( cpi , & this_frame_copy ) ;
}
}
2010-06-09 18:03:48 +04:00
// Keep a globally available copy of this and the next frame's iiratio.
2011-05-20 01:16:39 +04:00
cpi - > twopass . this_iiratio = this_frame_intra_error /
2010-06-09 18:03:48 +04:00
DOUBLE_DIVIDE_CHECK ( this_frame_coded_error ) ;
2010-06-07 20:34:46 +04:00
{
FIRSTPASS_STATS next_frame ;
if ( lookup_next_frame_stats ( cpi , & next_frame ) ! = EOF )
2010-06-09 18:03:48 +04:00
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . next_iiratio = next_frame . intra_error /
2010-06-09 18:03:48 +04:00
DOUBLE_DIVIDE_CHECK ( next_frame . coded_error ) ;
}
2010-06-07 20:34:46 +04:00
}
2010-05-18 19:58:33 +04:00
// Set nominal per second bandwidth for this frame
cpi - > target_bandwidth = cpi - > per_frame_bandwidth * cpi - > output_frame_rate ;
if ( cpi - > target_bandwidth < 0 )
cpi - > target_bandwidth = 0 ;
2011-09-15 17:36:24 +04:00
// Account for mv, mode and other overheads.
overhead_bits = estimate_modemvcost (
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
cpi , & cpi - > twopass . total_left_stats ) ;
2011-09-15 17:36:24 +04:00
// Special case code for first frame.
2010-05-18 19:58:33 +04:00
if ( cpi - > common . current_video_frame = = 0 )
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . est_max_qcorrection_factor = 1.0 ;
2010-05-18 19:58:33 +04:00
2011-09-15 17:36:24 +04:00
// Set a cq_level in constrained quality mode.
2011-01-07 21:29:37 +03:00
if ( cpi - > oxcf . end_usage = = USAGE_CONSTRAINED_QUALITY )
{
int est_cq ;
est_cq =
estimate_cq ( cpi ,
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
& cpi - > twopass . total_left_stats ,
2011-09-15 17:36:24 +04:00
( int ) ( cpi - > twopass . bits_left / frames_left ) ,
overhead_bits ) ;
2011-01-07 21:29:37 +03:00
cpi - > cq_target_quality = cpi - > oxcf . cq_level ;
if ( est_cq > cpi - > cq_target_quality )
cpi - > cq_target_quality = est_cq ;
}
// guess at maxq needed in 2nd pass
2011-05-20 01:16:39 +04:00
cpi - > twopass . maxq_max_limit = cpi - > worst_quality ;
cpi - > twopass . maxq_min_limit = cpi - > best_quality ;
2011-09-15 17:36:24 +04:00
tmp_q = estimate_max_q (
cpi ,
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
& cpi - > twopass . total_left_stats ,
2011-09-15 17:36:24 +04:00
( int ) ( cpi - > twopass . bits_left / frames_left ) ,
overhead_bits ) ;
2011-01-07 19:33:59 +03:00
2011-01-07 21:29:37 +03:00
// Limit the maxq value returned subsequently.
2011-01-10 19:41:53 +03:00
// This increases the risk of overspend or underspend if the initial
2011-01-07 19:33:59 +03:00
// estimate for the clip is bad, but helps prevent excessive
// variation in Q, especially near the end of a clip
// where for example a small overspend may cause Q to crash
2011-05-20 01:16:39 +04:00
cpi - > twopass . maxq_max_limit = ( ( tmp_q + 32 ) < cpi - > worst_quality )
2011-01-07 19:33:59 +03:00
? ( tmp_q + 32 ) : cpi - > worst_quality ;
2011-05-20 01:16:39 +04:00
cpi - > twopass . maxq_min_limit = ( ( tmp_q - 32 ) > cpi - > best_quality )
2011-01-07 19:33:59 +03:00
? ( tmp_q - 32 ) : cpi - > best_quality ;
cpi - > active_worst_quality = tmp_q ;
cpi - > ni_av_qi = tmp_q ;
2010-05-18 19:58:33 +04:00
}
2011-01-07 21:29:37 +03:00
2010-11-10 13:09:45 +03:00
// The last few frames of a clip almost always have to few or too many
// bits and for the sake of over exact rate control we dont want to make
// radical adjustments to the allowed quantizer range just to use up a
// few surplus bits or get beneath the target rate.
else if ( ( cpi - > common . current_video_frame <
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
( ( ( unsigned int ) cpi - > twopass . total_stats . count * 255 ) > > 8 ) ) & &
2010-11-10 13:09:45 +03:00
( ( cpi - > common . current_video_frame + cpi - > baseline_gf_interval ) <
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
( unsigned int ) cpi - > twopass . total_stats . count ) )
2010-05-18 19:58:33 +04:00
{
if ( frames_left < 1 )
frames_left = 1 ;
2011-09-15 17:36:24 +04:00
tmp_q = estimate_max_q (
cpi ,
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
& cpi - > twopass . total_left_stats ,
2011-09-15 17:36:24 +04:00
( int ) ( cpi - > twopass . bits_left / frames_left ) ,
overhead_bits ) ;
2010-05-18 19:58:33 +04:00
// Move active_worst_quality but in a damped way
if ( tmp_q > cpi - > active_worst_quality )
cpi - > active_worst_quality + + ;
else if ( tmp_q < cpi - > active_worst_quality )
cpi - > active_worst_quality - - ;
2011-09-15 17:36:24 +04:00
cpi - > active_worst_quality =
( ( cpi - > active_worst_quality * 3 ) + tmp_q + 2 ) / 4 ;
2010-05-18 19:58:33 +04:00
}
2011-05-20 01:16:39 +04:00
cpi - > twopass . frames_to_key - - ;
2011-09-15 17:36:24 +04:00
// Update the total stats remaining sturcture
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
subtract_stats ( & cpi - > twopass . total_left_stats , & this_frame ) ;
2010-05-18 19:58:33 +04:00
}
2011-12-22 02:21:29 +04:00
static int test_candidate_kf ( VP8_COMP * cpi , FIRSTPASS_STATS * last_frame , FIRSTPASS_STATS * this_frame , FIRSTPASS_STATS * next_frame )
2010-05-18 19:58:33 +04:00
{
2011-12-22 02:21:29 +04:00
int is_viable_kf = 0 ;
2010-05-18 19:58:33 +04:00
// Does the frame satisfy the primary criteria of a key frame
// If so, then examine how well it predicts subsequent frames
if ( ( this_frame - > pcnt_second_ref < 0.10 ) & &
( next_frame - > pcnt_second_ref < 0.10 ) & &
( ( this_frame - > pcnt_inter < 0.05 ) | |
(
2011-03-07 18:58:07 +03:00
( ( this_frame - > pcnt_inter - this_frame - > pcnt_neutral ) < .25 ) & &
2010-05-18 19:58:33 +04:00
( ( this_frame - > intra_error / DOUBLE_DIVIDE_CHECK ( this_frame - > coded_error ) ) < 2.5 ) & &
( ( fabs ( last_frame - > coded_error - this_frame - > coded_error ) / DOUBLE_DIVIDE_CHECK ( this_frame - > coded_error ) > .40 ) | |
( fabs ( last_frame - > intra_error - this_frame - > intra_error ) / DOUBLE_DIVIDE_CHECK ( this_frame - > intra_error ) > .40 ) | |
( ( next_frame - > intra_error / DOUBLE_DIVIDE_CHECK ( next_frame - > coded_error ) ) > 3.5 )
)
)
)
)
{
int i ;
FIRSTPASS_STATS * start_pos ;
FIRSTPASS_STATS local_next_frame ;
double boost_score = 0.0 ;
double old_boost_score = 0.0 ;
double decay_accumulator = 1.0 ;
double next_iiratio ;
vpx_memcpy ( & local_next_frame , next_frame , sizeof ( * next_frame ) ) ;
// Note the starting file position so we can reset to it
2011-05-20 01:16:39 +04:00
start_pos = cpi - > twopass . stats_in ;
2010-05-18 19:58:33 +04:00
// Examine how well the key frame predicts subsequent frames
for ( i = 0 ; i < 16 ; i + + )
{
next_iiratio = ( IIKFACTOR1 * local_next_frame . intra_error / DOUBLE_DIVIDE_CHECK ( local_next_frame . coded_error ) ) ;
if ( next_iiratio > RMAX )
next_iiratio = RMAX ;
// Cumulative effect of decay in prediction quality
if ( local_next_frame . pcnt_inter > 0.85 )
decay_accumulator = decay_accumulator * local_next_frame . pcnt_inter ;
else
decay_accumulator = decay_accumulator * ( ( 0.85 + local_next_frame . pcnt_inter ) / 2.0 ) ;
//decay_accumulator = decay_accumulator * local_next_frame.pcnt_inter;
// Keep a running total
boost_score + = ( decay_accumulator * next_iiratio ) ;
// Test various breakout clauses
if ( ( local_next_frame . pcnt_inter < 0.05 ) | |
( next_iiratio < 1.5 ) | |
2011-03-07 18:58:07 +03:00
( ( ( local_next_frame . pcnt_inter -
local_next_frame . pcnt_neutral ) < 0.20 ) & &
( next_iiratio < 3.0 ) ) | |
2010-05-18 19:58:33 +04:00
( ( boost_score - old_boost_score ) < 0.5 ) | |
( local_next_frame . intra_error < 200 )
)
{
break ;
}
old_boost_score = boost_score ;
// Get the next frame details
2011-03-18 00:07:59 +03:00
if ( EOF = = input_stats ( cpi , & local_next_frame ) )
2010-05-18 19:58:33 +04:00
break ;
}
// If there is tolerable prediction for at least the next 3 frames then break out else discard this pottential key frame and move on
if ( boost_score > 5.0 & & ( i > 3 ) )
2011-12-22 02:21:29 +04:00
is_viable_kf = 1 ;
2010-05-18 19:58:33 +04:00
else
{
// Reset the file position
reset_fpf_position ( cpi , start_pos ) ;
2011-12-22 02:21:29 +04:00
is_viable_kf = 0 ;
2010-05-18 19:58:33 +04:00
}
}
return is_viable_kf ;
}
2011-03-18 00:07:59 +03:00
static void find_next_key_frame ( VP8_COMP * cpi , FIRSTPASS_STATS * this_frame )
2010-05-18 19:58:33 +04:00
{
2011-03-07 18:11:09 +03:00
int i , j ;
2010-05-18 19:58:33 +04:00
FIRSTPASS_STATS last_frame ;
FIRSTPASS_STATS first_frame ;
FIRSTPASS_STATS next_frame ;
FIRSTPASS_STATS * start_position ;
2011-03-07 18:11:09 +03:00
double decay_accumulator = 1.0 ;
2010-05-18 19:58:33 +04:00
double boost_score = 0 ;
double old_boost_score = 0.0 ;
double loop_decay_rate ;
double kf_mod_err = 0.0 ;
double kf_group_err = 0.0 ;
double kf_group_intra_err = 0.0 ;
double kf_group_coded_err = 0.0 ;
2011-03-07 18:11:09 +03:00
double recent_loop_decay [ 8 ] = { 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 } ;
2010-05-18 19:58:33 +04:00
2010-06-11 22:33:49 +04:00
vpx_memset ( & next_frame , 0 , sizeof ( next_frame ) ) ; // assure clean
2010-05-18 19:58:33 +04:00
vp8_clear_system_state ( ) ; //__asm emms;
2011-05-20 01:16:39 +04:00
start_position = cpi - > twopass . stats_in ;
2010-05-18 19:58:33 +04:00
cpi - > common . frame_type = KEY_FRAME ;
2011-01-12 20:08:42 +03:00
// is this a forced key frame by interval
cpi - > this_key_frame_forced = cpi - > next_key_frame_forced ;
2010-05-18 19:58:33 +04:00
// Clear the alt ref active flag as this can never be active on a key frame
2011-12-22 02:21:29 +04:00
cpi - > source_alt_ref_active = 0 ;
2010-05-18 19:58:33 +04:00
// Kf is always a gf so clear frames till next gf counter
cpi - > frames_till_gf_update_due = 0 ;
2011-05-20 01:16:39 +04:00
cpi - > twopass . frames_to_key = 1 ;
2010-05-18 19:58:33 +04:00
// Take a copy of the initial frame details
vpx_memcpy ( & first_frame , this_frame , sizeof ( * this_frame ) ) ;
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_bits = 0 ; // Total bits avaialable to kf group
cpi - > twopass . kf_group_error_left = 0 ; // Group modified error score.
2010-05-18 19:58:33 +04:00
kf_mod_err = calculate_modified_err ( cpi , this_frame ) ;
// find the next keyframe
2011-03-07 18:11:09 +03:00
i = 0 ;
2011-05-20 01:16:39 +04:00
while ( cpi - > twopass . stats_in < cpi - > twopass . stats_in_end )
2010-05-18 19:58:33 +04:00
{
// Accumulate kf group error
kf_group_err + = calculate_modified_err ( cpi , this_frame ) ;
// These figures keep intra and coded error counts for all frames including key frames in the group.
// The effect of the key frame itself can be subtracted out using the first_frame data collected above
kf_group_intra_err + = this_frame - > intra_error ;
kf_group_coded_err + = this_frame - > coded_error ;
2010-08-20 15:27:26 +04:00
// load a the next frame's stats
2010-05-18 19:58:33 +04:00
vpx_memcpy ( & last_frame , this_frame , sizeof ( * this_frame ) ) ;
2011-03-18 00:07:59 +03:00
input_stats ( cpi , this_frame ) ;
2010-05-18 19:58:33 +04:00
// Provided that we are not at the end of the file...
2010-08-20 15:27:26 +04:00
if ( cpi - > oxcf . auto_key
& & lookup_next_frame_stats ( cpi , & next_frame ) ! = EOF )
2010-05-18 19:58:33 +04:00
{
2011-03-07 18:11:09 +03:00
// Normal scene cut check
2011-08-17 17:14:23 +04:00
if ( ( i > = MIN_GF_INTERVAL ) & &
test_candidate_kf ( cpi , & last_frame , this_frame , & next_frame ) )
{
2010-08-20 15:27:26 +04:00
break ;
2011-08-17 17:14:23 +04:00
}
2010-05-18 19:58:33 +04:00
2011-03-07 18:11:09 +03:00
// How fast is prediction quality decaying
loop_decay_rate = get_prediction_decay_rate ( cpi , & next_frame ) ;
// We want to know something about the recent past... rather than
// as used elsewhere where we are concened with decay in prediction
// quality since the last GF or KF.
recent_loop_decay [ i % 8 ] = loop_decay_rate ;
decay_accumulator = 1.0 ;
for ( j = 0 ; j < 8 ; j + + )
{
decay_accumulator = decay_accumulator * recent_loop_decay [ j ] ;
}
// Special check for transition or high motion followed by a
// to a static scene.
if ( detect_transition_to_still ( cpi , i ,
( cpi - > key_frame_frequency - i ) ,
loop_decay_rate ,
decay_accumulator ) )
{
break ;
}
2010-08-20 15:27:26 +04:00
// Step on to the next frame
2011-05-20 01:16:39 +04:00
cpi - > twopass . frames_to_key + + ;
2010-05-18 19:58:33 +04:00
2010-08-20 15:27:26 +04:00
// If we don't have a real key frame within the next two
// forcekeyframeevery intervals then break out of the loop.
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . frames_to_key > = 2 * ( int ) cpi - > key_frame_frequency )
2010-08-20 15:27:26 +04:00
break ;
} else
2011-05-20 01:16:39 +04:00
cpi - > twopass . frames_to_key + + ;
2011-03-07 18:11:09 +03:00
i + + ;
2010-05-18 19:58:33 +04:00
}
// If there is a max kf interval set by the user we must obey it.
// We already breakout of the loop above at 2x max.
// This code centers the extra kf if the actual natural
// interval is between 1x and 2x
2010-08-20 15:27:26 +04:00
if ( cpi - > oxcf . auto_key
2011-05-20 01:16:39 +04:00
& & cpi - > twopass . frames_to_key > ( int ) cpi - > key_frame_frequency )
2010-05-18 19:58:33 +04:00
{
2011-05-20 01:16:39 +04:00
FIRSTPASS_STATS * current_pos = cpi - > twopass . stats_in ;
2011-01-25 15:29:06 +03:00
FIRSTPASS_STATS tmp_frame ;
2011-05-20 01:16:39 +04:00
cpi - > twopass . frames_to_key / = 2 ;
2010-05-18 19:58:33 +04:00
2011-01-25 15:29:06 +03:00
// Copy first frame details
vpx_memcpy ( & tmp_frame , & first_frame , sizeof ( first_frame ) ) ;
// Reset to the start of the group
reset_fpf_position ( cpi , start_position ) ;
kf_group_err = 0 ;
kf_group_intra_err = 0 ;
kf_group_coded_err = 0 ;
// Rescan to get the correct error data for the forced kf group
2011-05-20 01:16:39 +04:00
for ( i = 0 ; i < cpi - > twopass . frames_to_key ; i + + )
2011-01-25 15:29:06 +03:00
{
// Accumulate kf group errors
kf_group_err + = calculate_modified_err ( cpi , & tmp_frame ) ;
kf_group_intra_err + = tmp_frame . intra_error ;
kf_group_coded_err + = tmp_frame . coded_error ;
// Load a the next frame's stats
2011-03-18 00:07:59 +03:00
input_stats ( cpi , & tmp_frame ) ;
2011-01-25 15:29:06 +03:00
}
// Reset to the start of the group
reset_fpf_position ( cpi , current_pos ) ;
2011-01-12 20:08:42 +03:00
2011-12-22 02:21:29 +04:00
cpi - > next_key_frame_forced = 1 ;
2010-05-18 19:58:33 +04:00
}
2011-01-12 20:08:42 +03:00
else
2011-12-22 02:21:29 +04:00
cpi - > next_key_frame_forced = 0 ;
2010-05-18 19:58:33 +04:00
// Special case for the last frame of the file
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . stats_in > = cpi - > twopass . stats_in_end )
2010-05-18 19:58:33 +04:00
{
// Accumulate kf group error
kf_group_err + = calculate_modified_err ( cpi , this_frame ) ;
// These figures keep intra and coded error counts for all frames including key frames in the group.
// The effect of the key frame itself can be subtracted out using the first_frame data collected above
kf_group_intra_err + = this_frame - > intra_error ;
kf_group_coded_err + = this_frame - > coded_error ;
}
// Calculate the number of bits that should be assigned to the kf group.
2011-05-20 01:16:39 +04:00
if ( ( cpi - > twopass . bits_left > 0 ) & & ( cpi - > twopass . modified_error_left > 0.0 ) )
2010-05-18 19:58:33 +04:00
{
2010-07-23 20:01:12 +04:00
// Max for a single normal frame (not key frame)
int max_bits = frame_max_bits ( cpi ) ;
// Maximum bits for the kf group
2011-07-26 05:44:59 +04:00
int64_t max_grp_bits ;
2010-05-18 19:58:33 +04:00
2010-07-23 20:01:12 +04:00
// Default allocation based on bits left and relative
// complexity of the section
2011-07-26 05:44:59 +04:00
cpi - > twopass . kf_group_bits = ( int64_t ) ( cpi - > twopass . bits_left *
2010-07-23 20:01:12 +04:00
( kf_group_err /
2011-05-20 01:16:39 +04:00
cpi - > twopass . modified_error_left ) ) ;
2010-05-18 19:58:33 +04:00
// Clip based on maximum per frame rate defined by the user.
2011-07-26 05:44:59 +04:00
max_grp_bits = ( int64_t ) max_bits * ( int64_t ) cpi - > twopass . frames_to_key ;
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . kf_group_bits > max_grp_bits )
cpi - > twopass . kf_group_bits = max_grp_bits ;
2010-05-18 19:58:33 +04:00
// Additional special case for CBR if buffer is getting full.
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
2010-07-23 20:01:12 +04:00
int opt_buffer_lvl = cpi - > oxcf . optimal_buffer_level ;
int buffer_lvl = cpi - > buffer_level ;
// If the buffer is near or above the optimal and this kf group is
// not being allocated much then increase the allocation a bit.
if ( buffer_lvl > = opt_buffer_lvl )
2010-05-18 19:58:33 +04:00
{
2010-07-23 20:01:12 +04:00
int high_water_mark = ( opt_buffer_lvl +
cpi - > oxcf . maximum_buffer_size ) > > 1 ;
2011-07-26 05:44:59 +04:00
int64_t av_group_bits ;
2010-07-23 20:01:12 +04:00
// Av bits per frame * number of frames
2011-07-26 05:44:59 +04:00
av_group_bits = ( int64_t ) cpi - > av_per_frame_bandwidth *
( int64_t ) cpi - > twopass . frames_to_key ;
2010-05-18 19:58:33 +04:00
// We are at or above the maximum.
if ( cpi - > buffer_level > = high_water_mark )
{
2011-07-26 05:44:59 +04:00
int64_t min_group_bits ;
2010-07-23 20:01:12 +04:00
min_group_bits = av_group_bits +
2011-07-26 05:44:59 +04:00
( int64_t ) ( buffer_lvl -
2010-07-23 20:01:12 +04:00
high_water_mark ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . kf_group_bits < min_group_bits )
cpi - > twopass . kf_group_bits = min_group_bits ;
2010-05-18 19:58:33 +04:00
}
// We are above optimal but below the maximum
2011-05-20 01:16:39 +04:00
else if ( cpi - > twopass . kf_group_bits < av_group_bits )
2010-05-18 19:58:33 +04:00
{
2011-07-26 05:44:59 +04:00
int64_t bits_below_av = av_group_bits -
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_bits ;
2010-07-23 20:01:12 +04:00
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_bits + =
2011-07-26 05:44:59 +04:00
( int64_t ) ( ( double ) bits_below_av *
2010-07-23 20:01:12 +04:00
( double ) ( buffer_lvl - opt_buffer_lvl ) /
( double ) ( high_water_mark - opt_buffer_lvl ) ) ;
2010-05-18 19:58:33 +04:00
}
}
}
}
else
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_bits = 0 ;
2010-05-18 19:58:33 +04:00
// Reset the first pass file position
reset_fpf_position ( cpi , start_position ) ;
// determine how big to make this keyframe based on how well the subsequent frames use inter blocks
decay_accumulator = 1.0 ;
boost_score = 0.0 ;
loop_decay_rate = 1.00 ; // Starting decay rate
2011-05-20 01:16:39 +04:00
for ( i = 0 ; i < cpi - > twopass . frames_to_key ; i + + )
2010-05-18 19:58:33 +04:00
{
double r ;
2011-03-18 00:07:59 +03:00
if ( EOF = = input_stats ( cpi , & next_frame ) )
2010-05-18 19:58:33 +04:00
break ;
2011-05-20 01:16:39 +04:00
if ( next_frame . intra_error > cpi - > twopass . kf_intra_err_min )
2011-01-04 20:55:49 +03:00
r = ( IIKFACTOR2 * next_frame . intra_error /
DOUBLE_DIVIDE_CHECK ( next_frame . coded_error ) ) ;
else
2011-05-20 01:16:39 +04:00
r = ( IIKFACTOR2 * cpi - > twopass . kf_intra_err_min /
2011-01-04 20:55:49 +03:00
DOUBLE_DIVIDE_CHECK ( next_frame . coded_error ) ) ;
2010-05-18 19:58:33 +04:00
if ( r > RMAX )
r = RMAX ;
2011-03-07 18:11:09 +03:00
// How fast is prediction quality decaying
loop_decay_rate = get_prediction_decay_rate ( cpi , & next_frame ) ;
2010-05-18 19:58:33 +04:00
decay_accumulator = decay_accumulator * loop_decay_rate ;
2010-10-02 20:31:46 +04:00
decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator ;
2010-05-18 19:58:33 +04:00
boost_score + = ( decay_accumulator * r ) ;
if ( ( i > MIN_GF_INTERVAL ) & &
( ( boost_score - old_boost_score ) < 1.0 ) )
{
break ;
}
old_boost_score = boost_score ;
}
if ( 1 )
{
FIRSTPASS_STATS sectionstats ;
double Ratio ;
2011-03-18 00:07:59 +03:00
zero_stats ( & sectionstats ) ;
2010-05-18 19:58:33 +04:00
reset_fpf_position ( cpi , start_position ) ;
2011-05-20 01:16:39 +04:00
for ( i = 0 ; i < cpi - > twopass . frames_to_key ; i + + )
2010-05-18 19:58:33 +04:00
{
2011-03-18 00:07:59 +03:00
input_stats ( cpi , & next_frame ) ;
accumulate_stats ( & sectionstats , & next_frame ) ;
2010-05-18 19:58:33 +04:00
}
2011-03-18 00:07:59 +03:00
avg_stats ( & sectionstats ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
cpi - > twopass . section_intra_rating =
sectionstats . intra_error
/ DOUBLE_DIVIDE_CHECK ( sectionstats . coded_error ) ;
2010-05-18 19:58:33 +04:00
Ratio = sectionstats . intra_error / DOUBLE_DIVIDE_CHECK ( sectionstats . coded_error ) ;
// if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
//{
2011-05-20 01:16:39 +04:00
cpi - > twopass . section_max_qfactor = 1.0 - ( ( Ratio - 10.0 ) * 0.025 ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . section_max_qfactor < 0.80 )
cpi - > twopass . section_max_qfactor = 0.80 ;
2010-05-18 19:58:33 +04:00
//}
//else
2011-05-20 01:16:39 +04:00
// cpi->twopass.section_max_qfactor = 1.0;
2010-05-18 19:58:33 +04:00
}
// When using CBR apply additional buffer fullness related upper limits
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
double max_boost ;
if ( cpi - > drop_frames_allowed )
{
int df_buffer_level = cpi - > oxcf . drop_frames_water_mark * ( cpi - > oxcf . optimal_buffer_level / 100 ) ;
if ( cpi - > buffer_level > df_buffer_level )
max_boost = ( ( double ) ( ( cpi - > buffer_level - df_buffer_level ) * 2 / 3 ) * 16.0 ) / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > av_per_frame_bandwidth ) ;
else
max_boost = 0.0 ;
}
else if ( cpi - > buffer_level > 0 )
{
max_boost = ( ( double ) ( cpi - > buffer_level * 2 / 3 ) * 16.0 ) / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > av_per_frame_bandwidth ) ;
}
else
{
max_boost = 0.0 ;
}
if ( boost_score > max_boost )
boost_score = max_boost ;
}
// Reset the first pass file position
reset_fpf_position ( cpi , start_position ) ;
// Work out how many bits to allocate for the key frame itself
if ( 1 )
{
int kf_boost = boost_score ;
int allocation_chunks ;
2011-05-20 01:16:39 +04:00
int Counter = cpi - > twopass . frames_to_key ;
2010-05-18 19:58:33 +04:00
int alt_kf_bits ;
2010-07-22 16:07:32 +04:00
YV12_BUFFER_CONFIG * lst_yv12 = & cpi - > common . yv12_fb [ cpi - > common . lst_fb_idx ] ;
2010-05-18 19:58:33 +04:00
// Min boost based on kf interval
#if 0
while ( ( kf_boost < 48 ) & & ( Counter > 0 ) )
{
Counter - = 2 ;
kf_boost + + ;
}
# endif
if ( kf_boost < 48 )
{
kf_boost + = ( ( Counter + 1 ) > > 1 ) ;
if ( kf_boost > 48 ) kf_boost = 48 ;
}
// bigger frame sizes need larger kf boosts, smaller frames smaller boosts...
2010-07-22 16:07:32 +04:00
if ( ( lst_yv12 - > y_width * lst_yv12 - > y_height ) > ( 320 * 240 ) )
kf_boost + = 2 * ( lst_yv12 - > y_width * lst_yv12 - > y_height ) / ( 320 * 240 ) ;
else if ( ( lst_yv12 - > y_width * lst_yv12 - > y_height ) < ( 320 * 240 ) )
kf_boost - = 4 * ( 320 * 240 ) / ( lst_yv12 - > y_width * lst_yv12 - > y_height ) ;
2010-05-18 19:58:33 +04:00
kf_boost = ( int ) ( ( double ) kf_boost * 100.0 ) > > 4 ; // Scale 16 to 100
// Adjustment to boost based on recent average q
2011-01-04 20:55:49 +03:00
//kf_boost = kf_boost * vp8_kf_boost_qadjustment[cpi->ni_av_qi] / 100;
2010-05-18 19:58:33 +04:00
if ( kf_boost < 250 ) // Min KF boost
kf_boost = 250 ;
// We do three calculations for kf size.
// The first is based on the error score for the whole kf group.
// The second (optionaly) on the key frames own error if this is smaller than the average for the group.
// The final one insures that the frame receives at least the allocation it would have received based on its own error score vs the error score remaining
2011-05-20 01:16:39 +04:00
allocation_chunks = ( ( cpi - > twopass . frames_to_key - 1 ) * 100 ) + kf_boost ; // cpi->twopass.frames_to_key-1 because key frame itself is taken care of by kf_boost
2010-05-18 19:58:33 +04:00
// Normalize Altboost and allocations chunck down to prevent overflow
while ( kf_boost > 1000 )
{
kf_boost / = 2 ;
allocation_chunks / = 2 ;
}
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_bits = ( cpi - > twopass . kf_group_bits < 0 ) ? 0 : cpi - > twopass . kf_group_bits ;
2010-05-18 19:58:33 +04:00
// Calculate the number of bits to be spent on the key frame
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_bits = ( int ) ( ( double ) kf_boost * ( ( double ) cpi - > twopass . kf_group_bits / ( double ) allocation_chunks ) ) ;
2010-05-18 19:58:33 +04:00
// Apply an additional limit for CBR
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . kf_bits > ( ( 3 * cpi - > buffer_level ) > > 2 ) )
cpi - > twopass . kf_bits = ( 3 * cpi - > buffer_level ) > > 2 ;
2010-05-18 19:58:33 +04:00
}
2010-08-20 15:27:26 +04:00
// If the key frame is actually easier than the average for the
// kf group (which does sometimes happen... eg a blank intro frame)
// Then use an alternate calculation based on the kf error score
// which should give a smaller key frame.
2011-05-20 01:16:39 +04:00
if ( kf_mod_err < kf_group_err / cpi - > twopass . frames_to_key )
2010-05-18 19:58:33 +04:00
{
2010-08-20 15:27:26 +04:00
double alt_kf_grp_bits =
2011-05-20 01:16:39 +04:00
( ( double ) cpi - > twopass . bits_left *
( kf_mod_err * ( double ) cpi - > twopass . frames_to_key ) /
DOUBLE_DIVIDE_CHECK ( cpi - > twopass . modified_error_left ) ) ;
2010-05-18 19:58:33 +04:00
2010-08-20 15:27:26 +04:00
alt_kf_bits = ( int ) ( ( double ) kf_boost *
( alt_kf_grp_bits / ( double ) allocation_chunks ) ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( cpi - > twopass . kf_bits > alt_kf_bits )
2010-05-18 19:58:33 +04:00
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_bits = alt_kf_bits ;
2010-05-18 19:58:33 +04:00
}
}
2010-08-20 15:27:26 +04:00
// Else if it is much harder than other frames in the group make sure
// it at least receives an allocation in keeping with its relative
// error score
2010-05-18 19:58:33 +04:00
else
{
2010-08-20 15:27:26 +04:00
alt_kf_bits =
2011-05-20 01:16:39 +04:00
( int ) ( ( double ) cpi - > twopass . bits_left *
2010-08-20 15:27:26 +04:00
( kf_mod_err /
2011-05-20 01:16:39 +04:00
DOUBLE_DIVIDE_CHECK ( cpi - > twopass . modified_error_left ) ) ) ;
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
if ( alt_kf_bits > cpi - > twopass . kf_bits )
2010-05-18 19:58:33 +04:00
{
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_bits = alt_kf_bits ;
2010-05-18 19:58:33 +04:00
}
}
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_bits - = cpi - > twopass . kf_bits ;
cpi - > twopass . kf_bits + = cpi - > min_frame_bandwidth ; // Add in the minimum frame allowance
2010-05-18 19:58:33 +04:00
2011-05-20 01:16:39 +04:00
cpi - > per_frame_bandwidth = cpi - > twopass . kf_bits ; // Peer frame bit target for this frame
cpi - > target_bandwidth = cpi - > twopass . kf_bits * cpi - > output_frame_rate ; // Convert to a per second bitrate
2010-05-18 19:58:33 +04:00
}
// Note the total error score of the kf group minus the key frame itself
2011-05-20 01:16:39 +04:00
cpi - > twopass . kf_group_error_left = ( int ) ( kf_group_err - kf_mod_err ) ;
2010-05-18 19:58:33 +04:00
// Adjust the count of total modified error left.
// The count of bits left is adjusted elsewhere based on real coded frame sizes
2011-05-20 01:16:39 +04:00
cpi - > twopass . modified_error_left - = kf_group_err ;
2010-05-18 19:58:33 +04:00
if ( cpi - > oxcf . allow_spatial_resampling )
{
2011-12-22 02:21:29 +04:00
int resample_trigger = 0 ;
int last_kf_resampled = 0 ;
2010-05-18 19:58:33 +04:00
int kf_q ;
int scale_val = 0 ;
int hr , hs , vr , vs ;
int new_width = cpi - > oxcf . Width ;
int new_height = cpi - > oxcf . Height ;
int projected_buffer_level = cpi - > buffer_level ;
int tmp_q ;
double projected_bits_perframe ;
double group_iiratio = ( kf_group_intra_err - first_frame . intra_error ) / ( kf_group_coded_err - first_frame . coded_error ) ;
2011-05-20 01:16:39 +04:00
double err_per_frame = kf_group_err / cpi - > twopass . frames_to_key ;
2010-05-18 19:58:33 +04:00
double bits_per_frame ;
double av_bits_per_frame ;
double effective_size_ratio ;
if ( ( cpi - > common . Width ! = cpi - > oxcf . Width ) | | ( cpi - > common . Height ! = cpi - > oxcf . Height ) )
2011-12-22 02:21:29 +04:00
last_kf_resampled = 1 ;
2010-05-18 19:58:33 +04:00
// Set back to unscaled by defaults
cpi - > common . horiz_scale = NORMAL ;
cpi - > common . vert_scale = NORMAL ;
// Calculate Average bits per frame.
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
//av_bits_per_frame = cpi->twopass.bits_left/(double)(cpi->twopass.total_stats.count - cpi->common.current_video_frame);
2011-11-11 22:47:20 +04:00
av_bits_per_frame = cpi - > oxcf . target_bandwidth / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > frame_rate ) ;
2010-05-18 19:58:33 +04:00
//if ( av_bits_per_frame < 0.0 )
// av_bits_per_frame = 0.0
// CBR... Use the clip average as the target for deciding resample
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
bits_per_frame = av_bits_per_frame ;
}
// In VBR we want to avoid downsampling in easy section unless we are under extreme pressure
// So use the larger of target bitrate for this sectoion or average bitrate for sequence
else
{
2011-05-20 01:16:39 +04:00
bits_per_frame = cpi - > twopass . kf_group_bits / cpi - > twopass . frames_to_key ; // This accounts for how hard the section is...
2010-05-18 19:58:33 +04:00
if ( bits_per_frame < av_bits_per_frame ) // Dont turn to resampling in easy sections just because they have been assigned a small number of bits
bits_per_frame = av_bits_per_frame ;
}
// bits_per_frame should comply with our minimum
if ( bits_per_frame < ( cpi - > oxcf . target_bandwidth * cpi - > oxcf . two_pass_vbrmin_section / 100 ) )
bits_per_frame = ( cpi - > oxcf . target_bandwidth * cpi - > oxcf . two_pass_vbrmin_section / 100 ) ;
// Work out if spatial resampling is necessary
2011-03-10 19:13:44 +03:00
kf_q = estimate_kf_group_q ( cpi , err_per_frame , bits_per_frame , group_iiratio ) ;
2010-05-18 19:58:33 +04:00
// If we project a required Q higher than the maximum allowed Q then make a guess at the actual size of frames in this section
projected_bits_perframe = bits_per_frame ;
tmp_q = kf_q ;
while ( tmp_q > cpi - > worst_quality )
{
projected_bits_perframe * = 1.04 ;
tmp_q - - ;
}
// Guess at buffer level at the end of the section
2011-05-20 01:16:39 +04:00
projected_buffer_level = cpi - > buffer_level - ( int ) ( ( projected_bits_perframe - av_bits_per_frame ) * cpi - > twopass . frames_to_key ) ;
2010-05-18 19:58:33 +04:00
if ( 0 )
{
FILE * f = fopen ( " Subsamle.stt " , " a " ) ;
2011-05-20 01:16:39 +04:00
fprintf ( f , " %8d %8d %8d %8d %12.0f %8d %8d %8d \n " , cpi - > common . current_video_frame , kf_q , cpi - > common . horiz_scale , cpi - > common . vert_scale , kf_group_err / cpi - > twopass . frames_to_key , ( int ) ( cpi - > twopass . kf_group_bits / cpi - > twopass . frames_to_key ) , new_height , new_width ) ;
2010-05-18 19:58:33 +04:00
fclose ( f ) ;
}
// The trigger for spatial resampling depends on the various parameters such as whether we are streaming (CBR) or VBR.
if ( cpi - > oxcf . end_usage = = USAGE_STREAM_FROM_SERVER )
{
// Trigger resample if we are projected to fall below down sample level or
// resampled last time and are projected to remain below the up sample level
if ( ( projected_buffer_level < ( cpi - > oxcf . resample_down_water_mark * cpi - > oxcf . optimal_buffer_level / 100 ) ) | |
( last_kf_resampled & & ( projected_buffer_level < ( cpi - > oxcf . resample_up_water_mark * cpi - > oxcf . optimal_buffer_level / 100 ) ) ) )
//( ((cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))) &&
// ((projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))) ))
2011-12-22 02:21:29 +04:00
resample_trigger = 1 ;
2010-05-18 19:58:33 +04:00
else
2011-12-22 02:21:29 +04:00
resample_trigger = 0 ;
2010-05-18 19:58:33 +04:00
}
else
{
Avoid heap allocation of firstpass stats
The total_stats, this_frame_stats, and total_left_stats structures
were previously create by a heap allocation, despite being of fixed
size. These structures were allocated and deallocated during
{de,}allocate_compressor_data, which is reinvoked whenever the frame
size changes. Unfortunately, this clobbers the total_stats and
total_left_stats data.
Historically, these were variable size at one time, due to the first
pass motion map, which necessitated their being created by a unique
heap allocation. However, this bug with the total_stats being
clobbered has probably been present since that initial implementation.
These structures are instead moved to be stored within the struct
twopass_rc directly, rather than being heap allocated separately.
Change-Id: I7f9e519e25c58b92969071f0e99fa80307e0682b
2011-12-16 23:26:53 +04:00
int64_t clip_bits = ( int64_t ) ( cpi - > twopass . total_stats . count * cpi - > oxcf . target_bandwidth / DOUBLE_DIVIDE_CHECK ( ( double ) cpi - > frame_rate ) ) ;
2011-07-26 05:44:59 +04:00
int64_t over_spend = cpi - > oxcf . starting_buffer_level - cpi - > buffer_level ;
2010-05-18 19:58:33 +04:00
if ( ( last_kf_resampled & & ( kf_q > cpi - > worst_quality ) ) | | // If triggered last time the threshold for triggering again is reduced
( ( kf_q > cpi - > worst_quality ) & & // Projected Q higher than allowed and ...
( over_spend > clip_bits / 20 ) ) ) // ... Overspend > 5% of total bits
2011-12-22 02:21:29 +04:00
resample_trigger = 1 ;
2010-05-18 19:58:33 +04:00
else
2011-12-22 02:21:29 +04:00
resample_trigger = 0 ;
2010-05-18 19:58:33 +04:00
}
if ( resample_trigger )
{
while ( ( kf_q > = cpi - > worst_quality ) & & ( scale_val < 6 ) )
{
scale_val + + ;
cpi - > common . vert_scale = vscale_lookup [ scale_val ] ;
cpi - > common . horiz_scale = hscale_lookup [ scale_val ] ;
Scale2Ratio ( cpi - > common . horiz_scale , & hr , & hs ) ;
Scale2Ratio ( cpi - > common . vert_scale , & vr , & vs ) ;
new_width = ( ( hs - 1 ) + ( cpi - > oxcf . Width * hr ) ) / hs ;
new_height = ( ( vs - 1 ) + ( cpi - > oxcf . Height * vr ) ) / vs ;
// Reducing the area to 1/4 does not reduce the complexity (err_per_frame) to 1/4...
// effective_sizeratio attempts to provide a crude correction for this
effective_size_ratio = ( double ) ( new_width * new_height ) / ( double ) ( cpi - > oxcf . Width * cpi - > oxcf . Height ) ;
effective_size_ratio = ( 1.0 + ( 3.0 * effective_size_ratio ) ) / 4.0 ;
// Now try again and see what Q we get with the smaller image size
2011-03-10 19:13:44 +03:00
kf_q = estimate_kf_group_q ( cpi , err_per_frame * effective_size_ratio , bits_per_frame , group_iiratio ) ;
2010-05-18 19:58:33 +04:00
if ( 0 )
{
FILE * f = fopen ( " Subsamle.stt " , " a " ) ;
2011-05-20 01:16:39 +04:00
fprintf ( f , " ******** %8d %8d %8d %12.0f %8d %8d %8d \n " , kf_q , cpi - > common . horiz_scale , cpi - > common . vert_scale , kf_group_err / cpi - > twopass . frames_to_key , ( int ) ( cpi - > twopass . kf_group_bits / cpi - > twopass . frames_to_key ) , new_height , new_width ) ;
2010-05-18 19:58:33 +04:00
fclose ( f ) ;
}
}
}
if ( ( cpi - > common . Width ! = new_width ) | | ( cpi - > common . Height ! = new_height ) )
{
cpi - > common . Width = new_width ;
cpi - > common . Height = new_height ;
vp8_alloc_compressor_data ( cpi ) ;
}
}
}