Files
monibuca/pkg/av-reader.go
2024-06-07 18:16:28 +08:00

147 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package pkg
import (
"context"
"log/slog"
"time"
)
const (
READSTATE_INIT = iota
READSTATE_FIRST
READSTATE_NORMAL
)
const (
SUBMODE_REAL = iota
SUBMODE_NOJUMP
SUBMODE_BUFFER
)
type AVRingReader struct {
RingReader
mode int
Track *AVTrack
State byte
FirstSeq uint32
StartTs time.Duration
FirstTs time.Duration
SkipTs time.Duration //ms
beforeJump time.Duration
LastCodecCtx ICodecCtx
startTime time.Time
AbsTime uint32
Delay uint32
*slog.Logger
}
func (r *AVRingReader) DecConfChanged() bool {
return r.LastCodecCtx != r.Track.ICodecCtx
}
func NewAVRingReader(t *AVTrack) *AVRingReader {
t.Debug("create reader")
t.Ready.Await()
t.Info("reader +1", "count", t.ReaderCount.Add(1))
return &AVRingReader{
Track: t,
}
}
func (r *AVRingReader) readFrame() (err error) {
err = r.ReadNext()
if err != nil {
return err
}
// 超过一半的缓冲区大小说明Reader太慢需要丢帧
if r.mode != SUBMODE_BUFFER && r.State == READSTATE_NORMAL && r.Track.LastValue.Sequence-r.Value.Sequence > uint32(r.Track.Size/2) {
idr := r.Track.IDRing.Load()
if idr != nil && idr.Value.Sequence > r.Value.Sequence {
r.Warn("reader too slow", "lastSeq", r.Track.LastValue.Sequence, "seq", r.Value.Sequence)
return r.Read(idr)
}
}
return
}
func (r *AVRingReader) ReadFrame(mode int) (err error) {
r.mode = mode
switch r.State {
case READSTATE_INIT:
r.Info("start read", "mode", mode)
startRing := r.Track.Ring
idr := r.Track.IDRing.Load()
if idr != nil {
startRing = idr
} else {
r.Warn("no IDRring", "track", r.Track.FourCC().String())
}
switch mode {
case SUBMODE_REAL:
if idr != nil {
r.State = READSTATE_FIRST
} else {
r.State = READSTATE_NORMAL
}
case SUBMODE_NOJUMP:
r.State = READSTATE_NORMAL
case SUBMODE_BUFFER:
if idr := r.Track.HistoryRing.Load(); idr != nil {
startRing = idr
}
r.State = READSTATE_NORMAL
}
if err = r.StartRead(startRing); err != nil {
return
}
r.startTime = time.Now()
if r.FirstTs == 0 {
r.FirstTs = r.Value.Timestamp
}
r.SkipTs = r.FirstTs - r.StartTs
r.FirstSeq = r.Value.Sequence
r.Info("first frame read", "firstTs", r.FirstTs, "firstSeq", r.FirstSeq)
case READSTATE_FIRST:
if idr := r.Track.IDRing.Load(); idr.Value.Sequence != r.FirstSeq {
if err = r.Read(idr); err != nil {
return
}
r.SkipTs = r.Value.Timestamp - r.beforeJump - r.StartTs - 10*time.Millisecond
r.Info("jump", "skipSeq", idr.Value.Sequence-r.FirstSeq, "skipTs", r.SkipTs)
r.State = READSTATE_NORMAL
} else {
if err = r.readFrame(); err != nil {
return
}
r.beforeJump = r.Value.Timestamp - r.FirstTs
// 防止过快消费
if fast := r.beforeJump - time.Since(r.startTime); fast > 0 && fast < time.Second {
time.Sleep(fast)
}
}
case READSTATE_NORMAL:
if err = r.readFrame(); err != nil {
return
}
}
r.AbsTime = uint32((r.Value.Timestamp - r.SkipTs).Milliseconds())
if r.AbsTime == 0 {
r.AbsTime = 1
}
r.Delay = uint32(r.Track.LastValue.Sequence - r.Value.Sequence)
r.Log(context.TODO(), TraceLevel, r.Track.FourCC().String(), "delay", r.Delay)
return
}
// func (r *AVRingReader) GetPTS32() uint32 {
// return uint32((r.Value.Raw.PTS - r.SkipTs*90/time.Millisecond))
// }
// func (r *AVRingReader) GetDTS32() uint32 {
// return uint32((r.Value.DTS - r.SkipTs*90/time.Millisecond))
// }
func (r *AVRingReader) ResetAbsTime() {
r.SkipTs = r.Value.Timestamp
r.AbsTime = 1
}