mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-07 01:22:51 +08:00
129 lines
4.0 KiB
Go
129 lines
4.0 KiB
Go
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为lbr,2为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...)
|
||
}
|