-
Notifications
You must be signed in to change notification settings - Fork 194
/
g711.go
82 lines (74 loc) · 1.76 KB
/
g711.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package track
import (
"io"
"go.uber.org/zap"
"m7s.live/engine/v4/codec"
. "m7s.live/engine/v4/common"
"m7s.live/engine/v4/util"
)
var _ SpesificTrack = (*G711)(nil)
func NewG711(puber IPuber, alaw bool, stuff ...any) (g711 *G711) {
g711 = &G711{}
if alaw {
g711.Name = "pcma"
g711.PayloadType = 8
} else {
g711.Name = "pcmu"
g711.PayloadType = 0
}
if alaw {
g711.CodecID = codec.CodecID_PCMA
} else {
g711.CodecID = codec.CodecID_PCMU
}
g711.SampleSize = 8
g711.Channels = 1
g711.AVCCHead = []byte{(byte(g711.CodecID) << 4) | (1 << 1)}
g711.SetStuff(uint32(8000), g711, stuff, puber)
if g711.BytesPool == nil {
g711.BytesPool = make(util.BytesPool, 17)
}
go g711.Attach()
return
}
type G711 struct {
Audio
}
func (g711 *G711) WriteAVCC(ts uint32, frame *util.BLL) error {
if l := frame.ByteLength; l < 2 {
g711.Error("AVCC data too short", zap.Int("len", l))
return io.ErrShortWrite
}
i := 0
frame.Range(func(v util.Buffer) bool {
if i == 0 {
v = v.SubBuf(1, v.Len()-1)
}
g711.Value.AUList.Push(g711.BytesPool.GetShell(v))
i++
return true
})
g711.Audio.WriteAVCC(ts, frame)
return nil
}
func (g711 *G711) WriteRTPFrame(rtpItem *util.ListItem[RTPFrame]) {
frame := &rtpItem.Value
g711.Value.RTP.Push(rtpItem)
if g711.SampleRate != 90000 {
g711.generateTimestamp(uint32(uint64(frame.Timestamp) * 90000 / uint64(g711.SampleRate)))
}
g711.AppendAuBytes(frame.Payload)
g711.Flush()
}
func (g711 *G711) CompleteRTP(value *AVFrame) {
if value.AUList.ByteLength > RTPMTU {
var packets [][][]byte
r := value.AUList.Next.Value.NewReader()
for bufs := r.ReadN(RTPMTU); len(bufs) > 0; bufs = r.ReadN(RTPMTU) {
packets = append(packets, bufs)
}
g711.PacketizeRTP(packets...)
} else {
g711.Audio.CompleteRTP(value)
}
}