stage borrowed video frames on render thread
This commit is contained in:
+55
-20
@@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"mxl-player/internal/imgui"
|
"mxl-player/internal/imgui"
|
||||||
|
"mxl-player/internal/playback"
|
||||||
"mxl-player/internal/renderer"
|
"mxl-player/internal/renderer"
|
||||||
"mxl-player/internal/sdl"
|
"mxl-player/internal/sdl"
|
||||||
"mxl-player/internal/source"
|
"mxl-player/internal/source"
|
||||||
@@ -359,7 +360,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
// One control channel: grant (empty params) or reconnect (with params).
|
// One control channel: grant (empty params) or reconnect (with params).
|
||||||
control := make(chan reconnectParams, 1)
|
control := make(chan reconnectParams, 1)
|
||||||
staged := make(chan uint64)
|
videoBridge := playback.NewVideoBridge()
|
||||||
|
|
||||||
reopen := func(params reconnectParams) error {
|
reopen := func(params reconnectParams) error {
|
||||||
// Close current sources
|
// Close current sources
|
||||||
@@ -529,9 +530,7 @@ func main() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var payload []byte
|
var videoFrame playback.VideoFrame
|
||||||
var grainIdx uint64
|
|
||||||
|
|
||||||
if syncSrc != nil {
|
if syncSrc != nil {
|
||||||
vFrame, aFrame, err := syncSrc.NextSync(ctx, audioBatch, 200*time.Millisecond)
|
vFrame, aFrame, err := syncSrc.NextSync(ctx, audioBatch, 200*time.Millisecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -551,8 +550,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
payload = vFrame.Payload
|
videoFrame = playback.VideoFrame{
|
||||||
grainIdx = vFrame.Index
|
Index: vFrame.Index,
|
||||||
|
Width: vFrame.Width,
|
||||||
|
Height: vFrame.Height,
|
||||||
|
Stride: vFrame.Stride,
|
||||||
|
Size: vFrame.Size,
|
||||||
|
Invalid: vFrame.Invalid,
|
||||||
|
Payload: vFrame.Payload,
|
||||||
|
}
|
||||||
if aFrame.Samples != nil && audioStream != 0 {
|
if aFrame.Samples != nil && audioStream != 0 {
|
||||||
sdl.PutAudioStreamData(audioStream, interleaveAudio(aFrame.Samples))
|
sdl.PutAudioStreamData(audioStream, interleaveAudio(aFrame.Samples))
|
||||||
}
|
}
|
||||||
@@ -575,16 +581,22 @@ func main() {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
payload = f.Payload
|
videoFrame = playback.VideoFrame{
|
||||||
grainIdx = f.Index
|
Index: f.Index,
|
||||||
|
Width: f.Width,
|
||||||
|
Height: f.Height,
|
||||||
|
Stride: f.Stride,
|
||||||
|
Size: f.Size,
|
||||||
|
Invalid: f.Invalid,
|
||||||
|
Payload: f.Payload,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r != nil {
|
if err := videoBridge.ConsumeVideo(ctx, videoFrame); err != nil {
|
||||||
vk.CopyToMapped(r.StagingMapped(), payload)
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
select {
|
log.Printf("video output: %v", err)
|
||||||
case staged <- grainIdx:
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -661,15 +673,38 @@ func main() {
|
|||||||
}
|
}
|
||||||
var shownIndex uint64
|
var shownIndex uint64
|
||||||
hasFrame := false
|
hasFrame := false
|
||||||
select {
|
|
||||||
case shownIndex = <-staged:
|
frameCtx, frameCancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||||
|
pendingFrame, frameErr := videoBridge.Next(frameCtx)
|
||||||
|
frameCancel()
|
||||||
|
|
||||||
|
if pendingFrame != nil {
|
||||||
|
var stageErr error
|
||||||
|
if r != nil {
|
||||||
|
stageErr = r.StageFrame(
|
||||||
|
pendingFrame.Frame.Payload,
|
||||||
|
pendingFrame.Frame.Width,
|
||||||
|
pendingFrame.Frame.Height,
|
||||||
|
pendingFrame.Frame.Stride,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the borrowed payload before reacting to a staging error
|
||||||
|
pendingFrame.Complete(stageErr)
|
||||||
|
|
||||||
|
if stageErr != nil {
|
||||||
|
panic(stageErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
shownIndex = pendingFrame.Frame.Index
|
||||||
granted = false
|
granted = false
|
||||||
hasFrame = true
|
hasFrame = true
|
||||||
case <-ctx.Done():
|
} else if frameErr != nil &&
|
||||||
running = false
|
!errors.Is(frameErr, context.DeadlineExceeded) &&
|
||||||
continue
|
!errors.Is(frameErr, context.Canceled) {
|
||||||
case <-time.After(100 * time.Millisecond):
|
panic(frameErr)
|
||||||
// No frame staged. Reset granted so we re-grant on next iteration.
|
} else {
|
||||||
|
// No frame arrived before the deadline.
|
||||||
granted = false
|
granted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user