fix crashing issue due to H264 if running at the same time.

This commit is contained in:
KingKDot
2026-05-21 21:11:10 -05:00
parent 0959c90e46
commit 3c3e20e079
3 changed files with 130 additions and 19 deletions
+39 -19
View File
@@ -418,6 +418,10 @@ var (
prevMu sync.Mutex
prevFrame *prevImage
hvncPrevMu sync.Mutex
hvncPrevFrame *prevImage
hvncLastKeyframe atomic.Int64
)
type prevImage struct {
@@ -713,14 +717,14 @@ func buildFrameHVNC(img *image.RGBA, display int, quality int) (wire.Frame, time
codec = "jpeg"
} else {
if webrtcpub.ConsumeKeyframeRequest() {
resetH264Encoder()
resetH264EncoderHVNC()
}
h264Bytes, err := encodeH264Frame(img)
h264Bytes, err := encodeH264FrameHVNC(img)
if err == nil && len(h264Bytes) > 0 {
prevMu.Lock()
copyPrev(img)
prevMu.Unlock()
lastKeyframe.Store(now.UnixNano())
hvncPrevMu.Lock()
copyPrevHVNC(img)
hvncPrevMu.Unlock()
hvncLastKeyframe.Store(now.UnixNano())
statFullFrames.Add(1)
frame := wire.Frame{Type: "frame", Header: wire.FrameHeader{Monitor: display, FPS: 0, Format: "h264", HVNC: true}, Data: h264Bytes}
return frame, time.Since(encStart), nil
@@ -737,16 +741,16 @@ func buildFrameHVNC(img *image.RGBA, display int, quality int) (wire.Frame, time
}
}
prevMu.Lock()
pf := prevFrame
prevMu.Unlock()
hvncPrevMu.Lock()
pf := hvncPrevFrame
hvncPrevMu.Unlock()
if pf == nil || pf.w != width || pf.h != height || now.Sub(time.Unix(0, lastKeyframe.Load())) > keyframeEvery {
if pf == nil || pf.w != width || pf.h != height || now.Sub(time.Unix(0, hvncLastKeyframe.Load())) > keyframeEvery {
jpegBytes, err := encodeJPEG(img, quality)
prevMu.Lock()
copyPrev(img)
prevMu.Unlock()
lastKeyframe.Store(now.UnixNano())
hvncPrevMu.Lock()
copyPrevHVNC(img)
hvncPrevMu.Unlock()
hvncLastKeyframe.Store(now.UnixNano())
statFullFrames.Add(1)
frame := wire.Frame{Type: "frame", Header: wire.FrameHeader{Monitor: display, FPS: 0, Format: "jpeg", HVNC: true}, Data: jpegBytes}
return frame, time.Since(encStart), err
@@ -772,10 +776,10 @@ func buildFrameHVNC(img *image.RGBA, display int, quality int) (wire.Frame, time
if changedRatio > maxBlockRatio {
jpegBytes, err := encodeJPEG(img, quality)
prevMu.Lock()
copyPrev(img)
prevMu.Unlock()
lastKeyframe.Store(now.UnixNano())
hvncPrevMu.Lock()
copyPrevHVNC(img)
hvncPrevMu.Unlock()
hvncLastKeyframe.Store(now.UnixNano())
statBlockFallbacks.Add(1)
statFullFrames.Add(1)
frame := wire.Frame{Type: "frame", Header: wire.FrameHeader{Monitor: display, FPS: 0, Format: "jpeg", HVNC: true}, Data: jpegBytes}
@@ -1315,6 +1319,22 @@ func copyPrev(img *image.RGBA) {
}
}
func copyPrevHVNC(img *image.RGBA) {
width := img.Bounds().Dx()
height := img.Bounds().Dy()
n := len(img.Pix)
if hvncPrevFrame != nil && cap(hvncPrevFrame.pix) >= n {
hvncPrevFrame.w = width
hvncPrevFrame.h = height
hvncPrevFrame.pix = hvncPrevFrame.pix[:n]
copy(hvncPrevFrame.pix, img.Pix)
} else {
buf := make([]byte, n)
copy(buf, img.Pix)
hvncPrevFrame = &prevImage{w: width, h: height, pix: buf}
}
}
func encodeBlockRaw(img *image.RGBA, x, y, w, h int) []byte {
stride := img.Stride
buf := make([]byte, w*h*4)
@@ -1470,7 +1490,7 @@ func sendBlackFrameHVNC(ctx context.Context, env *rt.Env) error {
img := image.NewRGBA(image.Rect(0, 0, 64, 64))
quality := 60
frame, _, err := buildFrame(img, 0, quality)
frame, _, err := buildFrameHVNC(img, 0, quality)
if err != nil {
return err
}