📄 encoder.c
字号:
/* build ref list 0/1 */
h->i_ref0 = 0;
h->i_ref1 = 0;
for( i = 1; i < h->param.i_frame_reference+2; i++ )
{
if( h->freference[i]->i_poc >= 0 )
{
if( h->freference[i]->i_poc < h->fdec->i_poc )
{
h->fref0[h->i_ref0++] = h->freference[i];
}
else if( h->freference[i]->i_poc > h->fdec->i_poc )
{
h->fref1[h->i_ref1++] = h->freference[i];
}
}
}
/* Order ref0 from higher to lower poc */
do
{
b_ok = 1;
for( i = 0; i < h->i_ref0 - 1; i++ )
{
if( h->fref0[i]->i_poc < h->fref0[i+1]->i_poc )
{
x264_frame_t *tmp = h->fref0[i+1];
h->fref0[i+1] = h->fref0[i];
h->fref0[i] = tmp;
b_ok = 0;
break;
}
}
} while( !b_ok );
/* Order ref1 from lower to higher poc (bubble sort) for B-frame */
do
{
b_ok = 1;
for( i = 0; i < h->i_ref1 - 1; i++ )
{
if( h->fref1[i]->i_poc > h->fref1[i+1]->i_poc )
{
x264_frame_t *tmp = h->fref1[i+1];
h->fref1[i+1] = h->fref1[i];
h->fref1[i] = tmp;
b_ok = 0;
break;
}
}
} while( !b_ok );
if( h->i_ref0 > h->param.i_frame_reference )
{
h->i_ref0 = h->param.i_frame_reference;
}
if( h->i_ref1 > 1 )
{
h->i_ref1 = 1;
}
/* Init the rate control */
x264_ratecontrol_start( h->rc, i_slice_type );
/* ------------------------ Create slice header ----------------------- */
if( i_nal_type == NAL_SLICE_IDR )
{
x264_slice_header_init( &h->sh, &h->param, h->sps, h->pps, i_slice_type, h->i_idr_pic_id, h->i_frame_num - 1 );
/* increment id */
h->i_idr_pic_id = ( h->i_idr_pic_id + 1 ) % 65535;
}
else
{
x264_slice_header_init( &h->sh, &h->param, h->sps, h->pps, i_slice_type, -1, h->i_frame_num - 1 );
/* always set the real higher num of ref frame used */
h->sh.b_num_ref_idx_override = 1;
h->sh.i_num_ref_idx_l0_active = h->i_ref0 <= 0 ? 1 : h->i_ref0;
h->sh.i_num_ref_idx_l1_active = h->i_ref1 <= 0 ? 1 : h->i_ref1;
}
if( h->sps->i_poc_type == 0 )
{
h->sh.i_poc_lsb = h->fdec->i_poc & ( (1 << h->sps->i_log2_max_poc_lsb) - 1 );
h->sh.i_delta_poc_bottom = 0; /* XXX won't work for field */
}
else if( h->sps->i_poc_type == 1 )
{
/* FIXME TODO FIXME */
}
else
{
/* Nothing to do ? */
}
/* global qp */
h->sh.i_qp_delta = x264_ratecontrol_qp( h->rc ) - h->pps->i_pic_init_qp;
/* get adapative cabac model if needed */
if( h->param.b_cabac )
{
if( h->param.i_cabac_init_idc == -1 )
{
h->sh.i_cabac_init_idc = x264_cabac_model_get( &h->cabac, i_slice_type );
}
}
/* ---------------------- Write the bitstream -------------------------- */
/* init bitstream context */
h->i_nal = 0;
bs_init( &h->bs, h->p_bitstream, h->i_bitstream );
/* Put SPS and PPS */
if( h->i_frame == 0 )
{
/* generate sequence parameters */
x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
x264_sps_write( &h->bs, h->sps );
x264_nal_end( h );
/* generate picture parameters */
x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
x264_pps_write( &h->bs, h->pps );
x264_nal_end( h );
}
/* Reset stats */
for( i = 0; i < 18; i++ ) h->stat.i_mb_count[i] = 0;
/* Slice */
x264_nal_start( h, i_nal_type, i_nal_ref_idc );
/* Slice header */
x264_slice_header_write( &h->bs, &h->sh, i_nal_ref_idc );
if( h->param.b_cabac )
{
/* alignement needed */
bs_align_1( &h->bs );
/* init cabac */
x264_cabac_context_init( &h->cabac, h->sh.i_type, h->sh.pps->i_pic_init_qp + h->sh.i_qp_delta, h->sh.i_cabac_init_idc );
x264_cabac_encode_init ( &h->cabac, &h->bs );
}
for( mb_xy = 0, i_skip = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )
{
x264_mb_context_t context;
x264_macroblock_t *mb;
mb = &h->mb[mb_xy];
/* load neighbour */
x264_macroblock_context_load( h, mb, &context );
/* analyse parameters
* Slice I: choose I_4x4 or I_16x16 mode
* Slice P: choose between using P mode or intra (4x4 or 16x16)
* */
TIMER_START( i_mtime_analyse );
x264_macroblock_analyse( h, &h->mb[mb_xy] );
TIMER_STOP( i_mtime_analyse );
/* encode this macrobock -> be carefull it can change the mb type to P_SKIP if needed */
TIMER_START( i_mtime_encode );
x264_macroblock_encode( h, mb );
TIMER_STOP( i_mtime_encode );
TIMER_START( i_mtime_write );
if( IS_SKIP( mb->i_type ) )
{
if( h->param.b_cabac )
{
if( mb_xy > 0 )
{
/* not end_of_slice_flag */
x264_cabac_encode_terminal( &h->cabac, 0 );
}
x264_cabac_mb_skip( h, mb, 1 );
}
else
{
i_skip++;
}
}
else
{
if( h->param.b_cabac )
{
if( mb_xy > 0 )
{
/* not end_of_slice_flag */
x264_cabac_encode_terminal( &h->cabac, 0 );
}
if( i_slice_type != SLICE_TYPE_I )
{
x264_cabac_mb_skip( h, mb, 0 );
}
x264_macroblock_write_cabac( h, &h->bs, mb );
}
else
{
if( i_slice_type != SLICE_TYPE_I )
{
bs_write_ue( &h->bs, i_skip ); /* skip run */
i_skip = 0;
}
x264_macroblock_write_cavlc( h, &h->bs, mb );
}
}
TIMER_STOP( i_mtime_write );
h->stat.i_mb_count[mb->i_type]++;
}
if( h->param.b_cabac )
{
/* end of slice */
x264_cabac_encode_terminal( &h->cabac, 1 );
}
else if( i_skip > 0 )
{
bs_write_ue( &h->bs, i_skip ); /* last skip run */
}
if( h->param.b_cabac )
{
int i_cabac_word;
x264_cabac_encode_flush( &h->cabac );
/* TODO cabac stuffing things (p209) */
i_cabac_word = (((3 * h->cabac.i_sym_cnt - 3 * 96 * h->sps->i_mb_width * h->sps->i_mb_height)/32) - bs_pos( &h->bs)/8)/3;
while( i_cabac_word > 0 )
{
bs_write( &h->bs, 16, 0x0000 );
i_cabac_word--;
}
}
else
{
/* rbsp_slice_trailing_bits */
bs_rbsp_trailing( &h->bs );
}
x264_nal_end( h );
/* now set output*/
*pi_nal = h->i_nal;
*pp_nal = &h->nal[0];
/* update cabac */
if( h->param.b_cabac )
{
x264_cabac_model_update( &h->cabac, i_slice_type, h->sh.pps->i_pic_init_qp + h->sh.i_qp_delta );
}
/* update rc */
x264_ratecontrol_end( h->rc, h->nal[h->i_nal-1].i_payload * 8 );
/* ----------------------- handle frame reference ---------------------- */
if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )
{
/* apply deblocking filter to the current decoded picture */
if( h->param.b_deblocking_filter )
{
TIMER_START( i_mtime_filter );
x264_frame_deblocking_filter( h, i_slice_type );
TIMER_STOP( i_mtime_filter );
}
/* expand border */
x264_frame_expand_border( h->fdec );
/* move frame in the buffer */
h->fdec = h->freference[h->param.i_frame_reference+1];
for( i = h->param.i_frame_reference+1; i > 0; i-- )
{
h->freference[i] = h->freference[i-1];
}
h->freference[0] = h->fdec;
}
/* increase frame count */
h->i_frame++;
/* PSNR */
psnr_y = x264_psnr( frame_psnr->plane[0], frame_psnr->i_stride[0], h->picture->plane[0], h->picture->i_stride[0], h->param.i_width, h->param.i_height );
psnr_u = x264_psnr( frame_psnr->plane[1], frame_psnr->i_stride[1], h->picture->plane[1], h->picture->i_stride[1], h->param.i_width/2, h->param.i_height/2);
psnr_v = x264_psnr( frame_psnr->plane[2], frame_psnr->i_stride[2], h->picture->plane[2], h->picture->i_stride[2], h->param.i_width/2, h->param.i_height/2);
/* print stat */
fprintf( stderr, "frame=%4d NAL=%d Slice:%c Poc:%-3d I4x4:%-5d I16x16:%-5d P:%-5d SKIP:%-3d size=%d bytes PSNR Y:%2.2f U:%2.2f V:%2.2f\n",
h->i_frame - 1,
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.i_mb_count[I_4x4],
h->stat.i_mb_count[I_16x16],
h->stat.i_mb_count[P_L0] + h->stat.i_mb_count[P_8x8],
h->stat.i_mb_count[P_SKIP],
h->nal[h->i_nal-1].i_payload,
psnr_y, psnr_u, psnr_v );
#if 0
/* Dump reconstructed frame */
x264_frame_dump( h, frame_psnr, "fdec.yuv" );
#endif
#if 0
if( h->i_ref0 > 0 )
{
x264_frame_dump( h, h->fref0[0], "ref0.yuv" );
}
if( h->i_ref1 > 0 )
{
x264_frame_dump( h, h->fref1[0], "ref1.yuv" );
}
#endif
return 0;
}
/****************************************************************************
* x264_encoder_close:
****************************************************************************/
void x264_encoder_close ( x264_t *h )
{
int64_t i_mtime_total = i_mtime_analyse + i_mtime_encode + i_mtime_write + i_mtime_filter + 1;
int i;
fprintf( stderr, "x264: analyse=%d(%lldms) encode=%d(%lldms) write=%d(%lldms) filter=%d(%lldms)",
(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 );
/* ref frames */
for( i = 0; i < h->param.i_frame_reference+2; i++ )
{
x264_frame_delete( h->freference[i] );
}
/* empty all allocated picture for bframes */
for( i = 0; i < h->param.i_bframe; i++ )
{
if( h->frame_unused[i] )
{
x264_frame_delete( h->frame_unused[i] );
}
if( h->bframe_current[i] )
{
x264_frame_delete( h->bframe_current[i] );
}
if( h->frame_next[i] )
{
x264_frame_delete( h->frame_next[i] );
}
}
/* rc */
x264_ratecontrol_delete( h->rc );
x264_free( h->mb );
x264_free( h->p_bitstream );
x264_free( h );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -