📄 h264.h
字号:
#ifndef _H264_DEFINE
#define _H264_DEFINE 1
//Baseline(4.1)
//支持720p实时编码
//ccs dm642-600mhz sdram-133mhz
//支持主流解码器解码(coreplayer,vlc,moonlight,my mpc。。)
//2008-12-10
//modified: adds a sei slice
#define Q1 1
#define Q2 2
#define Q3 3
#define Q4 4
#define Q5 5
#define Q6 6
#define Q7 7
#define Q8 8
#define Q9 9
#define Q0 10 //恒定质量的图像质量级别
#define IFrame 1
#define PFrame 3
#define H264_Handle void *
typedef struct User_parameter
{
int width; //视频输入宽度,D1:720,要求整16象素 ,运行时修改参数,必须按文件流操作
int height; //视频输入高度,D1:576,要求整16象素 ,运行时修改参数,必须按文件流操作
int cbr; //cbr = 1,使能码流控制,cbr = 0,使能质量控制
int bitrate; //Cbr = 1, 128kbps < bitrate < 8192bps;
//Cbr = 0, Quality_I~~~Quality_Io,选定不同质量,(1-10)
//Quality_I1:表明恒定质量一般以下,为低带宽准备
//Quality_I0:表明恒定质量最好,为高清准备;
//int yuv_format: //这项不填写,缺省是采用TI-yuv422格式,比如yuv422
unsigned char *bufferY; //TI-yuv422 Y分量的指针, 这个参数可以实时修改,可以直接对接ti框架的y采集指针
unsigned char *bufferU; //TI-yuv422 U分量的指针,这个参数可以实时修改,可以直接对接ti框架的u采集指针
unsigned char *bufferV; //TI-yuv422 V分量的指针,这个参数可以实时修改,可以直接对接ti框架的v采集指针
int iframe_interval; //I帧间隔 25<= iframe_interval<=1000
} User_parameter; //缺省参数:
//width = 352;
//height = 288;
//cbr = 0;
//bitrate = Q3;
//iframe_interval = 100;
H264_Handle *H264_encoder_open ( User_parameter *User_param);
//return H264_Handle * 如果为0,说明内存错误
//同时支持8个通道同时编码,每个通道都直接支持高清(qvga-1080p),所以可以一个通道编码cif另一个通道编码720p
//return H264_Handle <=0 表示分别通道错误,要考虑是否超过8个通道或者exheap过小
int H264_Encoding(H264_Handle h264_handle,User_parameter User_param,
char *encoderBuf, int *len, int *i_p, int * seqlen,
int force_I);
//return int,如果为-1,说明用户参数错误,0表示正常
//char *encoderBuf,用户申请的Buffer,编码后的码流写入到这个buffer中
//int *len, 编码后的码流大小
//int *i_p, 此码流为IFrame或PFrame
//seqlen[4],如果是PFrame,那么len等于seqlen【0】,这个数组是为了让用户实现对编码流进行各种文件容器封装
//如果是I_Frame,seqlen【0】存放sei(uuid) slice
// seqlen【1】存放sequence parameters slice
// seqlen【2】存放picture parameters slice
// seqlen【3】存放a frame slice
//len = seqlen【0】+seqlen【1】+seqlen【2】
//force_I == 1, 强制当前帧编码后为I帧, cbr==0时,force_I=1同样有意义.
//force_I == 0, I和P帧按ip帧间隔产生相应帧(iframe_interval)
int B264_close(H264_Handle h264_handle );
//return int,如果为-1,内存释放错误,0表示正常
char * H264_GetVersion(); //得到当前版本号
/*
内存资源使用规则:
添加连接文件,连接文件定义如下
SECTIONS
{
h264parameterb > H264Buffer
h264parameterc > H264Buffer
h264parameterd > H264Buffer
L2BuffersAligns8byte > H264Data
}
DM642片上sdram为256KB,
用户能使用的大小为:ISRAM=0x8000; 定义base=0x00000, len = 0x8000;(主要为用户函数使用和h264编码使用栈(1kbyte)
另外用户必须配置32KB cache,定义如下:
CSL_init();
CACHE_clean(CACHE_L2ALL, 0, 0);
CACHE_setL2Mode(CACHE_32KCACHE); //必须为32K
CACHE_enableCaching(CACHE_EMIFA_CE00);
CACHE_enableCaching(CACHE_EMIFA_CE01);
用户使用必须用这段代码加入自己的工程
除去上面用户定义的DM642片上的sdram外,其余256K-32K(Cache)-32K(stack+_inHeap) = 192K都为H264所用。
算法的H264Buffer占64KB,h264在运行中栈的大小为2KB,
堆大小按D1的象素为例,720*576*1.5*3*4约等于7MB(H264要动态申请的空间)。
在这H264-96KB内存分配中,通过CDB文件,在MEM - Memery Section Manger必须按下列规则
创建内存段
//cache: base:0x038000 len:0x08000 //32KB 可以不分配,实际上对应CACHE_setL2Mode(CACHE_32KCACHE)函数
H264Buffer: base:0x028000 len:0x010000 //64KB
H264Data: base:0x8000 len:0x20000 //128KB
ISRAM: base:0x000000 len:0x08000 //32KB
SDRAM: base:0x80000000 len:
高级选项:上面H264Buffer和H264Data空间段可以动态的调整,比如说项目只用到实时编码720p或者1080i,
那只需要打开1个handle,那么H264Data空间可以进行自由的调整,L2BuffersAligns8byte是以16KB对齐的
每个handle只需要16KB空间,那么H264Data只需开16KB空间就可以了,那么ISRAM可以开大CACHE_32KCACHE也可以开大。
当然,这必须你要cache分配的机制,它是至上向下分配的,如果CACHE_64KCACHE,那么256KB的高64KB分配给cache,
所以,这时的空间分配为:
{cdb内存分配表:
//cache: base:0x030000 len:0x010000 //64KB 可以不分配,实际上对于CACHE_setL2Mode(CACHE_32KCACHE)函数
H264Buffer: base:0x020000 len:0x010000 //64KB
H264Data: base:0x1c000 len:0x4000 //16KB
ISRAM: base:0x000000 len:0x1c000 //112KB
SDRAM: base:0x80000000 len:
}
另外,必须在CDB文件的Scheduling的PRD - Perodic Function Manager下创建
一个周期定时入口函数,定义如下:
HPrd:period(ticks):100 ,mode选continuous, function:_H264TimerTick, arg0: 0, arg1:0
C代码参考用法:
#include "h264_define.h"
void EncodeTskFxn(void)
{
User_parameter User_param;
H264_Handle h;
int seqlen[3];
User_param.bitrate = Q1; //质量最差
User_param.cbr = 0; //恒定质量
User_param.height = 576;
User_param.width = 720;
User_param.iframe_interval = 250;
h = H264_encoder_open( &User_param ) ;
for(;;)
.....
User_param.bufferY = Y; //当前采集Y分量数据指针
User_param.bufferU = U; //当前采集U分量数据指针
User_param.bufferV = V; //当前采集V分量数据指针
H264_Encoding(h,User_param,encoderBuf, &i_file, &i_p, int *seqlen,0);
.....
}
H264_close(h );
}
#include "h264_define.h"
void EncodeTskFxn(void)
{
User_parameter User_param;
H264_Handle h;
int seqlen[3];
User_param.bitrate = 1024;(当前码流设置为1024kbps)
User_param.cbr = 1;
User_param.height = 576;
User_param.width = 720;
User_param.iframe_interval = 250;
h = H264_encoder_open( User_param ) ;
for(;;)
.....
User_param.bufferY = Y; //当前采集Y分量数据指针
User_param.bufferU = U; //当前采集U分量数据指针
User_param.bufferV = V; //当前采集V分量数据指针
H264_Encoding(h,User_param,encoderBuf, &i_file, &i_p, int *seqlen,0);
.....
}
H264_close(h );
}
*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -