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; }
相关文章推荐
- PS: Going Deeper With Convolutions___CVPR2015
- C# 的 Socket基本编程例子
- homerHEVC代码阅读(1)——参数解析
- 从零开始写javaweb框架笔记6-需求分析与系统设计
- Java集合中HashMap的实现原理
- 在eclipse使用log4j记录日志
- python异常
- share中简单聊天界面的实现<代码>
- 几款常用PHP开发工具
- thinkphp笔记-常量参考
- C++实现输入输出运算符重载、友元函数和成员函数实现复数类Complex
- openstack之neutron代码分析---(1)neutron初始化流程
- Java.IO note
- 【Eclipse for IAR】使用 Eclipse 编写 IAR 程序
- 操作系统概念 管程Java代码实现
- C#拆箱与装箱
- java+struts+spring验证用户名是否存在
- 《代码整洁之道》-- 写代码时需要注意的命名技巧
- C++学习笔记——一只P转C的OIer的学习历程
- Java数据库操作