mp4v2一般是用来做h264到mp4的封装,后来经过总结和优化,出现了支持h264/h265的版本,链接如下:
mp4v2-h265
从以上链接中下载的MP4V2源码
相关接口如下:
MP4V2_EXPORT
MP4TrackId MP4AddH265VideoTrack(MP4FileHandle hFile,uint32_t timeScale,MP4Duration sampleDuration,uint16_t width,uint16_t height,uint8_t AVCProfileIndication,uint8_t profile_compat,uint8_t AVCLevelIndication,uint8_t sampleLenFieldSizeMinusOne );MP4V2_EXPORT
void MP4AddH265VideoParameterSet(MP4FileHandle hFile,MP4TrackId trackId,const uint8_t *pSequence,uint16_t sequenceLen); MP4V2_EXPORT
void MP4AddH265SequenceParameterSet(MP4FileHandle hFile,MP4TrackId trackId,const uint8_t* pSequence,uint16_t sequenceLen );MP4V2_EXPORT
void MP4AddH265PictureParameterSet(MP4FileHandle hFile,MP4TrackId trackId,const uint8_t* pPict,uint16_t pictLen );
我用的MP4v2-2.0.0 封装(打包)h265和aac到MP4文件能正常播放。为了兼容h264,我通过判断第一个I帧的NALU中是否有vps来做了一个同时支持h265和h264的mp4录制实现,这里需要了解h265和h264裸流的区别:
H.264码流
H264中,NALU类型1-5为视频帧,其余则为非视频帧。在解码过程中,我们只需要取出NALU头字节的后5位,即将NALU头字节和0x1F进行与计算即可得知NALU类型,即:
NALU类型 = NALU头字节 & 0x1F
SPS:十进制 7
PPS:十进制 8
I 帧:十进制 5
P帧:十进制 1
SEI: 十进制 6
H.265码流
HEVC全称High Efficiency Video Coding(高效率视频编码,又称H.265),是比H.264更优秀的一种视频压缩标准。HEVC在低码率视频压缩上,提升视频质量、减少容量即节省带宽方面都有突出表现。 H.265标准围绕H.264编码标准,保留原有的某些技术,同时对一些技术进行改进,编码结构大致上和H.264的架构类似。这里着重讲一下两者编码格式的区别。 同H.264一样,H.265也是以NALU的形式组织起来。而在NALU header上,H.264的HALU header是一个字节,而H.265则是两个字节。
NALU类型 = (NALU头第一字节 & 0x7E) >> 1
如下图所示:
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| F | Type | LayerId | TID |
+------------ - +---------------- - +
从图中可以看出hHEVC的nal包结构与h264有明显的不同,hevc加入了nal所在的时间层的ID,去除了nal_ref_idc,此信息合并到了naltype中,
通常情况下F为0,layerid为0, TID为1。
VPS:十进制 32
SPS:十进制 33
PPS:十进制 34
I 帧:十进制 19
P帧:十进制 1
SEI: 十进制 39
生成文件:smarthome_20210419_104841.MP4
查看文件信息:
具体使用流程:
从h265视频流中分离出vps、sps、pps、IDR(i)帧、p帧等信息进行后面处理。处理流程类似封装h264流
h264 使用sps帧 添加视频流MP4AddH264VideoTrack
h265 使用vps帧 添加视频流MP4AddH265VideoTrack
对于h265其中有个问题就是视频的宽 高信息 在sps帧中,vps初始化使用的宽高参数就 先自己赋值为实际的视频宽高了,
接着 以下几个参数设置了
vps帧就 MP4AddH265VideoParameterSet
sps帧就 MP4AddH265SequenceParameterSet
pps帧就 MP4AddH265PictureParameterSet
i和p帧就写数据MP4WriteSample
正常来说,传输给接口的数据没有问题的话,打包出来的文件就能正常播放。