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; } |
|