大改版

This commit is contained in:
langhuihui
2021-02-14 22:56:17 +08:00
parent 70706fc8da
commit c2ff0bbcae
14 changed files with 250 additions and 222 deletions

View File

@@ -2,14 +2,16 @@ package engine
import (
"context"
"encoding/json"
"time"
"github.com/Monibuca/utils/v3/codec"
"github.com/pkg/errors"
)
// SubscriberInfo 订阅者可序列化信息,用于控制台输出
type SubscriberInfo struct {
// Subscriber 订阅者实体定义
type Subscriber struct {
context.Context
*Stream `json:"-"`
ID string
TotalDrop int //总丢帧
TotalPacket int
@@ -17,19 +19,12 @@ type SubscriberInfo struct {
BufferLength int
Delay uint32
SubscribeTime time.Time
}
// Subscriber 订阅者实体定义
type Subscriber struct {
context.Context
*Stream `json:"-"`
SubscriberInfo
cancel context.CancelFunc
Sign string
OffsetTime uint32
startTime uint32
vtIndex int //第几个视频轨
atIndex int //第几个音频轨
cancel context.CancelFunc
Sign string
OffsetTime uint32
startTime uint32
OnAudio func(pack AudioPack) `json:"-"`
OnVideo func(pack VideoPack) `json:"-"`
}
// IsClosed 检查订阅者是否已经关闭
@@ -44,14 +39,41 @@ func (s *Subscriber) Close() {
s.cancel()
}
}
func (s *Subscriber) MarshalJSON() ([]byte, error) {
return json.Marshal(s.SubscriberInfo)
func (r *Subscriber) GetVideoTrack(codec string) *VideoTrack {
if !config.EnableVideo {
return nil
}
r.videoRW.RLock()
defer r.videoRW.RUnlock()
return r.VideoTracks[codec]
}
func (s *Subscriber) GetAudioTrack(codecs ...string) (at *AudioTrack) {
if !config.EnableAudio {
return nil
}
if HasTranscoder {
s.audioRW.Lock()
defer s.audioRW.Unlock()
} else {
s.audioRW.RLock()
defer s.audioRW.RUnlock()
}
for _, codec := range codecs {
if at, ok := s.AudioTracks[codec]; ok {
return at
}
}
if HasTranscoder {
at = s.AddAudioTrack(codecs[0], nil)
at.SoundFormat = codec.Codec2SoundFormat[codecs[0]]
TriggerHook(Hook{HOOK_REQUEST_TRANSAUDIO, &TransCodeReq{s, codecs[0]}})
}
return
}
//Subscribe 开始订阅
//Subscribe 开始订阅 将Subscriber与Stream关联
func (s *Subscriber) Subscribe(streamPath string) error {
if !config.EnableWaitStream && FindStream(streamPath) == nil {
if FindStream(streamPath) == nil {
return errors.Errorf("Stream not found:%s", streamPath)
}
GetStream(streamPath).Subscribe(s)
@@ -60,3 +82,115 @@ func (s *Subscriber) Subscribe(streamPath string) error {
}
return nil
}
//Play 开始播放
func (s *Subscriber) Play(ctx context.Context, at *AudioTrack, vt *VideoTrack) {
defer s.Close()
if vt == nil && at == nil {
return
}
if vt == nil {
s.PlayAudio(ctx, at)
return
} else if at == nil {
s.PlayVideo(ctx, vt)
return
}
select {
case <-vt.WaitFirst: //等待获取到第一个关键帧
case <-s.Context.Done():
return
case <-ctx.Done(): //可能等不到关键帧就退出了
return
}
vr := vt.Buffer.SubRing(vt.FirstScreen) //从关键帧开始读取,首屏秒开
vr.Current.Wait() //等到RingBuffer可读
ar := at.Buffer.SubRing(at.Buffer.Index)
ar.Current.Wait()
dropping := false //是否处于丢帧中
send_audio := func() {
s.OnAudio(ar.Current.AudioPack)
if at.Buffer.Index-ar.Index > 128 {
dropping = true
}
}
send_video := func() {
s.OnVideo(vr.Current.VideoPack)
if vt.Buffer.Index-vr.Index > 128 {
dropping = true
}
}
for ctx.Err() == nil && s.Context.Err() == nil {
if ar.Current.Timestamp > vr.Current.Timestamp || ar.Current.Timestamp == 0 {
if !dropping {
send_video()
} else if vr.Current.NalType == codec.NALU_IDR_Picture {
dropping = false
}
vr.NextR()
} else {
if !dropping {
send_audio()
}
ar.NextR()
}
}
}
func (s *Subscriber) PlayAudio(ctx context.Context, at *AudioTrack) {
ring := at.Buffer.SubRing(at.Buffer.Index)
ring.Current.Wait()
droped := 0
var action, send func()
drop := func() {
if at.Buffer.Index-ring.Index < 10 {
action = send
} else {
droped++
}
}
send = func() {
s.OnAudio(ring.Current.AudioPack)
//s.BufferLength = pIndex - ring.Index
//s.Delay = s.AVRing.Timestamp - packet.Timestamp
if at.Buffer.Index-ring.Index > 128 {
action = drop
}
}
for action = send; ctx.Err() == nil && s.Context.Err() == nil; ring.NextR() {
action()
}
}
func (s *Subscriber) PlayVideo(ctx context.Context, vt *VideoTrack) {
select {
case <-vt.WaitFirst:
case <-s.Context.Done():
return
case <-ctx.Done(): //可能等不到关键帧就退出了
return
}
ring := vt.Buffer.SubRing(vt.FirstScreen)
ring.Current.Wait()
droped := 0
var action, send func()
drop := func() {
if ring.Current.NalType == codec.NALU_IDR_Picture {
action = send
} else {
droped++
}
}
send = func() {
s.OnVideo(ring.Current.VideoPack)
pIndex := vt.Buffer.Index
//s.BufferLength = pIndex - ring.Index
//s.Delay = s.AVRing.Timestamp - packet.Timestamp
if pIndex-ring.Index > 128 {
action = drop
}
}
for action = send; ctx.Err() == nil && s.Context.Err() == nil; ring.NextR() {
action()
}
}