AudioSpecificConfig

AAC格式里有个复杂的AudioSpecificConfig, 在FLV格式里称为AAC sequence header。在正式播放ADTS AAC数据包之前,需要用AudioSpecificConfig生成一个audio_tag交给播放器。
其实AudioSpecificConfig的内容,完全可以通过ADTS的7字节头生成,具体来说,AudioSpecificConfig需要3部分数据:profile(LC,Main,HE),sample_rate, channel,这3个数据在ADTS头里都可以找到。具体算法见代码。
有了这3个数据以后,可以进行合并生成2个字节,就是所谓的AudioSpecificConfig,见代码部分config1/config2的算法。

//output AAC config header:
var profile:int = ((payload[2]&0xc0)>>6)+1;
var sample_rate:int = (payload[2]&0x3c)>>2;
var channel:int = ((payload[2]&0x1)<<2)|((payload[3]&0xc0)>>6);
var config1:int = (profile<<3)|((sample_rate&0xe)>>1);
var config2:int = ((sample_rate&0x1)<<7)|(channel<<3);
var aacSeqHeader:ByteArray = new ByteArray();
aacSeqHeader.writeByte(config1);
aacSeqHeader.writeByte(config2);

根据第一个ADTS包生成的aacSeqHeader,打包到audio_tag里,交给NetStream,后面的ADTS包就可以直接打包成audio_tag播放了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
av包是lal库的一个子包,主要用于处理音视频数据。下面是av包的部分代码,你可以参考一下: ```go package av import ( "errors" "fmt" ) // 音视频数据类型 type MediaType int const ( MediaTypeUnknown MediaType = iota // 未知类型 MediaTypeAudio // 音频 MediaTypeVideo // 视频 ) // Packet表示音视频数据包 type Packet struct { IsAudio bool // 是否为音频数据 Time uint32 // 时间戳 Data []byte // 数据 Type MediaType // 数据类型 } // SampleRate表示采样率 type SampleRate int const ( SampleRateUnknown SampleRate = iota // 未知采样率 SampleRate44100 // 44100Hz SampleRate48000 // 48000Hz ) // ChannelLayout表示音频通道布局 type ChannelLayout int const ( ChannelLayoutUnknown ChannelLayout = iota // 未知布局 ChannelLayoutMono // 单声道 ChannelLayoutStereo // 立体声 ChannelLayout5_1 // 5.1声道 ChannelLayout7_1 // 7.1声道 ) // AudioSpecificConfig表示AAC音频编码配置 type AudioSpecificConfig struct { Profile int // 编码配置文件号 SampleRate SampleRate // 采样率 Channel int // 声道数 ChannelMode ChannelLayout // 声道布局 } // AVPacket表示音视频数据包,用于传输音视频数据和控制信息。 type AVPacket struct { IsKeyFrame bool // 是否为关键帧 TimeStamp uint32 // 时间戳 Data []byte // 数据 Type MediaType // 数据类型 CodecID CodecID // 编码器ID Width int // 视频宽度 Height int // 视频高度 FrameRate float32 // 视频帧率 SampleRate SampleRate // 音频采样率 Channel int // 音频声道数 AacConfig *AudioSpecificConfig // AAC音频编码配置 } // CodecID表示编码器ID type CodecID int const ( CodecIDEsds CodecID = iota + 1 // AAC ESDS编码 CodecIDAVC // H.264编码 CodecIDHEVC // H.265编码 CodecIDOpus // Opus编码 ) // NewAudioPacket创建一个音频数据包 func NewAudioPacket(time uint32, data []byte) *Packet { return &Packet{ IsAudio: true, Time: time, Data: data, Type: MediaTypeAudio, } } // NewVideoPacket创建一个视频数据包 func NewVideoPacket(time uint32, data []byte) *Packet { return &Packet{ IsAudio: false, Time: time, Data: data, Type: MediaTypeVideo, } } // ParseAudioSpecificConfig从AAC音频数据中解析出音频编码配置 func ParseAudioSpecificConfig(data []byte) (*AudioSpecificConfig, error) { if len(data) < 2 { return nil, errors.New("invalid audio specific config") } asc := &AudioSpecificConfig{} asc.Profile = int(data[0] >> 3) if asc.Profile < 1 || asc.Profile > 4 { return nil, fmt.Errorf("invalid audio specific config: profile=%d", asc.Profile) } asc.SampleRate = SampleRate((data[0]&0x7)<<1 | (data[1]>>7)) if asc.SampleRate >= SampleRateUnknown { return nil, fmt.Errorf("invalid audio specific config: sample rate=%d", asc.SampleRate) } asc.Channel = int((data[1] >> 3) & 0xf) if asc.ChannelMode == ChannelLayoutUnknown { return nil, fmt.Errorf("invalid audio specific config: channel=%d", asc.Channel) } asc.ChannelMode = ChannelLayout((data[1] & 0x7) << 2) if asc.ChannelMode >= ChannelLayoutUnknown { return nil, fmt.Errorf("invalid audio specific config: channel mode=%d", asc.ChannelMode) } return asc, nil } ``` 在这个包中,你可以看到定义了音视频数据类型、音频采样率、音频通道布局、AAC编码配置等类型和常量。同时,还定义了音视频数据包的结构体Packet和AVPacket,以及一些用于创建和解析音视频数据包的函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值