mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-06 17:16:55 +08:00
重构媒体轨道等待逻辑
This commit is contained in:
127
rtp.go
Normal file
127
rtp.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/Monibuca/utils/v3/codec"
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
type RTPPublisher struct {
|
||||
rtp.Packet
|
||||
Push func(payload []byte)
|
||||
}
|
||||
type RTPAudio struct {
|
||||
RTPPublisher
|
||||
*AudioTrack
|
||||
}
|
||||
type RTPVideo struct {
|
||||
RTPPublisher
|
||||
*VideoTrack
|
||||
}
|
||||
|
||||
func (s *Stream) NewRTPVideo(codec byte) (r *RTPVideo) {
|
||||
r = &RTPVideo{
|
||||
VideoTrack: s.NewVideoTrack(codec),
|
||||
}
|
||||
r.Push = r.push
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Stream) NewRTPAudio(codec byte) (r *RTPAudio) {
|
||||
r = &RTPAudio{
|
||||
AudioTrack: s.NewAudioTrack(codec),
|
||||
}
|
||||
r.Push = r.push
|
||||
return
|
||||
}
|
||||
|
||||
func (v *RTPVideo) push(payload []byte) {
|
||||
vt := v.VideoTrack
|
||||
if err := v.Unmarshal(payload); err != nil {
|
||||
return
|
||||
}
|
||||
t := v.Timestamp / 90
|
||||
if t < vt.Buffer.GetLast().Timestamp {
|
||||
if vt.WaitIDR.Err() == nil {
|
||||
return
|
||||
}
|
||||
//有B帧
|
||||
var tmpVT VideoTrack
|
||||
tmpVT.Buffer = NewRing_Video()
|
||||
tmpVT.revIDR = func() {
|
||||
tmpVT.IDRIndex = tmpVT.Buffer.Index
|
||||
}
|
||||
// tmpVT.pushRTP = func(p rtp.Packet) {
|
||||
// tmpVT.Push(VideoPack{Timestamp:p.Timestamp/90,Payload:p.Payload})
|
||||
// }
|
||||
gopBuffer := tmpVT.Buffer //缓存一个GOP用来计算dts
|
||||
var gopFirst byte
|
||||
var tsSlice TSSlice
|
||||
for i := vt.IDRIndex; vt.Buffer.Index != i; i++ {
|
||||
t := vt.Buffer.GetAt(i)
|
||||
c := gopBuffer.Current
|
||||
c.VideoPack = t.VideoPack.Clone()
|
||||
tsSlice = append(tsSlice, gopBuffer.Current.Timestamp)
|
||||
gopBuffer.NextW()
|
||||
}
|
||||
v.Push = func(payload []byte) {
|
||||
if err := v.Unmarshal(payload); err != nil {
|
||||
return
|
||||
}
|
||||
t := v.Timestamp / 90
|
||||
c := gopBuffer.Current
|
||||
vp := VideoPack{Timestamp: t, NALUs: [][]byte{v.Payload}}
|
||||
tmpVT.PushNalu(vp)
|
||||
if c != gopBuffer.Current {
|
||||
if c.IDR {
|
||||
sort.Sort(tsSlice) //排序后相当于DTS列表
|
||||
var offset uint32
|
||||
for i := 0; i < len(tsSlice); i++ {
|
||||
j := gopFirst + byte(i)
|
||||
f := gopBuffer.GetAt(j)
|
||||
if f.Timestamp+offset < tsSlice[i] {
|
||||
offset = tsSlice[i] - f.Timestamp
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(tsSlice); i++ {
|
||||
f := gopBuffer.GetAt(gopFirst + byte(i))
|
||||
f.CompositionTime = f.Timestamp + offset - tsSlice[i]
|
||||
f.Timestamp = tsSlice[i]
|
||||
vt.PushNalu(f.VideoPack)
|
||||
}
|
||||
gopFirst = gopBuffer.Index - 1
|
||||
tsSlice = nil
|
||||
}
|
||||
tsSlice = append(tsSlice, t)
|
||||
}
|
||||
}
|
||||
v.Push(payload)
|
||||
return
|
||||
}
|
||||
vt.PushNalu(VideoPack{Timestamp: t, NALUs: [][]byte{v.Payload}})
|
||||
}
|
||||
func (v *RTPAudio) push(payload []byte) {
|
||||
at := v.AudioTrack
|
||||
if err := v.Unmarshal(payload); err != nil {
|
||||
return
|
||||
}
|
||||
switch at.CodecID {
|
||||
case 10:
|
||||
v.Push = func(payload []byte) {
|
||||
if err := v.Unmarshal(payload); err != nil {
|
||||
return
|
||||
}
|
||||
for _, payload = range codec.ParseRTPAAC(v.Payload) {
|
||||
at.PushRaw(AudioPack{Timestamp: v.Timestamp / 90, Raw: payload})
|
||||
}
|
||||
}
|
||||
case 7, 8:
|
||||
v.Push = func(payload []byte) {
|
||||
if err := v.Unmarshal(payload); err != nil {
|
||||
return
|
||||
}
|
||||
at.PushRaw(AudioPack{Timestamp: v.Timestamp / 8, Raw: v.Payload})
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user