Files
engine/subscriber.go
2022-02-17 21:49:55 +08:00

131 lines
2.4 KiB
Go

package engine
import (
"context"
"time"
. "github.com/Monibuca/engine/v4/common"
"github.com/Monibuca/engine/v4/config"
"github.com/Monibuca/engine/v4/track"
)
type AudioFrame AVFrame[AudioSlice]
type VideoFrame AVFrame[NALUSlice]
type ISubscriber interface {
IIO
receive(string, any, *config.Subscribe) bool
config.SubscribeConfig
GetSubscriber() *Subscriber
Unsubscribe()
}
type TrackPlayer struct {
context.Context
context.CancelFunc
AudioTrack *track.Audio
VideoTrack *track.Video
vr *AVRing[NALUSlice]
ar *AVRing[AudioSlice]
}
// Subscriber 订阅者实体定义
type Subscriber struct {
IO[config.Subscribe]
TrackPlayer
}
func (p *Subscriber) GetSubscriber() *Subscriber {
return p
}
func (p *Subscriber) Unsubscribe() {
p.bye(p)
}
func (s *Subscriber) GetSubscribeConfig() *config.Subscribe {
return s.Config
}
func (s *Subscriber) OnEvent(event any) any {
s.IO.OnEvent(event)
switch v := event.(type) {
case TrackRemoved:
if a, ok := v.(*track.Audio); ok && a == s.AudioTrack {
s.ar = nil
} else if v, ok := v.(*track.Video); ok && v == s.VideoTrack {
s.vr = nil
}
}
return event
}
func (s *Subscriber) AddTrack(t Track) bool {
if v, ok := t.(*track.Video); ok {
if s.Config.SubVideo {
if s.VideoTrack != nil {
return false
}
s.VideoTrack = v
s.vr = v.ReadRing()
return true
}
} else if a, ok := t.(*track.Audio); ok {
if s.Config.SubAudio {
if s.AudioTrack != nil {
return false
}
s.AudioTrack = a
s.ar = a.ReadRing()
return true
}
}
return false
// TODO: data track
}
func (s *Subscriber) IsPlaying() bool {
return s.TrackPlayer.Err() == nil && (s.AudioTrack != nil || s.VideoTrack != nil)
}
//Play 开始播放
func (s *Subscriber) Play() {
var t time.Time
for s.TrackPlayer.Err() == nil {
if s.vr != nil {
for {
vp := s.vr.Read(s.TrackPlayer)
s.OnEvent((*VideoFrame)(vp))
s.vr.MoveNext()
if vp.Timestamp.After(t) {
t = vp.Timestamp
break
}
}
}
if s.ar != nil {
for {
ap := s.ar.Read(s.TrackPlayer)
s.OnEvent((*AudioFrame)(ap))
s.ar.MoveNext()
if ap.Timestamp.After(t) {
t = ap.Timestamp
break
}
}
}
}
return
}
type PushEvent int
type Pusher struct {
Config *config.Push
StreamPath string
RemoteURL string
PushCount int
}
// 是否需要重连
func (pub *Pusher) Reconnect() bool {
return pub.Config.RePush == -1 || pub.PushCount <= pub.Config.RePush
}