📄 encoder.c
字号:
x264_frame_t *tmp;
/* Reset */
h->i_frame_num = 0;
/* Reinit field of fenc */
h->fenc->i_type = X264_TYPE_IDR;
h->fenc->i_poc = 0;
/* Put enqueued frames back in the pool */
while( (tmp = x264_frame_get( h->frames.current ) ) != NULL )
x264_frame_put( h->frames.next, tmp );
x264_frame_sort_pts( h->frames.next );
}
else
{
h->fenc->i_type = X264_TYPE_I;
}
goto do_encode;
}
}
/* End bitstream, set output */
*pi_nal = h->out.i_nal;
*pp_nal = h->out.nal;
/* Set output picture properties */
if( i_slice_type == SLICE_TYPE_I )
pic_out->i_type = i_nal_type == NAL_SLICE_IDR ? X264_TYPE_IDR : X264_TYPE_I;
else if( i_slice_type == SLICE_TYPE_P )
pic_out->i_type = X264_TYPE_P;
else
pic_out->i_type = X264_TYPE_B;
pic_out->i_pts = h->fenc->i_pts;
pic_out->img.i_plane = h->fdec->i_plane;
for(i = 0; i < 4; i++){
pic_out->img.i_stride[i] = h->fdec->i_stride[i];
pic_out->img.plane[i] = h->fdec->plane[i];
}
/* ---------------------- Update encoder state ------------------------- */
/* update rc */
x264_cpu_restore( h->param.cpu );
x264_ratecontrol_end( h, i_frame_size * 8 );
/* handle references */
if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )
x264_reference_update( h );
#ifdef DEBUG_DUMP_FRAME
else
x264_fdec_deblock( h );
#endif
x264_frame_put( h->frames.unused, h->fenc );
/* increase frame count */
h->i_frame++;
/* restore CPU state (before using float again) */
x264_cpu_restore( h->param.cpu );
x264_noise_reduction_update( h );
TIMER_STOP( i_mtime_encode_frame );
/* ---------------------- Compute/Print statistics --------------------- */
/* Slice stat */
h->stat.i_slice_count[i_slice_type]++;
h->stat.i_slice_size[i_slice_type] += i_frame_size + NALU_OVERHEAD;
h->stat.i_slice_qp[i_slice_type] += i_global_qp;
for( i = 0; i < 19; i++ )
h->stat.i_mb_count[h->sh.i_type][i] += h->stat.frame.i_mb_count[i];
for( i = 0; i < 2; i++ )
h->stat.i_mb_count_8x8dct[i] += h->stat.frame.i_mb_count_8x8dct[i];
if( h->sh.i_type != SLICE_TYPE_I )
{
for( i = 0; i < 7; i++ )
h->stat.i_mb_count_size[h->sh.i_type][i] += h->stat.frame.i_mb_count_size[i];
for( i = 0; i < 16; i++ )
h->stat.i_mb_count_ref[h->sh.i_type][i] += h->stat.frame.i_mb_count_ref[i];
}
if( i_slice_type == SLICE_TYPE_B )
{
h->stat.i_direct_frames[ h->sh.b_direct_spatial_mv_pred ] ++;
if( h->mb.b_direct_auto_write )
{
//FIXME somewhat arbitrary time constants
if( h->stat.i_direct_score[0] + h->stat.i_direct_score[1] > h->mb.i_mb_count )
{
for( i = 0; i < 2; i++ )
h->stat.i_direct_score[i] = h->stat.i_direct_score[i] * 9/10;
}
for( i = 0; i < 2; i++ )
h->stat.i_direct_score[i] += h->stat.frame.i_direct_score[i];
}
}
if( h->param.analyse.b_psnr )
{
int64_t i_sqe_y, i_sqe_u, i_sqe_v;
/* PSNR */
i_sqe_y = x264_pixel_ssd_wxh( &h->pixf, frame_psnr->plane[0], frame_psnr->i_stride[0], h->fenc->plane[0], h->fenc->i_stride[0], h->param.i_width, h->param.i_height );
i_sqe_u = x264_pixel_ssd_wxh( &h->pixf, frame_psnr->plane[1], frame_psnr->i_stride[1], h->fenc->plane[1], h->fenc->i_stride[1], h->param.i_width/2, h->param.i_height/2);
i_sqe_v = x264_pixel_ssd_wxh( &h->pixf, frame_psnr->plane[2], frame_psnr->i_stride[2], h->fenc->plane[2], h->fenc->i_stride[2], h->param.i_width/2, h->param.i_height/2);
x264_cpu_restore( h->param.cpu );
h->stat.i_sqe_global[i_slice_type] += i_sqe_y + i_sqe_u + i_sqe_v;
h->stat.f_psnr_average[i_slice_type] += x264_psnr( i_sqe_y + i_sqe_u + i_sqe_v, 3 * h->param.i_width * h->param.i_height / 2 );
h->stat.f_psnr_mean_y[i_slice_type] += x264_psnr( i_sqe_y, h->param.i_width * h->param.i_height );
h->stat.f_psnr_mean_u[i_slice_type] += x264_psnr( i_sqe_u, h->param.i_width * h->param.i_height / 4 );
h->stat.f_psnr_mean_v[i_slice_type] += x264_psnr( i_sqe_v, h->param.i_width * h->param.i_height / 4 );
snprintf( psz_message, 80, " PSNR Y:%2.2f U:%2.2f V:%2.2f",
x264_psnr( i_sqe_y, h->param.i_width * h->param.i_height ),
x264_psnr( i_sqe_u, h->param.i_width * h->param.i_height / 4),
x264_psnr( i_sqe_v, h->param.i_width * h->param.i_height / 4) );
psz_message[79] = '\0';
}
else
{
psz_message[0] = '\0';
}
x264_log( h, X264_LOG_DEBUG,
"frame=%4d QP=%i NAL=%d Slice:%c Poc:%-3d I:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
h->i_frame - 1,
i_global_qp,
i_nal_ref_idc,
i_slice_type == SLICE_TYPE_I ? 'I' : (i_slice_type == SLICE_TYPE_P ? 'P' : 'B' ),
frame_psnr->i_poc,
h->stat.frame.i_mb_count_i,
h->stat.frame.i_mb_count_p,
h->stat.frame.i_mb_count_skip,
i_frame_size,
psz_message );
#ifdef DEBUG_MB_TYPE
{
static const char mb_chars[] = { 'i', 'i', 'I', 'C', 'P', '8', 'S',
'D', '<', 'X', 'B', 'X', '>', 'B', 'B', 'B', 'B', '8', 'S' };
int mb_xy;
for( mb_xy = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )
{
if( h->mb.type[mb_xy] < 19 && h->mb.type[mb_xy] >= 0 )
fprintf( stderr, "%c ", mb_chars[ h->mb.type[mb_xy] ] );
else
fprintf( stderr, "? " );
if( (mb_xy+1) % h->sps->i_mb_width == 0 )
fprintf( stderr, "\n" );
}
}
#endif
#ifdef DEBUG_DUMP_FRAME
/* Dump reconstructed frame */
x264_frame_dump( h, frame_psnr, "fdec.yuv" );
#endif
return 0;
}
/****************************************************************************
* x264_encoder_close:
****************************************************************************/
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++ )
{
static const int slice_order[] = { SLICE_TYPE_I, SLICE_TYPE_SI, SLICE_TYPE_P, SLICE_TYPE_SP, SLICE_TYPE_B };
static const char *slice_name[] = { "P", "B", "I", "SP", "SI" };
int i_slice = slice_order[i];
if( h->stat.i_slice_count[i_slice] > 0 )
{
const int i_count = h->stat.i_slice_count[i_slice];
if( h->param.analyse.b_psnr )
{
x264_log( h, X264_LOG_INFO,
"slice %s:%-5d Avg QP:%5.2f size:%6.0f PSNR Mean Y:%5.2f U:%5.2f V:%5.2f Avg:%5.2f Global:%5.2f\n",
slice_name[i_slice],
i_count,
(double)h->stat.i_slice_qp[i_slice] / i_count,
(double)h->stat.i_slice_size[i_slice] / i_count,
h->stat.f_psnr_mean_y[i_slice] / i_count, h->stat.f_psnr_mean_u[i_slice] / i_count, h->stat.f_psnr_mean_v[i_slice] / i_count,
h->stat.f_psnr_average[i_slice] / i_count,
x264_psnr( h->stat.i_sqe_global[i_slice], i_count * i_yuv_size ) );
}
else
{
x264_log( h, X264_LOG_INFO,
"slice %s:%-5d Avg QP:%5.2f size:%6.0f\n",
slice_name[i_slice],
i_count,
(double)h->stat.i_slice_qp[i_slice] / i_count,
(double)h->stat.i_slice_size[i_slice] / i_count );
}
}
}
/* MB types used */
if( h->stat.i_slice_count[SLICE_TYPE_I] > 0 )
{
const int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_I];
const double i_count = h->stat.i_slice_count[SLICE_TYPE_I] * h->mb.i_mb_count / 100.0;
x264_log( h, X264_LOG_INFO,
"mb I I16..4: %4.1f%% %4.1f%% %4.1f%%\n",
i_mb_count[I_16x16]/ i_count,
i_mb_count[I_8x8] / i_count,
i_mb_count[I_4x4] / i_count );
}
if( h->stat.i_slice_count[SLICE_TYPE_P] > 0 )
{
const int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_P];
const int64_t *i_mb_size = h->stat.i_mb_count_size[SLICE_TYPE_P];
const double i_count = h->stat.i_slice_count[SLICE_TYPE_P] * h->mb.i_mb_count / 100.0;
x264_log( h, X264_LOG_INFO,
"mb P I16..4: %4.1f%% %4.1f%% %4.1f%% P16..4: %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% skip:%4.1f%%\n",
i_mb_count[I_16x16]/ i_count,
i_mb_count[I_8x8] / i_count,
i_mb_count[I_4x4] / i_count,
i_mb_size[PIXEL_16x16] / (i_count*4),
(i_mb_size[PIXEL_16x8] + i_mb_size[PIXEL_8x16]) / (i_count*4),
i_mb_size[PIXEL_8x8] / (i_count*4),
(i_mb_size[PIXEL_8x4] + i_mb_size[PIXEL_4x8]) / (i_count*4),
i_mb_size[PIXEL_4x4] / (i_count*4),
i_mb_count[P_SKIP] / i_count );
}
if( h->stat.i_slice_count[SLICE_TYPE_B] > 0 )
{
const int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_B];
const int64_t *i_mb_size = h->stat.i_mb_count_size[SLICE_TYPE_B];
const double i_count = h->stat.i_slice_count[SLICE_TYPE_B] * h->mb.i_mb_count / 100.0;
x264_log( h, X264_LOG_INFO,
"mb B I16..4: %4.1f%% %4.1f%% %4.1f%% B16..8: %4.1f%% %4.1f%% %4.1f%% direct:%4.1f%% skip:%4.1f%%\n",
i_mb_count[I_16x16] / i_count,
i_mb_count[I_8x8] / i_count,
i_mb_count[I_4x4] / i_count,
i_mb_size[PIXEL_16x16] / (i_count*4),
(i_mb_size[PIXEL_16x8] + i_mb_size[PIXEL_8x16]) / (i_count*4),
i_mb_size[PIXEL_8x8] / (i_count*4),
i_mb_count[B_DIRECT] / i_count,
i_mb_count[B_SKIP] / i_count );
}
x264_ratecontrol_summary( h );
if( h->stat.i_slice_count[SLICE_TYPE_I] + h->stat.i_slice_count[SLICE_TYPE_P] + h->stat.i_slice_count[SLICE_TYPE_B] > 0 )
{
const int i_count = h->stat.i_slice_count[SLICE_TYPE_I] +
h->stat.i_slice_count[SLICE_TYPE_P] +
h->stat.i_slice_count[SLICE_TYPE_B];
float fps = (float) h->param.i_fps_num / h->param.i_fps_den;
#define SUM3(p) (p[SLICE_TYPE_I] + p[SLICE_TYPE_P] + p[SLICE_TYPE_B])
#define SUM3b(p,o) (p[SLICE_TYPE_I][o] + p[SLICE_TYPE_P][o] + p[SLICE_TYPE_B][o])
float f_bitrate = fps * SUM3(h->stat.i_slice_size) / i_count / 125;
if( h->param.analyse.b_transform_8x8 )
{
int64_t i_i8x8 = SUM3b( h->stat.i_mb_count, I_8x8 );
int64_t i_intra = i_i8x8 + SUM3b( h->stat.i_mb_count, I_4x4 )
+ SUM3b( h->stat.i_mb_count, I_16x16 );
x264_log( h, X264_LOG_INFO, "8x8 transform intra:%.1f%% inter:%.1f%%\n",
100. * i_i8x8 / i_intra,
100. * h->stat.i_mb_count_8x8dct[1] / h->stat.i_mb_count_8x8dct[0] );
}
if( h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO
&& h->stat.i_slice_count[SLICE_TYPE_B] )
{
x264_log( h, X264_LOG_INFO, "direct mvs spatial:%.1f%% temporal:%.1f%%\n",
h->stat.i_direct_frames[1] * 100. / h->stat.i_slice_count[SLICE_TYPE_B],
h->stat.i_direct_frames[0] * 100. / h->stat.i_slice_count[SLICE_TYPE_B] );
}
if( h->param.i_frame_reference > 1 )
{
int i_slice;
for( i_slice = 0; i_slice < 2; i_slice++ )
{
char buf[200];
char *p = buf;
int64_t i_den = 0;
int i_max = 0;
for( i = 0; i < h->param.i_frame_reference; i++ )
if( h->stat.i_mb_count_ref[i_slice][i] )
{
i_den += h->stat.i_mb_count_ref[i_slice][i];
i_max = i;
}
if( i_max == 0 )
continue;
for( i = 0; i <= i_max; i++ )
p += sprintf( p, " %4.1f%%", 100. * h->stat.i_mb_count_ref[i_slice][i] / i_den );
x264_log( h, X264_LOG_INFO, "ref %c %s\n", i_slice==SLICE_TYPE_P ? 'P' : 'B', buf );
}
}
if( h->param.analyse.b_psnr )
x264_log( h, X264_LOG_INFO,
"PSNR Mean Y:%6.3f U:%6.3f V:%6.3f Avg:%6.3f Global:%6.3f kb/s:%.2f\n",
SUM3( h->stat.f_psnr_mean_y ) / i_count,
SUM3( h->stat.f_psnr_mean_u ) / i_count,
SUM3( h->stat.f_psnr_mean_v ) / i_count,
SUM3( h->stat.f_psnr_average ) / i_count,
x264_psnr( SUM3( h->stat.i_sqe_global ), i_count * i_yuv_size ),
f_bitrate );
else
x264_log( h, X264_LOG_INFO, "kb/s:%.1f\n", f_bitrate );
}
/* frames */
for( i = 0; i < X264_BFRAME_MAX + 3; i++ )
{
if( h->frames.current[i] ) x264_frame_delete( h->frames.current[i] );
if( h->frames.next[i] ) x264_frame_delete( h->frames.next[i] );
if( h->frames.unused[i] ) x264_frame_delete( h->frames.unused[i] );
}
/* ref frames */
for( i = 0; i < h->frames.i_max_dpb; i++ )
{
x264_frame_delete( h->frames.reference[i] );
}
/* rc */
x264_ratecontrol_delete( h );
/* param */
if( h->param.rc.psz_stat_out )
free( h->param.rc.psz_stat_out );
if( h->param.rc.psz_stat_in )
free( h->param.rc.psz_stat_in );
if( h->param.rc.psz_rc_eq )
free( h->param.rc.psz_rc_eq );
x264_macroblock_cache_end( h );
x264_free( h->out.p_bitstream );
for( i = 1; i < h->param.i_threads; i++ )
x264_free( h->thread[i] );
x264_free( h );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -