x264代码剖析(九):x264_encoder_encode()函数之x264_slice's'_write()函数
x264_encoder_encode()函数的核心函数就是x264_slices_write()函数。在x264_slices_write()函数中,最主要的工作就是调用了x264_slice_write()函数(注意“x264_slices_write()”和“x264_slice_write()”名字差了一个“s”),x264_slice_write()函数才是真正完成编码的核心函数,如下图所示。
1、x264_slices_write()函数
在x264_slices_write()函数中,最主要的工作就是调用了x264_slice_write()函数,需要注意,x264_slices_write()调用了x264_slice_write()。其中x264_slices_write()的单位为帧,而x264_slice_write()的单位为Slice。最常见的情况下一个帧里面只有一个Slice,但是也有可能一个帧里面有多个Slice。对应的代码如下:
/******************************************************************/
/******************************************************************/
/*
======Analysed by RuiDong Fang
======Csdn Blog:http://blog.csdn.net/frd2009041510
======Date:2016.03.10
*/
/******************************************************************/
/******************************************************************/
/************====== x264_slices_write()函数 ======************/
/*
功能:编码数据(最关键的步骤),其中调用了x264_slice_write()完成了编码的工作
(注意“x264_slices_write()”和“x264_slice_write()”名字差了一个“s”)。
*/
static void *x264_slices_write( x264_t *h )
{
int i_slice_num = 0;
int last_thread_mb = h->sh.i_last_mb;
/* init stats */
memset( &h->stat.frame, 0, sizeof(h->stat.frame) );
h->mb.b_reencode_mb = 0;
//循环每一个slice(一幅图像可以由多个Slice构成)
while( h->sh.i_first_mb + SLICE_MBAFF*h->mb.i_mb_stride <= last_thread_mb )
{
h->sh.i_last_mb = last_thread_mb;
if( !i_slice_num || !x264_frame_new_slice( h, h->fdec ) )
{
if( h->param.i_slice_max_mbs )
{
if( SLICE_MBAFF )
{
// convert first to mbaff form, add slice-max-mbs, then convert back to normal form
int last_mbaff = 2*(h->sh.i_first_mb % h->mb.i_mb_width)
+ h->mb.i_mb_width*(h->sh.i_first_mb / h->mb.i_mb_width)
+ h->param.i_slice_max_mbs - 1;
int last_x = (last_mbaff % (2*h->mb.i_mb_width))/2;
int last_y = (last_mbaff / (2*h->mb.i_mb_width))*2 + 1;
h->sh.i_last_mb = last_x + h->mb.i_mb_stride*last_y;
}
else
{
h->sh.i_last_mb = h->sh.i_first_mb + h->param.i_slice_max_mbs - 1;
if( h->sh.i_last_mb < last_thread_mb && last_thread_mb - h->sh.i_last_mb < h->param.i_slice_min_mbs )
h->sh.i_last_mb = last_thread_mb - h->param.i_slice_min_mbs;
}
i_slice_num++;
}
else if( h->param.i_slice_count && !h->param.b_sliced_threads )
{
int height = h->mb.i_mb_height >> PARAM_INTERLACED;
int width = h->mb.i_mb_width << PARAM_INTERLACED;
i_slice_num++;
h->sh.i_last_mb = (height * i_slice_num + h->param.i_slice_count/2) / h->param.i_slice_count * width - 1;
}
}
h->sh.i_last_mb = X264_MIN( h->sh.i_last_mb, last_thread_mb );
//真正的编码——编码1个Slice
//x264_stack_align()应该是平台优化过程中内存对齐的工作
//实际上就是调用x264_slice_write()
if( x264_stack_align( x264_slice_write, h ) ) //调用x264_slice_write(),进入核心编码函数块
goto fail;
h->sh.i_first_mb = h->sh.i_last_mb + 1;//注意这里对i_first_mb进行了赋值
// if i_first_mb is not the last mb in a row then go to the next mb in MBAFF order
if( SLICE_MBAFF && h->sh.i_first_mb % h->mb.i_mb_width )
h->sh.i_first_mb -= h->mb.i_mb_stride;
}
return (void *)0;
fail:
/* Tell other threads we're done, so they wouldn't wait for it */
if( h->param.b_sliced_threads )
x264_threadslice_cond_broadcast( h, 2 );
return (void *)-1;
}
2、x264_slice_write()函数
x264_slice_write()是完成编码工作的函数。该函数中包含了去块效应滤波,运动估计,宏块编码,熵编码等模块。x264_slice_write()调用了如下函数:
x264_nal_start()&