Commit 0a709047 authored by Loren Merritt's avatar Loren Merritt

My last change of IDR decision broke in 2pass mode. fixed by remembering which frames are IDR.

Disable benchmarking, as it was very slow for some people, and we already know that all the time is spent in macroblock analysis.


git-svn-id: svn://svn.videolan.org/x264/trunk@94 df754926-b1dd-0310-bc7b-ec298dee348c
parent 64832808
......@@ -215,7 +215,7 @@ struct x264_t
/* frames used for reference +1 for decoding */
x264_frame_t *reference[16+1];
int i_last_idr; /* How many frames since last IDR */
int i_last_idr; /* Frame number of the last IDR */
int i_input; /* Number of input frames already accepted */
} frames;
......
......@@ -37,9 +37,10 @@
//#define DEBUG_MB_TYPE
//#define DEBUG_DUMP_FRAME
//#define DEBUG_BENCHMARK
#ifdef DEBUG_BENCHMARK
static int64_t i_mtime_encode_frame = 0;
static int64_t i_mtime_analyse = 0;
static int64_t i_mtime_encode = 0;
static int64_t i_mtime_write = 0;
......@@ -51,6 +52,10 @@ static int64_t i_mtime_filter = 0;
#define TIMER_STOP( d ) \
d += x264_mdate() - d##start;\
}
#else
#define TIMER_START( d )
#define TIMER_STOP( d )
#endif
/****************************************************************************
......@@ -344,7 +349,7 @@ x264_t *x264_encoder_open ( x264_param_t *param )
h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 5 );
if( h->param.analyse.inter & X264_ANALYSE_PSUB8x8 )
h->param.analyse.inter &= X264_ANALYSE_PSUB16x16;
h->param.analyse.inter |= X264_ANALYSE_PSUB16x16;
if( h->param.rc.f_qblur < 0 )
h->param.rc.f_qblur = 0;
......@@ -427,7 +432,7 @@ x264_t *x264_encoder_open ( x264_param_t *param )
/* 2 = 1 backward ref + 1 fdec */
h->frames.reference[i] = x264_frame_new( h );
}
h->frames.i_last_idr = h->param.i_keyint_max;
h->frames.i_last_idr = - h->param.i_keyint_max;
h->frames.i_input = 0;
h->i_ref0 = 0;
......@@ -955,15 +960,15 @@ int x264_encoder_encode( x264_t *h,
frm = h->frames.next[bframes];
/* Limit GOP size */
if( ( h->frames.i_last_idr + bframes + 1 >= h->param.i_keyint_min
&& frm->i_type == X264_TYPE_I )
|| h->frames.i_last_idr + bframes + 1 >= h->param.i_keyint_max )
if( frm->i_frame - h->frames.i_last_idr >= h->param.i_keyint_max )
{
if( frm->i_type == X264_TYPE_AUTO )
frm->i_type = X264_TYPE_IDR;
if( frm->i_type != X264_TYPE_IDR )
x264_log( h, X264_LOG_ERROR, "specified frame type (%d) is not compatible with keyframe interval\n", frm->i_type );
}
if( frm->i_type == X264_TYPE_IDR )
{
if( frm->i_type == X264_TYPE_P
|| frm->i_type == X264_TYPE_B )
x264_log( h, X264_LOG_ERROR, "specified frame type is not compatible with keyframe interval\n" );
frm->i_type = X264_TYPE_IDR;
h->i_poc = 0;
h->i_frame_num = 0;
......@@ -1017,11 +1022,7 @@ do_encode:
if( h->fenc->i_type == X264_TYPE_IDR )
{
h->frames.i_last_idr = 0;
}
else
{
h->frames.i_last_idr++;
h->frames.i_last_idr = h->fenc->i_frame;
}
/* ------------------- Setup frame context ----------------------------- */
......@@ -1126,21 +1127,22 @@ do_encode:
if( h->param.i_keyint_min == h->param.i_keyint_max )
f_thresh_min= f_thresh_max;
float f_bias;
int i_gop_size = h->fenc->i_frame - h->frames.i_last_idr;
/* macroblock_analyse() doesn't further analyse skipped mbs,
* so we have to guess their cost */
if( i_mb_s < i_mb )
i_intra_cost = i_intra_cost * i_mb / (i_mb - i_mb_s);
if( h->frames.i_last_idr < h->param.i_keyint_min / 4 )
if( i_gop_size < h->param.i_keyint_min / 4 )
f_bias = f_thresh_min / 4;
else if( h->frames.i_last_idr <= h->param.i_keyint_min )
f_bias = f_thresh_min * h->frames.i_last_idr / h->param.i_keyint_min;
else if( i_gop_size <= h->param.i_keyint_min )
f_bias = f_thresh_min * i_gop_size / h->param.i_keyint_min;
else
{
f_bias = f_thresh_min
+ ( f_thresh_max - f_thresh_min )
* ( h->frames.i_last_idr - h->param.i_keyint_min )
* ( i_gop_size - h->param.i_keyint_min )
/ ( h->param.i_keyint_max - h->param.i_keyint_min );
}
f_bias = X264_MIN( f_bias, 1.0 );
......@@ -1157,12 +1159,12 @@ do_encode:
h->frames.i_last_i > 4)*/
{
x264_log( h, X264_LOG_DEBUG, "scene cut at %d size=%d I_cost:%lld P_cost:%lld ratio:%.3f bias=%.3f last_IDR:%d (I:%d P:%d Skip:%d)\n",
x264_log( h, X264_LOG_DEBUG, "scene cut at %d size=%d Icost:%lld Pcost:%lld ratio:%.3f bias=%.3f lastIDR:%d (I:%d P:%d Skip:%d)\n",
h->fenc->i_frame,
h->out.nal[h->out.i_nal-1].i_payload,
i_intra_cost, i_inter_cost,
(float)i_inter_cost / i_intra_cost,
f_bias, h->frames.i_last_idr,
f_bias, i_gop_size,
i_mb_i, i_mb_p, i_mb_s );
/* Restore frame num */
......@@ -1185,7 +1187,7 @@ do_encode:
h->fenc->i_type = X264_TYPE_P;
}
/* Do IDR if needed */
else if( h->frames.i_last_idr + 1 >= h->param.i_keyint_min )
else if( i_gop_size >= h->param.i_keyint_min )
{
x264_frame_t *tmp;
......@@ -1351,16 +1353,20 @@ do_encode:
****************************************************************************/
void x264_encoder_close ( x264_t *h )
{
#ifdef DEBUG_BENCHMARK
int64_t i_mtime_total = i_mtime_analyse + i_mtime_encode + i_mtime_write + i_mtime_filter + 1;
#endif
int64_t i_yuv_size = 3 * h->param.i_width * h->param.i_height / 2;
int i;
#ifdef DEBUG_BENCHMARK
x264_log( h, X264_LOG_INFO,
"analyse=%d(%lldms) encode=%d(%lldms) write=%d(%lldms) filter=%d(%lldms)\n",
(int)(100*i_mtime_analyse/i_mtime_total), i_mtime_analyse/1000,
(int)(100*i_mtime_encode/i_mtime_total), i_mtime_encode/1000,
(int)(100*i_mtime_write/i_mtime_total), i_mtime_write/1000,
(int)(100*i_mtime_filter/i_mtime_total), i_mtime_filter/1000 );
#endif
/* Slices used and PSNR */
for( i=0; i<5; i++ )
......@@ -1443,7 +1449,7 @@ void x264_encoder_close ( x264_t *h )
if( h->param.analyse.b_psnr )
x264_log( h, X264_LOG_INFO,
"PSNR Mean Y:%5.2f U:%5.2f V:%5.2f Avg:%5.2f Global:%5.2f kb/s:%.1f fps:%.3f\n",
"PSNR Mean Y:%5.2f U:%5.2f V:%5.2f Avg:%5.2f Global:%5.2f kb/s:%.1f\n",
(h->stat.f_psnr_mean_y[SLICE_TYPE_I] + h->stat.f_psnr_mean_y[SLICE_TYPE_P] + h->stat.f_psnr_mean_y[SLICE_TYPE_B]) / i_count,
(h->stat.f_psnr_mean_u[SLICE_TYPE_I] + h->stat.f_psnr_mean_u[SLICE_TYPE_P] + h->stat.f_psnr_mean_u[SLICE_TYPE_B]) / i_count,
(h->stat.f_psnr_mean_v[SLICE_TYPE_I] + h->stat.f_psnr_mean_v[SLICE_TYPE_P] + h->stat.f_psnr_mean_v[SLICE_TYPE_B]) / i_count,
......@@ -1452,13 +1458,11 @@ void x264_encoder_close ( x264_t *h )
x264_psnr( h->stat.i_sqe_global[SLICE_TYPE_I] + h->stat.i_sqe_global[SLICE_TYPE_P]+ h->stat.i_sqe_global[SLICE_TYPE_B],
i_count * i_yuv_size ),
fps * 8*(h->stat.i_slice_size[SLICE_TYPE_I]+h->stat.i_slice_size[SLICE_TYPE_P]+h->stat.i_slice_size[SLICE_TYPE_B]) / i_count / 1000,
(double)1000000.0 * (double)i_count / (double)i_mtime_encode_frame );
fps * 8*(h->stat.i_slice_size[SLICE_TYPE_I]+h->stat.i_slice_size[SLICE_TYPE_P]+h->stat.i_slice_size[SLICE_TYPE_B]) / i_count / 1000 );
else
x264_log( h, X264_LOG_INFO,
"kb/s:%.1f fps:%.3f\n",
fps * 8*(h->stat.i_slice_size[SLICE_TYPE_I]+h->stat.i_slice_size[SLICE_TYPE_P]+h->stat.i_slice_size[SLICE_TYPE_B]) / i_count / 1000,
(double)1000000.0 * (double)i_count / (double)i_mtime_encode_frame );
"kb/s:%.1f\n",
fps * 8*(h->stat.i_slice_size[SLICE_TYPE_I]+h->stat.i_slice_size[SLICE_TYPE_P]+h->stat.i_slice_size[SLICE_TYPE_B]) / i_count / 1000 );
}
/* frames */
......
......@@ -48,13 +48,13 @@
typedef struct
{
int pict_type;
int idr;
float qscale;
int mv_bits;
int i_tex_bits;
int p_tex_bits;
int misc_bits;
uint64_t expected_bits;
int new_pict_type;
float new_qscale;
int new_qp;
int i_count;
......@@ -268,7 +268,7 @@ int x264_ratecontrol_new( x264_t *h )
/* init all to skipped p frames */
for(i=0; i<rc->num_entries; i++){
ratecontrol_entry_t *rce = &rc->entry[i];
rce->pict_type = rce->new_pict_type = SLICE_TYPE_P;
rce->pict_type = SLICE_TYPE_P;
rce->qscale = rce->new_qscale = qp2qscale(20);
rce->misc_bits = rc->nmb + 10;
rce->new_qp = 0;
......@@ -278,7 +278,8 @@ int x264_ratecontrol_new( x264_t *h )
p = stats_in;
for(i=0; i < rc->num_entries - h->param.i_bframe; i++){
ratecontrol_entry_t *rce;
int picture_number;
int frame_number;
char pict_type;
int e;
char *next;
float qp;
......@@ -288,15 +289,23 @@ int x264_ratecontrol_new( x264_t *h )
(*next)=0; //sscanf is unbelievably slow on looong strings
next++;
}
e = sscanf(p, " in:%d ", &picture_number);
e = sscanf(p, " in:%d ", &frame_number);
assert(picture_number >= 0);
assert(picture_number < rc->num_entries);
rce = &rc->entry[picture_number];
assert(frame_number >= 0);
assert(frame_number < rc->num_entries);
rce = &rc->entry[frame_number];
e += sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d",
&rce->pict_type, &qp, &rce->i_tex_bits, &rce->p_tex_bits,
e += sscanf(p, " in:%*d out:%*d type:%c q:%f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d",
&pict_type, &qp, &rce->i_tex_bits, &rce->p_tex_bits,
&rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count, &rce->s_count);
switch(pict_type){
case 'I': rce->idr = 1;
case 'i': rce->pict_type = SLICE_TYPE_I; break;
case 'P': rce->pict_type = SLICE_TYPE_P; break;
case 'B': rce->pict_type = SLICE_TYPE_B; break;
default: e = -1; break;
}
if(e != 10){
x264_log(h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);
return -1;
......@@ -358,9 +367,9 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
else if( h->param.rc.b_stat_read )
{
int frame = h->fenc->i_frame;
ratecontrol_entry_t *rce = &h->rc->entry[frame];
ratecontrol_entry_t *rce;
assert( frame >= 0 && frame < rc->num_entries );
rce = &h->rc->entry[frame];
rce->new_qscale = rate_estimate_qscale( h, i_slice_type );
rc->qpm = rc->qpa = rc->qp = rce->new_qp =
......@@ -538,10 +547,10 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
x264_log(h, X264_LOG_ERROR, "More input frames than in the 1st pass\n");
return X264_TYPE_P;
}
switch( h->rc->entry[frame_num].new_pict_type )
switch( h->rc->entry[frame_num].pict_type )
{
case SLICE_TYPE_I:
return X264_TYPE_I;
return h->rc->entry[frame_num].idr ? X264_TYPE_IDR : X264_TYPE_I;
case SLICE_TYPE_B:
return X264_TYPE_B;
......@@ -571,10 +580,12 @@ void x264_ratecontrol_end( x264_t *h, int bits )
if( h->param.rc.b_stat_write )
{
char c_type = rc->slice_type==SLICE_TYPE_I ? (h->fenc->i_poc==0 ? 'I' : 'i')
: rc->slice_type==SLICE_TYPE_P ? 'P' : 'B';
fprintf( rc->p_stat_file_out,
"in:%d out:%d type:%d q:%.3f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d;\n",
"in:%d out:%d type:%c q:%.3f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d;\n",
h->fenc->i_frame, h->i_frame-1,
rc->slice_type, rc->qpa,
c_type, rc->qpa,
h->stat.frame.i_itex_bits, h->stat.frame.i_ptex_bits,
h->stat.frame.i_hdr_bits, h->stat.frame.i_misc_bits,
h->stat.frame.i_mb_count[I_4x4] + h->stat.frame.i_mb_count[I_16x16],
......@@ -631,7 +642,7 @@ static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor
{
x264_ratecontrol_t *rcc= h->rc;
double bits;
const int pict_type = rce->new_pict_type;
const int pict_type = rce->pict_type;
double const_values[]={
rce->i_tex_bits * rce->qscale,
......@@ -700,7 +711,7 @@ static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor
static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
{
x264_ratecontrol_t *rcc = h->rc;
const int pict_type = rce->new_pict_type;
const int pict_type = rce->pict_type;
// force I/B quants as a function of P quants
const double last_p_q = rcc->last_qscale_for[SLICE_TYPE_P];
......@@ -755,8 +766,8 @@ static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
// clip a qscale to between lmin and lmax
static double clip_qscale( x264_t *h, ratecontrol_entry_t *rce, double q )
{
double lmin = h->rc->lmin[rce->new_pict_type];
double lmax = h->rc->lmax[rce->new_pict_type];
double lmin = h->rc->lmin[rce->pict_type];
double lmax = h->rc->lmax[rce->pict_type];
if(lmin==lmax){
return lmin;
......@@ -789,7 +800,7 @@ static float rate_estimate_qscale(x264_t *h, int pict_type)
rce = &rcc->entry[picture_number];
assert(pict_type == rce->new_pict_type);
assert(pict_type == rce->pict_type);
if(rce->pict_type == SLICE_TYPE_B)
{
......@@ -824,12 +835,11 @@ static int init_pass2( x264_t *h )
/* find total/average complexity & const_bits */
for(i=0; i<rcc->num_entries; i++){
ratecontrol_entry_t *rce = &rcc->entry[i];
rce->new_pict_type = rce->pict_type;
all_const_bits += rce->mv_bits + rce->misc_bits;
rcc->i_cplx_sum[rce->new_pict_type] += rce->i_tex_bits * rce->qscale;
rcc->p_cplx_sum[rce->new_pict_type] += rce->p_tex_bits * rce->qscale;
rcc->mv_bits_sum[rce->new_pict_type] += rce->mv_bits;
rcc->frame_count[rce->new_pict_type] ++;
rcc->i_cplx_sum[rce->pict_type] += rce->i_tex_bits * rce->qscale;
rcc->p_cplx_sum[rce->pict_type] += rce->p_tex_bits * rce->qscale;
rcc->mv_bits_sum[rce->pict_type] += rce->mv_bits;
rcc->frame_count[rce->pict_type] ++;
}
if( all_available_bits < all_const_bits)
......@@ -899,7 +909,6 @@ static int init_pass2( x264_t *h )
assert(filter_size%2==1);
for(i=0; i<rcc->num_entries; i++){
ratecontrol_entry_t *rce = &rcc->entry[i];
const int pict_type = rce->new_pict_type;
int j;
double q=0.0, sum=0.0;
......@@ -908,7 +917,7 @@ static int init_pass2( x264_t *h )
double d = index-i;
double coeff = qblur==0 ? 1.0 : exp(-d*d/(qblur*qblur));
if(index < 0 || index >= rcc->num_entries) continue;
if(pict_type != rcc->entry[index].new_pict_type) continue;
if(rce->pict_type != rcc->entry[index].pict_type) continue;
q += qscale[index] * coeff;
sum += coeff;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment