韩菱纱本子:Encode
来源:百度文库 编辑:九乡新闻网 时间:2024/05/05 10:51:35
static int Encode( x264_param_t *param, cli_opt_t *opt )
{
x264_t *h; //编码器句柄
x264_picture_t pic; //当前编码帧
int i_frame, i_frame_total; //编码帧数目统计
int64_t i_start, i_end; //编码时间统计
int64_t i_file; //当前NAL打包的长度
int i_frame_size; //编码后的码流长度
int i_update_interval; //统计编码信息的间隔长度
char buf[200]; //编码信息
opt->b_progress &= param->i_log_level < X264_LOG_DEBUG; //调试信息等级
i_frame_total = p_get_frame_total( opt->hin ); //读取输入文件的总帧数
i_frame_total -= opt->i_seek;
if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total )
&& param->i_frame_total > 0 )
i_frame_total = param->i_frame_total; //总编码帧数目
param->i_frame_total = i_frame_total;
i_update_interval = i_frame_total ? x264_clip3( i_frame_total / 1000, 1, 10 ) : 10;//编码信息更新间隔
if( ( h = x264_encoder_open( param ) ) == NULL ) //对不正确的264_t结构体(h的类型是264_t * )参数进行修改,并对各结构体参数、编码、预测等需要的参数进行初始化。
{
fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
p_close_infile( opt->hin ); //关闭YUV文件
return -1;
}
if( p_set_outfile_param( opt->hout, param ) ) //设置输出文件格式
{
fprintf( stderr, "x264 [error]: can't set outfile param\n" );
p_close_infile( opt->hin ); //关闭YUV文件
p_close_outfile( opt->hout ); //关闭码流文件
return -1;
}
/*创建一帧图像空间*/
if( x264_picture_alloc ( &pic, X264_CSP_I420, param->i_width, param->i_height ) < 0 )
{
fprintf( stderr, "x264 [error]: malloc failed\n" );
return -1;
} //x264_picture_alloc() 按照色度空间分配内存,并返回内存的首地址作为指针
i_start = x264_mdate(); //用于编码用时的计算,设定起始时间
/* 循环编码所有帧
利用下面一个for循环,开始一帧一帧进行编码。在这个for循环中, 读取 p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ), 编码并保存 i_file += Encode_frame( h, opt->hout, &pic );
*/
for( i_frame = 0, i_file = 0; b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); )
{
if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )
//按照h->hin提供的输入文件的地址,读入图像的内容到&pic提供的存储区的首地址
break;
pic.i_pts = (int64_t)i_frame * param->i_fps_den;
if( opt->qpfile )
parse_qpfile( opt, &pic, i_frame + opt->i_seek );//从指定文件中读qp值留下的接口,qpfile为文件的首地址
else
{
pic.i_type = X264_TYPE_AUTO;
pic.i_qpplus1 = 0; // 未强制任何编码参数
}
/*编码一帧图像,h编码器句柄,hout码流文件,pic预编码帧图像*/
i_frame_size =Encode_frame( h, opt->hout, &pic );
if( i_frame_size < 0 )
return -1;
i_file += i_frame_size;
i_frame++;
/* 更新数据行,用于显示整个编码过程的进度*/
if( opt->b_progress && i_frame % i_update_interval == 0 )
{
int64_t i_elapsed = x264_mdate() - i_start;
double fps = i_elapsed > 0 ? i_frame * 1000000. / i_elapsed : 0; //帧率的计算
double bitrate = (double) i_file * 8 * param->i_fps_num / ( (double) param->i_fps_den * i_frame * 1000 );
if( i_frame_total )
{
int eta = i_elapsed * (i_frame_total - i_frame) / ((int64_t)i_frame * 1000000);
sprintf( buf, "x264 [%.1f%%] %d/%d frames, %.2f fps, %.2f kb/s, eta %d:%02d:%02d",
100. * i_frame / i_frame_total, i_frame, i_frame_total, fps, bitrate,
eta/3600, (eta/60)%60, eta%60 );
}
else
{
sprintf( buf, "x264 %d frames: %.2f fps, %.2f kb/s", i_frame, fps, bitrate );
}
fprintf( stderr, "%s \r", buf+5 );
SetConsoleTitle( buf ); //命令行标题设定
fflush( stderr ); // 刷新输出缓冲区
}
}
/* 排空延迟的B帧*/
while( x264_encoder_delayed_frames( h ) )
{
i_frame_size = Encode_frame( h, opt->hout, NULL );
if( i_frame_size < 0 )
return -1;
i_file += i_frame_size;
}
i_end = x264_mdate();
x264_picture_clean( &pic ); //申请释放一帧图像控件
if( opt->b_progress )
fprintf( stderr, " \r" );
x264_encoder_close( h ); //关闭编码器
x264_free( mux_buffer ); //释放内存
fprintf( stderr, "\n" );
if( b_ctrl_c ) //信号中断,显示帧序号
fprintf( stderr, "aborted at input frame %d\n", opt->i_seek + i_frame );
p_close_infile( opt->hin ); //关闭输入的YUV文件
p_close_outfile( opt->hout ); //关闭输出的码流
if( i_frame > 0 ) //打印当前的统计信息:fps kbps
{
double fps = (double)i_frame * (double)1000000 /
(double)( i_end - i_start );
fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps,
(double) i_file * 8 * param->i_fps_num /
( (double) param->i_fps_den * i_frame * 1000 ) );
}
return 0;
}