mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-06 00:56:58 +08:00
GOP追帧
This commit is contained in:
104
ring.go
104
ring.go
@@ -12,7 +12,7 @@ import (
|
|||||||
type DataItem struct {
|
type DataItem struct {
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
Sequence int
|
Sequence int
|
||||||
Value interface{}
|
Value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 池化,泛型
|
// TODO: 池化,泛型
|
||||||
@@ -28,123 +28,123 @@ type RingBuffer struct {
|
|||||||
context.Context
|
context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) Init(ctx context.Context, n int) *RingBuffer {
|
func (rb *RingBuffer) Init(ctx context.Context, n int) *RingBuffer {
|
||||||
var flag int32
|
var flag int32
|
||||||
if r == nil {
|
if rb == nil {
|
||||||
r = &RingBuffer{Context: ctx, Ring: ring.New(n), Flag: &flag}
|
rb = &RingBuffer{Context: ctx, Ring: ring.New(n), Flag: &flag}
|
||||||
} else {
|
} else {
|
||||||
r.Ring = ring.New(n)
|
rb.Ring = ring.New(n)
|
||||||
r.Context = ctx
|
rb.Context = ctx
|
||||||
r.Flag = &flag
|
rb.Flag = &flag
|
||||||
}
|
}
|
||||||
for x := r.Ring; x.Value == nil; x = x.Next() {
|
for x := rb.Ring; x.Value == nil; x = x.Next() {
|
||||||
x.Value = new(LockItem)
|
x.Value = new(LockItem)
|
||||||
}
|
}
|
||||||
r.Current().Lock()
|
rb.Current().Lock()
|
||||||
return r
|
return rb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rb RingBuffer) Clone() *RingBuffer {
|
func (rb RingBuffer) Clone() *RingBuffer {
|
||||||
return &rb
|
return &rb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r RingBuffer) SubRing(rr *ring.Ring) *RingBuffer {
|
func (rb RingBuffer) SubRing(rr *ring.Ring) *RingBuffer {
|
||||||
r.Ring = rr
|
rb.Ring = rr
|
||||||
return &r
|
return &rb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) CurrentValue() interface{} {
|
func (rb *RingBuffer) CurrentValue() interface{} {
|
||||||
return r.Current().Value
|
return rb.Current().Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) NextValue() interface{} {
|
func (rb *RingBuffer) NextValue() interface{} {
|
||||||
return r.Next().Value.(*LockItem).Value
|
return rb.Next().Value.(*LockItem).Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) Current() *LockItem {
|
func (rb *RingBuffer) Current() *LockItem {
|
||||||
return r.Ring.Value.(*LockItem)
|
return rb.Ring.Value.(*LockItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) MoveNext() {
|
func (rb *RingBuffer) MoveNext() {
|
||||||
r.Ring = r.Next()
|
rb.Ring = rb.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) GetNext() *LockItem {
|
func (rb *RingBuffer) GetNext() *LockItem {
|
||||||
r.MoveNext()
|
rb.MoveNext()
|
||||||
return r.Current()
|
return rb.Current()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) Read() interface{} {
|
func (rb *RingBuffer) Read() interface{} {
|
||||||
current := r.Current()
|
current := rb.Current()
|
||||||
current.RLock()
|
current.RLock()
|
||||||
defer current.RUnlock()
|
defer current.RUnlock()
|
||||||
return current.Value
|
return current.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) Step() {
|
func (rb *RingBuffer) Step() {
|
||||||
last := r.Current()
|
last := rb.Current()
|
||||||
if atomic.CompareAndSwapInt32(r.Flag, 0, 1) {
|
if atomic.CompareAndSwapInt32(rb.Flag, 0, 1) {
|
||||||
current := r.GetNext()
|
current := rb.GetNext()
|
||||||
current.Lock()
|
current.Lock()
|
||||||
last.Unlock()
|
last.Unlock()
|
||||||
//Flag不为1代表被Dispose了,但尚未处理Done
|
//Flag不为1代表被Dispose了,但尚未处理Done
|
||||||
if !atomic.CompareAndSwapInt32(r.Flag, 1, 0) {
|
if !atomic.CompareAndSwapInt32(rb.Flag, 1, 0) {
|
||||||
current.Unlock()
|
current.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) Write(value interface{}) {
|
func (rb *RingBuffer) Write(value interface{}) {
|
||||||
last := r.Current()
|
last := rb.Current()
|
||||||
last.Value = value
|
last.Value = value
|
||||||
if atomic.CompareAndSwapInt32(r.Flag, 0, 1) {
|
if atomic.CompareAndSwapInt32(rb.Flag, 0, 1) {
|
||||||
current := r.GetNext()
|
current := rb.GetNext()
|
||||||
current.Lock()
|
current.Lock()
|
||||||
last.Unlock()
|
last.Unlock()
|
||||||
//Flag不为1代表被Dispose了,但尚未处理Done
|
//Flag不为1代表被Dispose了,但尚未处理Done
|
||||||
if !atomic.CompareAndSwapInt32(r.Flag, 1, 0) {
|
if !atomic.CompareAndSwapInt32(rb.Flag, 1, 0) {
|
||||||
current.Unlock()
|
current.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) Dispose() {
|
func (rb *RingBuffer) Dispose() {
|
||||||
current := r.Current()
|
current := rb.Current()
|
||||||
if atomic.CompareAndSwapInt32(r.Flag, 0, 2) {
|
if atomic.CompareAndSwapInt32(rb.Flag, 0, 2) {
|
||||||
current.Unlock()
|
current.Unlock()
|
||||||
} else if atomic.CompareAndSwapInt32(r.Flag, 1, 2) {
|
} else if atomic.CompareAndSwapInt32(rb.Flag, 1, 2) {
|
||||||
//当前是1代表正在写入,此时变成2,但是Done的任务得交给NextW来处理
|
//当前是1代表正在写入,此时变成2,但是Done的任务得交给NextW来处理
|
||||||
} else if atomic.CompareAndSwapInt32(r.Flag, 0, 2) {
|
} else if atomic.CompareAndSwapInt32(rb.Flag, 0, 2) {
|
||||||
current.Unlock()
|
current.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) read() reflect.Value {
|
func (rb *RingBuffer) read() reflect.Value {
|
||||||
return reflect.ValueOf(r.Read())
|
return reflect.ValueOf(rb.Read())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RingBuffer) nextRead() reflect.Value {
|
func (rb *RingBuffer) nextRead() reflect.Value {
|
||||||
r.MoveNext()
|
rb.MoveNext()
|
||||||
return r.read()
|
return rb.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadLoop 循环读取,采用了反射机制,不适用高性能场景
|
// ReadLoop 循环读取,采用了反射机制,不适用高性能场景
|
||||||
// handler入参可以传入回调函数或者channel
|
// handler入参可以传入回调函数或者channel
|
||||||
func (r *RingBuffer) ReadLoop(handler interface{}) {
|
func (rb *RingBuffer) ReadLoop(handler interface{}) {
|
||||||
r.ReadLoopConditional(handler, func() bool {
|
rb.ReadLoopConditional(handler, func() bool {
|
||||||
return r.Err() == nil && *r.Flag != 2
|
return rb.Err() == nil && *rb.Flag != 2
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// goon判断函数用来判断是否继续读取,返回false将终止循环
|
// goon判断函数用来判断是否继续读取,返回false将终止循环
|
||||||
func (r *RingBuffer) ReadLoopConditional(handler interface{}, goon func() bool) {
|
func (rb *RingBuffer) ReadLoopConditional(handler interface{}, goon func() bool) {
|
||||||
switch t := reflect.ValueOf(handler); t.Kind() {
|
switch t := reflect.ValueOf(handler); t.Kind() {
|
||||||
case reflect.Chan:
|
case reflect.Chan:
|
||||||
for v := r.read(); goon(); v = r.nextRead() {
|
for v := rb.read(); goon(); v = rb.nextRead() {
|
||||||
t.Send(v)
|
t.Send(v)
|
||||||
}
|
}
|
||||||
case reflect.Func:
|
case reflect.Func:
|
||||||
for args := []reflect.Value{r.read()}; goon(); args[0] = r.nextRead() {
|
for args := []reflect.Value{rb.read()}; goon(); args[0] = rb.nextRead() {
|
||||||
t.Call(args)
|
t.Call(args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
ring_av.go
40
ring_av.go
@@ -3,7 +3,6 @@ package engine
|
|||||||
import (
|
import (
|
||||||
"container/ring"
|
"container/ring"
|
||||||
"context"
|
"context"
|
||||||
"reflect"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -11,8 +10,8 @@ import (
|
|||||||
type AVItem struct {
|
type AVItem struct {
|
||||||
Timestamp uint32
|
Timestamp uint32
|
||||||
Sequence int
|
Sequence int
|
||||||
Value interface{}
|
Value interface{}
|
||||||
canRead bool
|
canRead bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AVItem) Since(ts uint32) uint32 {
|
func (p *AVItem) Since(ts uint32) uint32 {
|
||||||
@@ -36,8 +35,8 @@ func (r *AVRing) Init(ctx context.Context, n int) *AVRing {
|
|||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
func (rb AVRing) Clone() *AVRing {
|
func (r AVRing) Clone() *AVRing {
|
||||||
return &rb
|
return &r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r AVRing) SubRing(rr *ring.Ring) *AVRing {
|
func (r AVRing) SubRing(rr *ring.Ring) *AVRing {
|
||||||
@@ -65,19 +64,6 @@ func (r *AVRing) wait() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AVRing) read() reflect.Value {
|
|
||||||
current := r.Current()
|
|
||||||
for r.Err() == nil && !current.canRead {
|
|
||||||
r.wait()
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(current.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *AVRing) nextRead() reflect.Value {
|
|
||||||
r.MoveNext()
|
|
||||||
return r.read()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *AVRing) CurrentValue() interface{} {
|
func (r *AVRing) CurrentValue() interface{} {
|
||||||
return r.Current().Value
|
return r.Current().Value
|
||||||
}
|
}
|
||||||
@@ -93,6 +79,9 @@ func (r *AVRing) NextRead() (item *AVItem, value interface{}) {
|
|||||||
func (r *AVRing) NextValue() interface{} {
|
func (r *AVRing) NextValue() interface{} {
|
||||||
return r.Next().Value.(*AVItem).Value
|
return r.Next().Value.(*AVItem).Value
|
||||||
}
|
}
|
||||||
|
func (r *AVRing) PreItem() *AVItem {
|
||||||
|
return r.Prev().Value.(*AVItem)
|
||||||
|
}
|
||||||
func (r *AVRing) GetNext() *AVItem {
|
func (r *AVRing) GetNext() *AVItem {
|
||||||
r.MoveNext()
|
r.MoveNext()
|
||||||
return r.Current()
|
return r.Current()
|
||||||
@@ -104,18 +93,3 @@ func (r *AVRing) Read() (item *AVItem, value interface{}) {
|
|||||||
}
|
}
|
||||||
return current, current.Value
|
return current, current.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadLoop 循环读取,采用了反射机制,不适用高性能场景
|
|
||||||
// handler入参可以传入回调函数或者channel
|
|
||||||
func (r *AVRing) ReadLoop(handler interface{}) {
|
|
||||||
switch t := reflect.ValueOf(handler); t.Kind() {
|
|
||||||
case reflect.Chan:
|
|
||||||
for v := r.read(); r.Err() == nil; v = r.nextRead() {
|
|
||||||
t.Send(v)
|
|
||||||
}
|
|
||||||
case reflect.Func:
|
|
||||||
for args := []reflect.Value{r.read()}; r.Err() == nil; args[0] = r.nextRead() {
|
|
||||||
t.Call(args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -82,11 +82,13 @@ func (s *Subscriber) Play(at *AudioTrack, vt *VideoTrack) {
|
|||||||
case <-extraExit: //可能等不到关键帧就退出了
|
case <-extraExit: //可能等不到关键帧就退出了
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vr := vt.SubRing(vt.IDRing) //从关键帧开始读取,首屏秒开
|
vr := vt.SubRing(vt.IDRing) //从关键帧开始读取,首屏秒开
|
||||||
|
realSt := vt.PreItem().Timestamp // 当前时间戳
|
||||||
ar := at.Clone()
|
ar := at.Clone()
|
||||||
iv, vp := vr.Read()
|
iv, vp := vr.Read()
|
||||||
ia, ap := ar.Read()
|
ia, ap := ar.Read()
|
||||||
vst, ast := iv.Timestamp, ia.Timestamp
|
vst := iv.Timestamp
|
||||||
|
chase := true
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-extraExit:
|
case <-extraExit:
|
||||||
@@ -96,10 +98,18 @@ func (s *Subscriber) Play(at *AudioTrack, vt *VideoTrack) {
|
|||||||
default:
|
default:
|
||||||
if ia.Timestamp > iv.Timestamp || ia.Timestamp == 0 {
|
if ia.Timestamp > iv.Timestamp || ia.Timestamp == 0 {
|
||||||
s.OnVideo(iv.Timestamp-vst, vp.(*VideoPack))
|
s.OnVideo(iv.Timestamp-vst, vp.(*VideoPack))
|
||||||
|
if chase {
|
||||||
|
if vst < realSt-10 {
|
||||||
|
vst += 10
|
||||||
|
} else {
|
||||||
|
vst = realSt
|
||||||
|
chase = false
|
||||||
|
}
|
||||||
|
}
|
||||||
vr.MoveNext()
|
vr.MoveNext()
|
||||||
iv, vp = vr.Read()
|
iv, vp = vr.Read()
|
||||||
} else {
|
} else {
|
||||||
s.OnAudio(ia.Timestamp-ast, ap.(*AudioPack))
|
s.OnAudio(ia.Timestamp-vst, ap.(*AudioPack))
|
||||||
ar.MoveNext()
|
ar.MoveNext()
|
||||||
ia, ap = ar.Read()
|
ia, ap = ar.Read()
|
||||||
}
|
}
|
||||||
|
@@ -384,9 +384,11 @@ func (vt *VideoTrack) Play(onVideo func(uint32, *VideoPack), exit1, exit2 <-chan
|
|||||||
case <-exit2: //可能等不到关键帧就退出了
|
case <-exit2: //可能等不到关键帧就退出了
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vr := vt.SubRing(vt.IDRing) //从关键帧开始读取,首屏秒开
|
vr := vt.SubRing(vt.IDRing) //从关键帧开始读取,首屏秒开
|
||||||
|
realSt := vt.PreItem().Timestamp // 当前时间戳
|
||||||
item, vp := vr.Read()
|
item, vp := vr.Read()
|
||||||
for startTimestamp := item.Timestamp; ; item, vp = vr.Read() {
|
startTimestamp := item.Timestamp
|
||||||
|
for chase := true; ; item, vp = vr.Read() {
|
||||||
select {
|
select {
|
||||||
case <-exit1:
|
case <-exit1:
|
||||||
return
|
return
|
||||||
@@ -394,6 +396,14 @@ func (vt *VideoTrack) Play(onVideo func(uint32, *VideoPack), exit1, exit2 <-chan
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
onVideo(item.Timestamp-startTimestamp, vp.(*VideoPack))
|
onVideo(item.Timestamp-startTimestamp, vp.(*VideoPack))
|
||||||
|
if chase {
|
||||||
|
if startTimestamp < realSt-10 {
|
||||||
|
startTimestamp += 10
|
||||||
|
} else {
|
||||||
|
startTimestamp = realSt
|
||||||
|
chase = false
|
||||||
|
}
|
||||||
|
}
|
||||||
vr.MoveNext()
|
vr.MoveNext()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user