音视频开发---文件格式转换---h264转flv过程详解
程序员文章站
2022-07-02 10:42:43
...
将H.264封装为FLV格式 C源码CSDN下载:https://download.csdn.net/download/weixin_42462202/11037715
参考上面博文提供的c代码项目,整理一下h264转flv的流程
1、准备好flv文件头的buf(包含flv文件头信息+4字节 previous tag size)并写入目标flv文件 getFlvHeader + 写入flvFlushData
2、Script Tag Data结构 填充2个AFM包的元素(部分直接填/部分不填但记录下值的位置offfset) getVideoScriptParam(只有Script Tag Data数据) + buildTag + 写入flvFlushData
3、读取最前面2个nalu(即sps和pps)→→ getAVCSequenceHeader(将spspps数据打包成一个video tag date) +打包 + 写入
4、while循环读取nalu并打包成tag写入目标文件 (如果遇到sps则要做成一个spspps的tag写入) getvideoTagData将普通nalu打包成tag.date
5、补上前面缺少的数据 rewrite_amf_double
/*
自定义函数
写入AMF包的类型or元素个数(即写入一个enum int): ui8/16/24/32_to_bytes(uint8_t *buf, uint16_t val) 将一个8/16/24/32位数据按照大端格式存放/写入到buf
写入AMF包的元素名长度+元素名: amf_string_to_bytes(uint8_t *buf, const char *str)
写入AMF包的元素的值: *amf_double_to_bytes(uint8_t *buf, double d)
为3种tag封装一个tag头: buildTag
int getNALU(PT_NALU pNalu, FILE *pFile) 读去start_code后读取nalu_date(每读一个字节就检查是否读完本nalu)
rewrite_amf_double(FILE *fp, uint64_t position, double value)在文件的position位置填上数据value
*/
typedef struct FlvContext {
T_FlvTag flvTag;
{
unsigned char *pBuf; // 到目前位置已经准备好了的内容的buf(每次准备以tag为单位准备,且以previous tag size结尾)
unsigned int bufLen; //=FLV_HEAD_SIZE(头9字节)+FLV_TAG_PRE_SIZE(previous tag size 4字节)
unsigned char *pBufHelp; // 给本次tag(第一次:视频Script Tag Data 使用 4096足够用了)
unsigned int bufHelpLen;
unsigned int timeStamp; /* 时间戳 */
unsigned int tagType; /* 数据类型 */ // = FLV_TAG_TYPE_META;
unsigned long frameNum;
unsigned long frameRatePos;
unsigned long durationPos;
unsigned long fileSizePos;
unsigned long bitratePos;
}
T_AVParam avParam;
{
T_AudioParam audioParam;
T_VideoParam videoParam;
{
int frameType; /* 视频帧类型( I帧,P帧 ) */ //=15
unsigned int imageType; /* 图像分辨率类型 */
unsigned int form; /* 制式(PAL或N制) */
unsigned int width; /* 宽度 */ //= 320;
unsigned int height; /* 高度 */ //=240
unsigned int pitch;
unsigned int fieldFlag; /* 分场标志 */
unsigned int frameRate; //帧率
unsigned int codecType; //视频编码类型 = FLV_CODECID_H264;
}
int bHasAudio; /* 是否有音频数据 */
int bHasVideo =1; /* 是否有视频数据 */
}
unsigned int curTimeStamp; //=0
unsigned int aduioTimeInterval; //= 20;
unsigned int videoTimeInterval; //= 66; /* 一秒15帧,帧间隔15ms */
FILE *pSrcFile;
FILE *pDstFile;
} T_FlvContext, *PT_FlvContext;
T_NALU nalu[2];//分别为sps pps准备