1、用户应用程序可以调用6410自带的编码库,在这些库的函数可以直接进行系统层的函数调用(open、iotcl、close)
2、在解码处理过程中,S3C6410支持两种模式的输入流:LINE_BUF和RING_BUF。
3、在LINE_BUF模式中,应用程序需要根据一帧实际的大小来填充输入缓存。LINE_BUF模式支持MPEG4/H.263、H.264、VC-1解码。
4、LINE_BUF与RING_BUF的比较:LINE_BUF模式,填充单一编码帧,缓存大小随着当前帧的大小改变;RING_BUF模式,缓存被分割成几个固定大小的部分来填充编码的数据。
5、在编码任务中,FRAM_BUF被用于输入缓存;LINE_BUF被用于数出缓存。
6、数据结构:SSBSIP_H264_STREAM_INFO,里面包含了帧的长与宽(width and height)。
7、MFC Decoder (RING_BUF Mode)中函数解释:
1)void * SsbSipMfcDecodeInit (int dec_type):创建MFC解码事件,针对H.264,参数设置为SSBSIPMFCDEC_H264,函数调用成功,则返回一个句柄。
2)int SsbSipMfcDecodeExe (void *openHandle, long lengthFill)。函数用于解码视频流。参数openHandle为创建解码事件时返回的句柄,参数lengthFill为输入缓存中数据的长度。
3)int SsbSipMfcDecodeDeInit (void * openHandle)。用于释放编码资源。
4)void * SsbSipMfcDecodeGetInBuf (void * openHandle, long * size)。函数功能:得到解码输入缓存的地址。参数size:填充进输入缓存中数据的大小。
8、H.264 encode 所包含的函数:
SsbSipH264EncodeInti()
SsbSipH264EncodeExe()
SsbSipH264EncodeDeInit()
SsbSipH264EncodeGetInBuf()
SsbSipH264EncodeGetOutBuf()
SsbSipH264EncodeGetConfig()
SsbSipH264EncodeSetConfig()
编码函数详解:
1)SsbSipH264EncodeInit(width, height, frame_rate, bitrate, gop_num)
创建了一个H.264事件,分别定义了每一帧图像的长宽,帧的速度,比特率,GOP(Group of Pictures)策略影响编码质量(设置编码的质量系数)。返回一个handle句柄。
2) SsbSipH264EncodeExe()
对MFC内部的一些结构体进行初始化。例:ret= SsbSipH264EncodeExe(handle)
将YUV420的帧转为H.264视频流。
3) SsbSipH264EncodeDeInit()。例:SsbSipH264EncodeDeInit(handle)解除映射的过程,释放编码资源。
4)SsbSipH264EncodeGetInBuf()。
例:SsbSipH264EncodeGetInBuf(handle , 0)。得到输入缓冲区的地址。
5)SsbSipH264EncodeGetOutBuf()。得到输出缓冲区的大小。
6)SsbSipH264EncodeSetConfig()。配置编码参数。
例 cur_pic_opt[0] = H264_ENC_PIC_OPT_SKIP;
cur_pic_opt[1] = 1;
SsbSipH264EncodeSetConfig(handle, H264_ENC_SETCONF_CUR_PIC_OPT, &cur_pic_opt);
或者
cur_pic_opt[0] = H264_ENC_PIC_OPT_RECOVERY;
cur_pic_opt[1] = 1;
SsbSipH264EncodeSetConfig(handle, H264_ENC_SETCONF_CUR_PIC_OPT, &cur_pic_opt);
7)SsbSipH264EncodeGetConfig()。得到编码参数。
待修改(放入源码)。。。
/*
//此程序为H.264编码程序。净输入参数为7个;
参数0:程序名
参数1:源文件名。 参数2:输出文件名
参数3:宽 参数4:高
参数5:帧频 参数6:码率
参数7:两个相离关键帧之间最多包含多少个帧(B 或P 帧)
*/
int Test_H264_Encoder(int argc, char **argv)
{
int in_fd, out_fd;
char *in_addr;
int file_size;
int frame_count;
int frame_size;
void *handle;
int width, height, frame_rate, bitrate, gop_num;
unsigned char *p_inbuf;
unsigned char *p_outbuf;
long size;
int ret;
struct stat s;
#ifdef FPS
struct timevalstart, stop;
unsigned int time = 0;
int frame_cnt = 0;
#endif
if (argc != 8) {
printf("Usage : mfc <YUV file name> <output filename> <width> <height> ");
printf("<frame rate> <bitrate> <GOP number>\n");
return -1;
}
/
// Input/Output File Open //
/
in_fd = open(argv[1], O_RDONLY);
out_fd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0644);
if( (in_fd < 0) || (out_fd < 0) ) {
printf("input/output file open error\n");
return -1;
}
// get input file size
fstat(in_fd, &s);
file_size = s.st_size;
// mapping input file to memory
/
// Input/Output Buffer Memory Mapping //
/
//mmap()用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。
in_addr = (char *)mmap(0, file_size, PROT_READ, MAP_SHARED, in_fd, 0);//
if(in_addr == NULL) {
printf("input file memory mapping failed\n");
return -1;
}
width = atoi(argv[3]);
height = atoi(argv[4]);
frame_rate = atoi(argv[5]);
bitrate = atoi(argv[6]);
gop_num = atoi(argv[7]);
frame_size = (width * height * 3) >> 1; //YUV420格式单帧图像的字节大小
frame_count = file_size / frame_size; //总的文件大小除以单帧大小,得到帧数。
printf("file_size : %d, frame_size : %d, frame count : %d\n", file_size, frame_size, frame_count);
/
// 1. Create new instance and set the encoder parameters //
// (SsbSipH264EncodeInit) //
/
//初始化编码器,传入配置参数,获得编码器句柄。
handle = SsbSipH264EncodeInit(width, height, frame_rate, bitrate, gop_num);
if (handle == NULL) {
LOG_MSG(LOG_ERROR, "Test_Encoder", "SsbSipMPEG4EncodeInit Failed\n");
return -1;
}
/
/// 2. Obtaining the Input Buffer ///
/// (SsbSipH264EncodeGetInBuf) ///
/
p_inbuf = SsbSipH264EncodeGetInBuf(handle, 0);
while(frame_count > 0)
{
printf("frame count : %d\n", frame_count);
// Copy YUV data into input buffer //
//in_addr为文件在内存映射的首地址,p_inbuf为编码器输入缓存。
memcpy(p_inbuf, in_addr, frame_size);
in_addr += frame_size;
#ifdef FPS
gettimeofday(&start, NULL);
#endif
// 3. ENCODE //
// (SsbSipH264EncodeExe) //
ret = SsbSipH264EncodeExe(handle);
#ifdef FPS
gettimeofday(&stop, NULL);
time += measureTime(&start, &stop); //time为编码开始和结束时间。貌似没看到有measureTime函数相关介绍。。。。
frame_cnt++;
#endif
/
/// 4. Obtaining the Output Buffer ///
/// (SsbSipH264EncodeGetOutBuf) ///
/
p_outbuf = SsbSipH264EncodeGetOutBuf(handle, &size);
#ifndef FPS
write(out_fd, p_outbuf, size);
#endif
frame_count--;
}
#ifdef FPS
printf("Encoding Time : %u, Frame Count : %d, FPS : %f\n", time, frame_cnt, (float)frame_cnt*1000/time);
//time:整个源文件编码花费的总时间。frame_cnt:转换的总帧数。
//FPS:每秒转换的帧数(总帧数被时间均分,单位时间得到多少帧)。
#endif
close(in_fd);
close(out_fd);
return 0;
}