Stabilize unified player preview buffers
This commit is contained in:
parent
98bc6f903b
commit
79785b26b3
|
|
@ -66,6 +66,7 @@ type UnifiedPlayer struct {
|
||||||
|
|
||||||
// Buffer management
|
// Buffer management
|
||||||
frameBuffer *sync.Pool
|
frameBuffer *sync.Pool
|
||||||
|
videoBuffer []byte
|
||||||
audioBuffer []byte
|
audioBuffer []byte
|
||||||
audioBufferSize int
|
audioBufferSize int
|
||||||
|
|
||||||
|
|
@ -97,6 +98,7 @@ func NewUnifiedPlayer(config Config) *UnifiedPlayer {
|
||||||
},
|
},
|
||||||
audioBufferSize: 32768, // 170ms at 48kHz for smooth playback
|
audioBufferSize: 32768, // 170ms at 48kHz for smooth playback
|
||||||
}
|
}
|
||||||
|
player.previewMode = config.PreviewMode
|
||||||
if config.WindowWidth > 0 {
|
if config.WindowWidth > 0 {
|
||||||
player.windowW = config.WindowWidth
|
player.windowW = config.WindowWidth
|
||||||
}
|
}
|
||||||
|
|
@ -691,7 +693,9 @@ func (p *UnifiedPlayer) readVideoFrame() (*image.RGBA, error) {
|
||||||
|
|
||||||
// Read RGB24 frame data from FFmpeg pipe
|
// Read RGB24 frame data from FFmpeg pipe
|
||||||
frameSize := p.windowW * p.windowH * 3 // RGB24 = 3 bytes per pixel
|
frameSize := p.windowW * p.windowH * 3 // RGB24 = 3 bytes per pixel
|
||||||
frameData := make([]byte, frameSize)
|
if len(p.videoBuffer) != frameSize {
|
||||||
|
p.videoBuffer = make([]byte, frameSize)
|
||||||
|
}
|
||||||
|
|
||||||
// Check for paused state before reading
|
// Check for paused state before reading
|
||||||
if p.paused {
|
if p.paused {
|
||||||
|
|
@ -699,7 +703,7 @@ func (p *UnifiedPlayer) readVideoFrame() (*image.RGBA, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read full frame - io.ReadFull ensures we get complete frame
|
// Read full frame - io.ReadFull ensures we get complete frame
|
||||||
n, err := io.ReadFull(p.videoPipeReader, frameData)
|
n, err := io.ReadFull(p.videoPipeReader, p.videoBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
return nil, nil // End of stream
|
return nil, nil // End of stream
|
||||||
|
|
@ -711,21 +715,14 @@ func (p *UnifiedPlayer) readVideoFrame() (*image.RGBA, error) {
|
||||||
return nil, fmt.Errorf("incomplete frame: got %d bytes, expected %d", n, frameSize)
|
return nil, fmt.Errorf("incomplete frame: got %d bytes, expected %d", n, frameSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create RGBA image (Fyne requires RGBA, not RGB)
|
// Create RGBA image (Fyne requires RGBA, not RGB), reuse buffer.
|
||||||
img := image.NewRGBA(image.Rect(0, 0, p.windowW, p.windowH))
|
img := p.frameBuffer.Get().(*image.RGBA)
|
||||||
|
if img.Rect.Dx() != p.windowW || img.Rect.Dy() != p.windowH {
|
||||||
// Convert RGB24 to RGBA (add alpha channel)
|
img.Rect = image.Rect(0, 0, p.windowW, p.windowH)
|
||||||
for y := 0; y < p.windowH; y++ {
|
img.Stride = p.windowW * 4
|
||||||
for x := 0; x < p.windowW; x++ {
|
img.Pix = make([]uint8, p.windowW*p.windowH*4)
|
||||||
srcIdx := (y*p.windowW + x) * 3
|
|
||||||
dstIdx := (y*p.windowW + x) * 4
|
|
||||||
|
|
||||||
img.Pix[dstIdx+0] = frameData[srcIdx+0] // R
|
|
||||||
img.Pix[dstIdx+1] = frameData[srcIdx+1] // G
|
|
||||||
img.Pix[dstIdx+2] = frameData[srcIdx+2] // B
|
|
||||||
img.Pix[dstIdx+3] = 255 // A (fully opaque)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
utils.CopyRGBToRGBA(img.Pix, p.videoBuffer)
|
||||||
|
|
||||||
// Update frame counter
|
// Update frame counter
|
||||||
p.currentFrame++
|
p.currentFrame++
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user