/* 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;
//#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;
#define TIMER_STOP( d ) \
d += x264_mdate() - d##start;\
}
+#else
+#define TIMER_START( d )
+#define TIMER_STOP( d )
+#endif
/****************************************************************************
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;
/* 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;
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;
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 ----------------------------- */
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 );
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 */
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;
****************************************************************************/
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++ )
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,
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 */
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;
/* 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;
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;
(*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;
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 =
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;
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],
{
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,
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];
// 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;
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)
{
/* 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)
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;
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;
}