RTSP流封装成MP4方法总结

目的:为了更好的学习音视频知识,特把自己在录制学习过程中遇到的问题以及解决办法记录下来,方便自己以后查看的同时,也给后面学习这方面的人提供一些参考。

方法:
1.利用ffmpeg进行解码和编码,生成符合MP4v2要求的H264视频流和AAC音频流;
2.利用MP4v2对H264和aac进行合并;

注意问题:
1.确认RTSP流中的音频和视频是否是固定帧率?
由于MP4v2库针对固定帧率和非固定帧率有两种设置,因此需要根据实际情况进行设置。下面给出个人测试过程中的经验,如何判断固定帧率还是非固定帧率。

RTSP流封装成MP4方法总结_第1张图片
如果视频和音频每帧之间的间隔基本都一样,可以判断为固定帧率,否则为非固定帧率。
RTSP流封装成MP4方法总结_第2张图片
从图上可以看出,除了起始部分有差异外,后面视频每帧间隔为90000/25=3600,音频为aac间隔为1024。因此可以判定为固定帧率。
测试工程地址链接下载https://pan.baidu.com/s/1Wuhqsi6Gt0OiTSXWHVS8hA,该工程运行缺失的dll文件下载地址为:https://pan.baidu.com/s/1UlpTfaT4J2SP3zpMcLs0ng
1.固定帧率录制方式设置
H264视频固定帧率录制方式的参数设置:
MP4AddH264VideoTrack(m_hFile, Video_Time_Scale, 90000/ 25, nWidth, nHeight,sData[sps + 1], sData[sps + 2], sData[sps + 3], DEFAULT_VIDEO_TRACK_NUM);

MP4WriteSample(m_hFile, m_videoTrack, sData, nSize,MP4_INVALID_DURATION,0,true);

AAC音频固定帧率录制方式参数设置:
MP4AddAudioTrack(m_hFile, Audio_Time_Scale, 1024, MP4_MPEG4_AUDIO_TYPE);
MP4WriteSample(m_hFile, m_audioTrack, sData, nSize,MP4_INVALID_DURATION,0,true);

2.变帧率录制参数设置
H264视频非固定帧率录制方式的参数设置:
MP4AddH264VideoTrack(m_hFile, Video_Time_Scale,MP4_INVALID_DURATION, nWidth, nHeight,sData[sps + 1], sData[sps + 2], sData[sps + 3], DEFAULT_VIDEO_TRACK_NUM);

MP4WriteSample(m_hFile, m_videoTrack, sData, nSize,temp,0,true);

AAC音频非固定帧率录制方式参数设置:
MP4AddAudioTrack(m_hFile, Audio_Time_Scale,MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
temp=上一帧视频时间—当前帧视频时间

MP4WriteSample(m_hFile, m_audioTrack, sData, nSize,temp,0,true);
temp=上一帧音频时间—当前帧音频时间

2.确认RTSP流中视频解码参数(r_frame_rate)是否随着摄像机中帧率参数的设置而改变?
根据测试经验,部分摄像机存在更改摄像机内部帧率参数,获取的r_frame_rate参数并没有发生改变,因此直接影响后面视频时间戳设置出现问题,导致音视频不同步,如果是采用非固定帧率的录制方法,不会出现这种问题,因为变帧率是根据录制过程中实际数据采集时间进行设置(前提是采用MP4v2进行H264和AAC的封装)。

3.获取SPS和PPS参数
sps与pps决定着视频是否能正常显示,如果设置不正确会导致视频画面一直为黑色。
参数获取方法:利用ffmpeg获取rtsp流中的sps与pps,sps与pps主要存贮在ic->streams[video_index]->codecpar->extradata中,中间以00 00 00 01进行间隔,前面主要是sps,后面是pps.

4.添加音频和视频输出流
在实际获取流过程中,音频流和视频流的ID并非固定,有时候输入视频流ID为0,音频流ID为1;有时候视频流ID为1,音频流为0;如果不按照前面音频和视频的顺序进行设置,有可能会导致录制的视频没有声音。
RTSP流封装成MP4方法总结_第3张图片
5.利用MP4V2写入视频和音频数据
由于大部分摄像机的视频为H264格式(H265),与期望格式一致,因此,不准备对视频进行单独解码和编码,只需要获取h264裸流数据即可。
RTSP流封装成MP4方法总结_第4张图片
这里采用变帧率进行录制,首先找到packet.data中00 00 00 01标记的位置,然后将此标记后面数据利用MP4v2进行封装,就完成了每一帧视频的写入。

至于音频 ,所采用的方式也有所不同,这主要是由于摄像机中的多种音频格式所决定的。因此,音频需要先进行解码,然后进行AAC编码,AAC编码部分可以参考ffmpeg官网API中的transcode_aac.c示例。

由于AAC有两种格式,这里对编码后的AAC音频帧直接利用MP4v2进行写入,不需要去掉头部的7个字节。

录制验证:
最终利用可执行程序进行录制,可以生成完整的MP4文件。如果需要,请点击testMerge进行下载。
RTSP流封装成MP4方法总结_第5张图片
由于dll文件所占用资源较大,dll与原始工程分开放置。
dll下载链接:链接:https://pan.baidu.com/s/1UlpTfaT4J2SP3zpMcLs0ng

源码下载链接:https://download.csdn.net/download/unfound/11605618
该资源中提供固定帧率和变帧率两种录制方式,自行进行选择。

你可能感兴趣的:(音视频)