mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-05 00:32:44 +08:00
4.0初步改造
This commit is contained in:
105
subscriber.go
105
subscriber.go
@@ -6,14 +6,18 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
. "github.com/Monibuca/engine/v4/common"
|
||||
"github.com/Monibuca/engine/v4/track"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type AudioFrame AVFrame[AudioSlice]
|
||||
type VideoFrame AVFrame[NALUSlice]
|
||||
|
||||
// Subscriber 订阅者实体定义
|
||||
type Subscriber struct {
|
||||
context.Context `json:"-"`
|
||||
cancel context.CancelFunc
|
||||
Ctx2 context.Context `json:"-"`
|
||||
*Stream `json:"-"`
|
||||
ID string
|
||||
TotalDrop int //总丢帧
|
||||
@@ -23,8 +27,8 @@ type Subscriber struct {
|
||||
Delay uint32
|
||||
SubscribeTime time.Time
|
||||
SubscribeArgs url.Values
|
||||
OnAudio func(uint32, *AudioPack) `json:"-"`
|
||||
OnVideo func(uint32, *VideoPack) `json:"-"`
|
||||
OnAudio func(*AudioFrame) bool `json:"-"`
|
||||
OnVideo func(*VideoFrame) bool `json:"-"`
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
@@ -51,7 +55,7 @@ func (s *Subscriber) Subscribe(streamPath string) error {
|
||||
} else {
|
||||
streamPath = u.Path
|
||||
}
|
||||
if stream := FindStream(streamPath); stream == nil {
|
||||
if stream := Streams.Get(streamPath); stream == nil {
|
||||
return errors.Errorf("subscribe %s faild :stream not found", streamPath)
|
||||
} else {
|
||||
if stream.Subscribe(s); s.Context == nil {
|
||||
@@ -62,7 +66,7 @@ func (s *Subscriber) Subscribe(streamPath string) error {
|
||||
}
|
||||
|
||||
//Play 开始播放
|
||||
func (s *Subscriber) Play(at *AudioTrack, vt *VideoTrack) {
|
||||
func (s *Subscriber) Play(at track.Audio, vt track.Video) {
|
||||
defer s.Close()
|
||||
if vt == nil && at == nil {
|
||||
return
|
||||
@@ -74,71 +78,42 @@ func (s *Subscriber) Play(at *AudioTrack, vt *VideoTrack) {
|
||||
s.PlayVideo(vt)
|
||||
return
|
||||
}
|
||||
var extraExit <-chan struct{}
|
||||
if s.Ctx2 != nil {
|
||||
extraExit = s.Ctx2.Done()
|
||||
}
|
||||
streamExit := s.Context.Done()
|
||||
select {
|
||||
case <-vt.WaitIDR: //等待获取到第一个关键帧
|
||||
case <-streamExit: //可能等不到关键帧就退出了
|
||||
return
|
||||
case <-extraExit: //可能等不到关键帧就退出了
|
||||
return
|
||||
}
|
||||
vr := vt.SubRing(vt.IDRing) //从关键帧开始读取,首屏秒开
|
||||
realSt := vt.PreItem().Timestamp // 当前时间戳
|
||||
ar := at.Clone()
|
||||
iv, vp := vr.Read()
|
||||
ia, ap := ar.TryRead()
|
||||
vst := iv.Timestamp
|
||||
chase := true
|
||||
vr := vt.ReadRing() //从关键帧开始读取,首屏秒开
|
||||
ar := at.ReadRing()
|
||||
vp := vr.Read()
|
||||
ap := ar.TryRead()
|
||||
// chase := true
|
||||
for {
|
||||
select {
|
||||
case <-extraExit:
|
||||
return
|
||||
case <-streamExit:
|
||||
return
|
||||
default:
|
||||
if ia == nil && iv == nil {
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
} else if ia != nil && (iv == nil || iv.Timestamp.After(ia.Timestamp)) {
|
||||
s.OnAudio(uint32(ia.Timestamp.Sub(vst).Milliseconds()), ap.(*AudioPack))
|
||||
ar.MoveNext()
|
||||
} else if iv != nil && (ia == nil || ia.Timestamp.After(iv.Timestamp)) {
|
||||
s.OnVideo(uint32(iv.Timestamp.Sub(vst).Milliseconds()), vp.(*VideoPack))
|
||||
if chase {
|
||||
if add10 := vst.Add(time.Millisecond * 10); realSt.After(add10) {
|
||||
vst = add10
|
||||
} else {
|
||||
vst = realSt
|
||||
chase = false
|
||||
}
|
||||
}
|
||||
vr.MoveNext()
|
||||
}
|
||||
ia, ap = ar.TryRead()
|
||||
iv, vp = vr.TryRead()
|
||||
if ap == nil && vp == nil {
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
} else if ap != nil && (vp == nil || vp.SeqInStream > ap.SeqInStream) {
|
||||
s.onAudio(ap)
|
||||
ar.MoveNext()
|
||||
} else if vp != nil && (ap == nil || ap.SeqInStream > vp.SeqInStream) {
|
||||
s.onVideo(vp)
|
||||
// if chase {
|
||||
// if add10 := vst.Add(time.Millisecond * 10); realSt.After(add10) {
|
||||
// vst = add10
|
||||
// } else {
|
||||
// vst = realSt
|
||||
// chase = false
|
||||
// }
|
||||
// }
|
||||
vr.MoveNext()
|
||||
}
|
||||
ap = ar.TryRead()
|
||||
vp = vr.TryRead()
|
||||
}
|
||||
}
|
||||
func (s *Subscriber) onAudio(ts uint32, ap *AudioPack) {
|
||||
s.OnAudio(ts, ap)
|
||||
func (s *Subscriber) onAudio(af *AVFrame[AudioSlice]) bool {
|
||||
return s.OnAudio((*AudioFrame)(af))
|
||||
}
|
||||
func (s *Subscriber) onVideo(ts uint32, vp *VideoPack) {
|
||||
s.OnVideo(ts, vp)
|
||||
func (s *Subscriber) onVideo(vf *AVFrame[NALUSlice]) bool {
|
||||
return s.OnVideo((*VideoFrame)(vf))
|
||||
}
|
||||
func (s *Subscriber) PlayAudio(at *AudioTrack) {
|
||||
if s.Ctx2 != nil {
|
||||
at.Play(s.onAudio, s.Done(), s.Ctx2.Done())
|
||||
} else {
|
||||
at.Play(s.onAudio, s.Done(), nil)
|
||||
}
|
||||
func (s *Subscriber) PlayAudio(vt track.Audio) {
|
||||
vt.Play(s.onAudio)
|
||||
}
|
||||
func (s *Subscriber) PlayVideo(vt *VideoTrack) {
|
||||
if s.Ctx2 != nil {
|
||||
vt.Play(s.onVideo, s.Done(), s.Ctx2.Done())
|
||||
} else {
|
||||
vt.Play(s.onVideo, s.Done(), nil)
|
||||
}
|
||||
func (s *Subscriber) PlayVideo(vt track.Video) {
|
||||
vt.Play(s.onVideo)
|
||||
}
|
||||
|
Reference in New Issue
Block a user