65 lines
1.1 KiB
Go
65 lines
1.1 KiB
Go
package playback
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
)
|
|
|
|
type PendingVideoFrame struct {
|
|
Frame VideoFrame
|
|
Generation uint64
|
|
Source FeedConfig
|
|
|
|
completeOnce sync.Once
|
|
result chan error
|
|
}
|
|
|
|
type VideoBridge struct {
|
|
requests chan *PendingVideoFrame
|
|
}
|
|
|
|
func NewVideoBridge() *VideoBridge {
|
|
return &VideoBridge{
|
|
requests: make(chan *PendingVideoFrame),
|
|
}
|
|
}
|
|
|
|
func (b *VideoBridge) ConsumeVideo(
|
|
ctx context.Context,
|
|
frame VideoFrame,
|
|
) error {
|
|
pending := &PendingVideoFrame{
|
|
Frame: frame,
|
|
Generation: generationFromContext(ctx),
|
|
Source: videoSourceFromContext(ctx),
|
|
result: make(chan error, 1),
|
|
}
|
|
|
|
select {
|
|
case b.requests <- pending:
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
}
|
|
|
|
// The render thread now owns temporary access to the borrowed payload.
|
|
// We must wait for Complete even if ctx is canceled.
|
|
return <-pending.result
|
|
}
|
|
|
|
func (b *VideoBridge) Next(
|
|
ctx context.Context,
|
|
) (*PendingVideoFrame, error) {
|
|
select {
|
|
case pending := <-b.requests:
|
|
return pending, nil
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err()
|
|
}
|
|
}
|
|
|
|
func (f *PendingVideoFrame) Complete(err error) {
|
|
f.completeOnce.Do(func() {
|
|
f.result <- err
|
|
})
|
|
}
|