1. x264_encoder_encode( x264_t *h, x264_nal_t **pp_nal, int *pi_nal,
x264_picture_t *pic_in, x264_picture_t *pic_out ) //encoder.c中
(1)x264_frame_t *frame_psnr = h->fdec; // just to keep the current decoded frame for psnr calculation
(2) x264_frame_t *fenc = x264_frame_get( h->frames.unused );//返回h->frames.unused[0]的值,即得到了一幀图像给编码器fenc, x264_frame_get函数在encoder.c中,原型为:
static x264_frame_t *x264_frame_get( x264_frame_t *list[X264_BFRAME_MAX+1] )
{
x264_frame_t *frame = list[0];
int i;
for( i = 0; list[i]; i++ )
list[i] = list[i+1];
return frame;
}
(3) x264_frame_copy_picture( h, fenc, pic_in ); // pic_in复制到 fenc ,把要编码的帧存放到 fenc
该函数在frame.c中,原型为:
void x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
{
dst->i_type = src->i_type;
dst->i_qpplus1 = src->i_qpplus1;
dst->i_pts = src->i_pts;
switch( src->img.i_csp & X264_CSP_MASK )
{
case X264_CSP_I420:
h->csp.i420( dst, &src->img, h->param.i_width, h->param.i_height );
break;
....
default:
x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" );
break;
}
}
(4) if( h->param.i_width % 16 || h->param.i_height % 16 ) x264_frame_expand_border_mod16( h, fenc );
fenc->i_frame = h->frames.i_input++;
//若图像宽或高不是16的整数倍,调用 x264_frame_expand_border_mod16( h, fenc );
x264_frame_put( h->frames.next, fenc );//将fenc拷贝给h->frames.next数组中第一个不为0的位置,该函数在encoder.c中,原型为:
static void x264_frame_put( x264_frame_t *list[X264_BFRAME_MAX], x264_frame_t *frame )
{
int i = 0;
while( list[i] ) i++;
list[i] = frame;
}
(5)x264_slicetype_decide( h ); //判断slice的类型,在slicetype_decision.c中,如下:
void x264_slicetype_decide( x264_t *h )
{
...
if( h->param.rc.b_stat_read )
{
/* Use the frame types from the first pass */
for( i = 0; h->frames.next[i] != NULL; i++ )
h->frames.next[i]->i_type =
x264_ratecontrol_slice_type( h, h->frames.next[i]->i_frame );
}
else if( h->param.i_bframe && h->param.b_bframe_adaptive )
x264_slicetype_analyse( h );//x264_slicetype_analyse函数在slicetype_decision.c中。
//这里要注意默认的x264里面是没有B帧的,如果需要用到B帧可以在最初的参数设置的时候,
//用语句“--frames 数字”来定义,x264_slicetype_analyse 也只有在定义了“--frames 数字”时候,
//才会执行。
...
}
(6) /* move some B-frames and 1 non-B to encode queue */
while( IS_X264_TYPE_B( h->frames.next[bframes]->i_type ) )
bframes++;
x264_frame_put( h->frames.current, x264_frame_get( &h->frames.next[bframes] ) );
//将当前要编码的帧h->frames.current送给编码器,然后开始编码
(7) h->fenc = x264_frame_get( h->frames.current );//将当前要编码的帧给编码器
(8) if( h->fenc->i_type == X264_TYPE_IDR )
{
h->frames.i_last_idr = h->fenc->i_frame;
}
TIMER_START( i_mtime_encode_frame );
// 如果是解码即时刷新片,则h->frames.i_last_idr = h->fenc->i_frame;然后计时开
(9)if( h->fenc->i_type == X264_TYPE_IDR )
{
/* reset ref pictures */
x264_reference_reset( h );
i_nal_type = NAL_SLICE_IDR;
i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
i_slice_type = SLICE_TYPE_I;
}
else if( h->fenc->i_type == X264_TYPE_I )
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
i_slice_type = SLICE_TYPE_I;
}
else if( h->fenc->i_type == X264_TYPE_P )
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
i_slice_type = SLICE_TYPE_P;
}
else if( h->fenc->i_type == X264_TYPE_BREF )
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* maybe add MMCO to forget it? -> low */
i_slice_type = SLICE_TYPE_B;
}
else /* B frame */
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_DISPOSABLE;
i_slice_type = SLICE_TYPE_B;
}
//根据帧的类型初始化数据。总共有五种片的类型IDR,I,P,BREF,B 。如果是解码即时刷新片(idr),则要对参考帧重新设置