您的位置:首页 > 编程语言

homerHEVC代码阅读(2)——主函数

2015-11-29 21:02 609 查看
//  主函数
int main (int argc, char **argv)
{
// 总共的比特数量
int totalbits=0;
unsigned int msInit=0, msTotal=0;
int bCoding = 1;

// 读取的字节数
int bytes_read = 0;

// 读取的帧数和已经编码的帧数
int frames_read = 0, encoded_frames = 0;

// 输入文件、输出文件、参考文件
FILE *infile = NULL, *outfile = NULL, *reffile = NULL;

// 跳过的帧数
int skipped_frames = 0;//2075;//400+1575+25;//25;//1050;//800;//200;//0;

// 帧的数量
int num_frames = 1000;//1500;//500;//2200;//100;//700;//15;

// 这里并不是三个帧,而是一帧当中的三个分量:yuv
unsigned char *frame[3];

// 数据流
stream_t stream;

// 三个输入输出对象
// 三个分别是:输入帧、输出流、输出帧(重建帧)
encoder_in_out_t input_frame, output_stream, output_frame;

// 编码器
void *pEncoder;

nalu_t  *nalu_out[8];

// nal的数量
unsigned int num_nalus = 8;

// hevc配置
HVENC_Cfg	HmrCfg;

// 创建并初始化一个编码器
pEncoder = HOMER_enc_init();

printf("*********************************************************************************************\r\n");
printf("                                     HomerHEVC console App					\r\n");
printf("*********************************************************************************************\r\n");
printf("*********************************************************************************************\r\n");
printf("HomerApp:\r\n");

strcpy(file_in_name, FILE_IN);
strcpy(file_out_name, FILE_OUT);

// 默认不使用参考文件
//	strcpy(file_ref_name, FILE_REF);

//get default config
// 设置默认的参数
get_default_config(&HmrCfg);//	get_debug_config(&HmrCfg);

//get app arguments
// 解析用户参数
parse_args(argc, argv, &HmrCfg, &num_frames, &skipped_frames);

// 打开输入文件
if(!(infile = fopen(file_in_name, "rb")))
{
printf("Error opening input file: %s\r\n", file_in_name);
return -1;
}

// 打开输出文件
if((outfile = fopen(file_out_name, "wb")) == NULL)
{
printf("Error opening output file: %s\r\n", file_out_name);
return -1;
}

//如果设置了参考文件,那么就打开参考文件
if((strlen(file_ref_name)>0) && !(reffile = fopen(file_ref_name, "wb")))
{
printf("Error opening raw output file: %s\r\n", file_ref_name);
//		exit(0);
}

memset(&input_frame, 0, sizeof(input_frame));
memset(&output_stream, 0, sizeof(output_stream));
memset(&output_frame, 0, sizeof(output_frame));
memset(&stream, 0, sizeof(stream));

// 内存分配
// stream这个流主要用来存放读取的帧
stream.streams[0] = (unsigned char *)calloc(HmrCfg.width*HmrCfg.height, 1);
stream.streams[1] = (unsigned char *)calloc(HmrCfg.width*HmrCfg.height>>1,1);
stream.streams[2] = (unsigned char *)calloc(HmrCfg.width*HmrCfg.height>>1,1);

// 输出流
output_stream.stream.streams[0] = (unsigned char *)calloc(0x8000000,1);

// 参考帧(重建帧)
output_frame.stream.streams[0] = NULL;
output_frame.stream.streams[1] = NULL;
output_frame.stream.streams[2] = NULL;

// 如果有参考文件,那么就为参考帧分配流
if(strlen(file_ref_name)>0)//if this is not allocated, the internal copy is not done
{
output_frame.stream.streams[0] = (unsigned char *)calloc(HmrCfg.width*HmrCfg.height, 1);
output_frame.stream.streams[1] = (unsigned char *)calloc(HmrCfg.width*HmrCfg.height>>1,1);
output_frame.stream.streams[2] = (unsigned char *)calloc(HmrCfg.width*HmrCfg.height>>1,1);
}

printf("Input file: %s\r\n", file_in_name);
printf("Output file: %s\r\n", file_out_name);

// 根据cfg设置编码器的参数
if(!HOMER_enc_control(pEncoder,HENC_SETCFG,&HmrCfg))
return -1;

printf("\r\nAllocation: %d engines with %d processing threads each\r\n", HmrCfg.num_enc_engines, HmrCfg.wfpp_enable?HmrCfg.wfpp_num_threads:1);
printf("\r\n*********************************************************************************************\r\n");

msInit = get_ms();
fseek_64(infile, 0, SEEK_SET);

// 一直循环,直到文件被读取完毕
while(bCoding)
{
// 计算帧的大小
int frame_size = (int) (HmrCfg.width*HmrCfg.height*1.5);

// 跳过指定数量的帧
if(frames_read<skipped_frames)
{
fseek_64(infile, frame_size, SEEK_CUR); // move to first frame
frames_read++;
msInit = get_ms();
continue;
}

// 输入流
frame[0] = (unsigned char*)stream.streams[0];
frame[1] = (unsigned char*)stream.streams[1];
frame[2] = (unsigned char*)stream.streams[2];

// 读取一帧中的三个分量
bytes_read = fread(frame[0],HmrCfg.width,HmrCfg.height,infile)*HmrCfg.width;
bytes_read += fread(frame[1],HmrCfg.width>>1,HmrCfg.height>>1,infile)*(HmrCfg.width>>1);
bytes_read += fread(frame[2],HmrCfg.width>>1,HmrCfg.height>>1,infile)*(HmrCfg.width>>1);

// 流中数据的步长,主要用来计算色度分量的开始位置
stream.data_stride[0] = HmrCfg.width;
stream.data_stride[1] = stream.data_stride[2]  = stream.data_stride[0]/2;

// 输入文件的流
input_frame.stream = stream;

// 已经处理的帧的数量
input_frame.pts = frames_read-skipped_frames;

// 图像的类型
input_frame.image_type = IMAGE_AUTO;

if(bCoding)
{
// 判断文件是否已经读取完成
// bytes_read!=frame_size表示文件已经达到末尾
// num_frames==frames_read-skipped_frames表示已经读取了用户指定数量的帧
// 一旦这两个条件满足一个就表示文件读取完成
int bAllFilesFilled = (bytes_read!=frame_size) || (num_frames==frames_read-skipped_frames);

// 如果文件还没有读取完成,那么把刚刚读取的一帧放入容器中开始编码
if(!bAllFilesFilled)//if EOF is reached don磘 try to encode
{
num_nalus = 8;

// 开始编码,实际上是把这一帧放入输入容器中,等带编码线程取出来进行编码
HOMER_enc_encode(pEncoder, &input_frame);//, nalu_out, &num_nalus);
//				encoder_engine_thread(pEncoder);
// 帧计数增加
frames_read++;
}

// 获取一帧已编码的图像
HOMER_enc_get_coded_frame(pEncoder, &output_frame, nalu_out, &num_nalus);

// num_nalus>0表示成功获取到一个已经编码的帧
if(num_nalus>0)
{
//				printf("homer_app: slice_nalu:0x%x\r\n", nalu_out[num_nalus-1]);

// 把nal单元写入到比特流中
HOMER_enc_write_annex_b_output(nalu_out, num_nalus, &output_stream);

// 把比特流的数据写入到输出文件中
fwrite(output_stream.stream.streams[0], sizeof(unsigned char), output_stream.stream.data_size[0], outfile);
fflush(outfile);

// 统计总的比特数
totalbits+=output_stream.stream.data_size[0];

// 如果重建文件(参考文件)不为空
if(reffile!=NULL)
{
fwrite(output_frame.stream.streams[0], HmrCfg.width, HmrCfg.height, reffile);
fwrite(output_frame.stream.streams[1], HmrCfg.width>>1, HmrCfg.height>>1, reffile);
fwrite(output_frame.stream.streams[2], HmrCfg.width>>1, HmrCfg.height>>1, reffile);
}

// 统计已经编码的帧数
encoded_frames++;
}

// 如果已经把所有的帧都编码完了,那么退出循环
if(encoded_frames == num_frames || (bAllFilesFilled && encoded_frames==frames_read-skipped_frames))
{
bCoding = 0;
}
}

if(!bCoding)
{

// 关闭编码器
HOMER_enc_close(pEncoder);
msTotal += get_ms()-msInit;
printf("\r\n%d frames in %d milliseconds: %f fps", encoded_frames, msTotal, 1000.0*(encoded_frames)/(double)msTotal);

break;
}
}

//	printf("\r\npulse una tecla\r\n");
//	getchar();

// 清理
free(stream.streams[0]);
free(stream.streams[1]);
free(stream.streams[2]);
free(output_stream.stream.streams[0]);

if(strlen(file_ref_name)>0)//if this is not allocated, the internal copy is not done
{
free(output_frame.stream.streams[0]);
free(output_frame.stream.streams[1]);
free(output_frame.stream.streams[2]);
}

fclose(infile);
fclose(outfile);
if(reffile!=NULL)
fclose(reffile);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: