x264_slicetype_decide函数(代码所在位置为“x264-snapshot-20171128-2245-stable\encoder\slicetype.c”)的主要作用为:分析帧类型(I\P\B帧)以及将视频播放序列转换为编码序列
调用顺序如下:
x264_encoder_encode —> x264_lookahead_get_frames —> x264_slicetype_decide
x264_lookahead_get_frames函数:
void x264_lookahead_get_frames( x264_t *h )
{
if( h->param.i_sync_lookahead ) // 前向考虑帧数
{ /* We have a lookahead thread, so get frames from there */
x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
while( !h->lookahead->ofbuf.i_size && h->lookahead->b_thread_active )
x264_pthread_cond_wait( &h->lookahead->ofbuf.cv_fill, &h->lookahead->ofbuf.mutex );
x264_lookahead_encoder_shift( h );
x264_pthread_mutex_unlock( &h->lookahead->ofbuf.mutex );
}
else
{ /* We are not running a lookahead thread, so perform all the slicetype decide on the fly */
//currect[]必须为空,next不能为空,next为空意味着没有待确定类型的帧,后面就没必要进行帧类型分析了
if( h->frames.current[0] || !h->lookahead->next.i_size )
return;
//分析lookahead->next->list帧的类型
x264_stack_align( x264_slicetype_decide, h ); // x264_slicetype_decide()用于确定帧类型
//更新lookahead->last_nonb
x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] ); // 更新最后一个非B帧
int shift_frames = h->lookahead->next.list[0]->i_bframes + 1; // 计算需要移动的帧数
//将lookahead->next.list中最左边shift_frames个帧移动到lookahead->ofbuf.list
x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, shift_frames );
/* For MB-tree and VBV lookahead, we have to perform propagation analysis on I-frames too. */
if( h->lookahead->b_analyse_keyframe && IS_X264_TYPE_I( h->lookahead->last_nonb->i_type ) )
x264_stack_align( x264_slicetype_analyse, h, shift_frames ); // 分析帧类型
//lookahead->ofbuf.list帧移动到frames->current
x264_lookahead_encoder_shift( h );
}
}
x264_slicetype_decide函数:
- 首先,h->lookahead->next.list为待确定帧类型列表,一般存储至少一个GOP的帧数;
- 遍历h->lookahead->next.list链表,针对是否为可变帧率对duration以及其他参数进行赋值;
- 通过x264_slicetype_analyse函数对视频帧进行类型确认,确认是I帧还是P帧或者B帧等;
- 遍历分析h->lookahead->next.list链表,获取B帧(包括参考和非参考B帧)的个数和参考型B帧的个数;
- 根据不同的码率控制计算其帧代价,为后续帧内/帧间模式选择等做准备;
- 将播放序列转换为编码序列,方便后续的编码工作;
- 对durations等参数进行更新。
//分析帧的类型(I、B、P) 以及将播放序列转换为编码序列等功能
void x264_slicetype_decide( x264_t *h )
{
x264_frame_t *frames[X264_BFRAME_MAX+2]; //