赞
踩
由于网上写rtmp协议建立过程的文章比较多,这里就不再赘述,直接从发送发送音频包和视频包写起。
如果rtmp在推流链路或者拉流链路上要发送音频包和视频包数据,在发送音视频包前需要先发送onMetaData元数据包,告诉接收方发送视频的宽高信息,以及声明音频和视频的CodecID,如下图:
根据flv_v10_1.pdf的描述,aac音频的SoundFormat为10,即上图中的audiocodecid的值,flv文档部分截图如下:
H264视频的CodecID为10,即rtmp元数据onMetaData中的videocodecid值,flv文档的部分截图如下:
发送完元数据metaData后,发送视频包的第一个rtmp包必须是I帧,否则接收端解码不出视频,直到收到下一个I帧,第一个视频I帧rtmp包如下图:
上图中的00000001打头后面的数据,严格意义上来说是sps、pps信息,00000001四个字节后面的420028中的表示profile-level-id,其中0x42是profile-id值,表示的是H264 BP,0x28表示视频分辨率,这里具体是640*360
后面视频包数据的格式如下:
下面来说下,发送音频包,第一个音频包必须是音频的sequenceHeader包,如下图:
上面sequenceHeader中的0x1588的包含aac的ObjectType值,aac音频通道数channel值(单声道还是双声道),samplingFrequenceIndex:4bits,表示音频采样率索引值,44100对于值为4,48000对于值3,具体值如下:
//aac samplingFrequenceIndex值如下: SOUND_RATESampleRate96000 = 0x00 SOUND_RATESampleRate88200 = 0x01 SOUND_RATESampleRate64000 = 0x02 SOUND_RATESampleRate48000 = 0x03 SOUND_RATESampleRate44100 = 0x04 SOUND_RATESampleRate32000 = 0x05 SOUND_RATESampleRate24000 = 0x06 SOUND_RATESampleRate22050 = 0x07 SOUND_RATESampleRate16000 = 0x08 SOUND_RATESampleRate12000 = 0x09 SOUND_RATESampleRate11025 = 0x0a SOUND_RATESampleRate8000 = 0x0b
golang从asc值获取ObjectType,channel,samplingFrequenceIndex等值的代码如下:
type MpegCfgInfoSimple struct { ObjectType byte SampleRate byte //samplingFrequenceIndex Channel byte RealSampleRate int //实际采样率 } var aacRates = []int{96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350}
func (cfgInfoSimple *MpegCfgInfoSimple) GetMpegCfgInfoSimple(asc []byte) { cfgInfoSimple.ObjectType = (asc[0] >> 3) & 0xff cfgInfoSimple.SampleRate = ((asc[0] & 0x07) << 1) | asc[1]>>7 cfgInfoSimple.Channel = (asc[1] >> 3) & 0x0f cfgInfoSimple.RealSampleRate = aacRates[cfgInfoSimple.SampleRate] }
//asc的值为aac sequenceHeader中的具体值,这里以0x1588为例 asc := []byte{0x15, 0x88} cfgInfoSimple := &aac.MpegCfgInfoSimple{} cfgInfoSimple.GetMpegCfgInfoSimple(asc) fmt.Printf("---- objectType: %d, sampleRate: %d, realSampleRate: %d, channel: %d\n", cfgInfoSimple.ObjectType, cfgInfoSimple.SampleRate, cfgInfoSimple.RealSampleRate, cfgInfoSimple.Channel)
传输真实aac原始音频数据的的rtmp包如下:
aac音频AAC sequenceHeader和 AAC Raw包在flv文档中的规定如下:
rtmp发送aac音频数据,要去掉aac的ADTS头,ADTS头一般为7个字节或者9个字节,由于发送的aac音频数据为aac raw,因此发送音频数据的第一包数据中的RTMP BODY中的Control值,以及AudioSpecificConfig的值要准确,asc值包含解码aac音频数据需要的ObjectType、采样率和通道数据扥西,后面发送的AAC RAW数据中的RTMP BODY中的Control值要和sequenceHeader中的Control值保持一致,如果这些值打的不对,就会导致播放端解码aac音频数据失败。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。