Files
engine/track/aac.go
2023-02-11 22:09:47 +08:00

129 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package track
import (
"io"
"net"
"time"
"go.uber.org/zap"
"m7s.live/engine/v4/codec"
. "m7s.live/engine/v4/common"
"m7s.live/engine/v4/util"
)
var _ SpesificTrack = (*AAC)(nil)
func NewAAC(stream IStream, stuff ...any) (aac *AAC) {
aac = &AAC{
SizeLength: 13,
Mode: 2,
}
aac.CodecID = codec.CodecID_AAC
aac.Channels = 2
aac.SampleSize = 16
aac.SetStuff("aac", uint32(90000), stream, int(256+128), byte(97), aac, time.Millisecond*10)
aac.SetStuff(stuff...)
aac.AVCCHead = []byte{0xAF, 1}
return
}
type AAC struct {
Audio
SizeLength int // 通常为13
Mode int // 1为lbr2为hbr
lack int // 用于处理不完整的AU,缺少的字节数
}
func (aac *AAC) WriteADTS(adts []byte) {
profile := ((adts[2] & 0xc0) >> 6) + 1
sampleRate := (adts[2] & 0x3c) >> 2
channel := ((adts[2] & 0x1) << 2) | ((adts[3] & 0xc0) >> 6)
config1 := (profile << 3) | ((sampleRate & 0xe) >> 1)
config2 := ((sampleRate & 0x1) << 7) | (channel << 3)
aac.Media.WriteSequenceHead([]byte{0xAF, 0x00, config1, config2})
aac.SampleRate = uint32(codec.SamplingFrequencies[sampleRate])
aac.Channels = channel
aac.Parse(aac.SequenceHead[2:])
aac.Attach()
}
// https://datatracker.ietf.org/doc/html/rfc3640#section-3.2.1
func (aac *AAC) WriteRTPFrame(frame *RTPFrame) {
auHeaderLen := util.ReadBE[int](frame.Payload[:aac.Mode]) >> 3 //通常为2即一个AU Header的长度
// auHeaderCount := auHeaderLen >> 1 // AU Header的个数, 通常为1
if auHeaderLen == 0 {
aac.Value.AUList.Push(aac.BytesPool.GetShell(frame.Payload))
} else {
startOffset := aac.Mode + auHeaderLen // 实际数据开始的位置
if aac.lack > 0 {
rawLen := aac.Value.AUList.ByteLength
if rawLen == 0 {
aac.Error("lack >0 but rawlen=0")
}
last := aac.Value.AUList.Pre
auLen := len(frame.Payload) - startOffset
if aac.lack > auLen {
last.Value.Push(aac.BytesPool.GetShell(frame.Payload[startOffset:]))
aac.lack -= auLen
return
} else if aac.lack < auLen {
aac.Warn("lack < auLen", zap.Int("lack", aac.lack), zap.Int("auLen", auLen))
}
last.Value.Push(aac.BytesPool.GetShell(frame.Payload[startOffset : startOffset+aac.lack]))
aac.lack = 0
return
}
for iIndex := aac.Mode; iIndex <= auHeaderLen; iIndex += aac.Mode {
auLen := util.ReadBE[int](frame.Payload[iIndex:iIndex+aac.Mode]) >> (8*aac.Mode - aac.SizeLength) //取高13bit代表AU的长度
nextPos := startOffset + auLen
if len(frame.Payload) < nextPos {
aac.lack = nextPos - len(frame.Payload)
aac.AppendAuBytes(frame.Payload[startOffset:])
break
} else {
aac.AppendAuBytes(frame.Payload[startOffset:nextPos])
}
startOffset = nextPos
}
}
}
func (aac *AAC) WriteSequenceHead(sh []byte) {
aac.Media.WriteSequenceHead(sh)
config1, config2 := aac.SequenceHead[2], aac.SequenceHead[3]
aac.Channels = ((config2 >> 3) & 0x0F) //声道
aac.SampleRate = uint32(codec.SamplingFrequencies[((config1&0x7)<<1)|(config2>>7)])
aac.ClockRate = aac.SampleRate
aac.Parse(aac.SequenceHead[2:])
aac.Attach()
}
func (aac *AAC) WriteAVCC(ts uint32, frame *util.BLL) error {
if l := frame.ByteLength; l < 4 {
aac.Error("AVCC data too short", zap.Int("len", l))
return io.ErrShortWrite
}
if frame.GetByte(1) == 0 {
aac.WriteSequenceHead(frame.ToBytes())
frame.Recycle()
} else {
au := frame.ToBuffers()
au[0] = au[0][2:]
aac.AppendAuBytes(au...)
aac.Audio.WriteAVCC(ts, frame)
}
return nil
}
func (aac *AAC) CompleteRTP(value *AVFrame) {
l := value.AUList.ByteLength
//AU_HEADER_LENGTH,因为单位是bit, 除以8就是auHeader的字节长度又因为单个auheader字节长度2字节所以再除以2就是auheader的个数。
auHeaderLen := []byte{0x00, 0x10, (byte)((l & 0x1fe0) >> 5), (byte)((l & 0x1f) << 3)} // 3 = 16-13, 5 = 8-3
var packets [][][]byte
r := value.AUList.Next.Value.NewReader()
for bufs := r.ReadN(RTPMTU); len(bufs) > 0; bufs = r.ReadN(RTPMTU) {
packets = append(packets, append(net.Buffers{auHeaderLen}, bufs...))
}
aac.PacketizeRTP(packets...)
}