frame pacing fix
This commit is contained in:
@@ -57,6 +57,19 @@ func (b *VideoBridge) Next(
|
||||
}
|
||||
}
|
||||
|
||||
// TryNext returns a frame only when a producer is already waiting. It never
|
||||
// blocks the caller, allowing UI/render loops to run independently of video
|
||||
// frame cadence. A returned frame has the same completion requirements as
|
||||
// one returned by Next.
|
||||
func (b *VideoBridge) TryNext() (*PendingVideoFrame, bool) {
|
||||
select {
|
||||
case pending := <-b.requests:
|
||||
return pending, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func (f *PendingVideoFrame) Complete(err error) {
|
||||
f.completeOnce.Do(func() {
|
||||
f.result <- err
|
||||
|
||||
@@ -144,3 +144,52 @@ func TestVideoBridgeNextHonorsCancellation(t *testing.T) {
|
||||
t.Fatalf("Next() error = %v, want %v", err, context.Canceled)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideoBridgeTryNextReturnsImmediatelyWhenEmpty(t *testing.T) {
|
||||
bridge := NewVideoBridge()
|
||||
if pending, ok := bridge.TryNext(); ok || pending != nil {
|
||||
t.Fatalf("TryNext() = %#v, %t; want nil, false", pending, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideoBridgeTryNextDeliversWithoutCopyAndRequiresCompletion(t *testing.T) {
|
||||
bridge := NewVideoBridge()
|
||||
frame := VideoFrame{Index: 9, Payload: []byte{1, 2, 3}}
|
||||
consumeResult := make(chan error, 1)
|
||||
started := make(chan struct{})
|
||||
go func() {
|
||||
close(started)
|
||||
consumeResult <- bridge.ConsumeVideo(context.Background(), frame)
|
||||
}()
|
||||
<-started
|
||||
|
||||
deadline := time.Now().Add(videoBridgeTestTimeout)
|
||||
var pending *PendingVideoFrame
|
||||
for pending == nil && time.Now().Before(deadline) {
|
||||
pending, _ = bridge.TryNext()
|
||||
if pending == nil {
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
}
|
||||
if pending == nil {
|
||||
t.Fatal("TryNext() did not receive waiting producer")
|
||||
}
|
||||
if &pending.Frame.Payload[0] != &frame.Payload[0] {
|
||||
t.Fatal("TryNext() copied borrowed payload")
|
||||
}
|
||||
select {
|
||||
case err := <-consumeResult:
|
||||
t.Fatalf("ConsumeVideo() returned before completion: %v", err)
|
||||
default:
|
||||
}
|
||||
|
||||
pending.Complete(nil)
|
||||
select {
|
||||
case err := <-consumeResult:
|
||||
if err != nil {
|
||||
t.Fatalf("ConsumeVideo() error = %v", err)
|
||||
}
|
||||
case <-time.After(videoBridgeTestTimeout):
|
||||
t.Fatal("ConsumeVideo() did not return after completion")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user