Skip to content

Tags: nakagami/grdp

Tags

v0.8.7

Toggle v0.8.7's commit message
rdpgfx: fix AVC444 colour shift by forcing limited-range BT.709 in NV…

…12 Y-cache

VideoToolbox on macOS outputs kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
(color_range=2), so nv12.FullRange was propagated to avc444YPlane.fullRange=true.
This caused combineAVC444v2BGRA to apply the BT.709 full-range coefficients
(256·y + 403·v, etc.) on LC=2 chroma-upgrade frames.

SDL2's Metal renderer, however, auto-selects limited-range BT.709 for HD
resolutions (>1000×600) via SDL_GetYUVConversionModeForResolution.  The result
was a visible colour shift whenever the display alternated between LC=0/1 NV12
frames (SDL2 limited BT.709) and LC=2 BGRA overlay frames (full-range BT.709):
e.g. a blue pixel at Y=98, Cb=210 rendered as (95,77,255) via SDL2 but (98,82,250)
via LC=2.

Fix: always set avc444YPlane.fullRange=false in updateAVC444YCacheFromNV12.
Both SDL2 and combineAVC444v2BGRA now apply limited-range BT.709 coefficients to
the same VideoToolbox-supplied Y and UV values, making the B2/B3 pixels (shared
stream-1 chroma) identical between the two rendering paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v0.8.6

Toggle v0.8.6's commit message
rdpgfx: skip no-IDR soft reset when in SW fallback mode

After a VideoToolbox stall, ForceRefresh is already sent multiple times
during the stall period before the SW fallback is created.  Allowing a
no-IDR soft reset in SW fallback mode just adds another
keyframeWaitTimeoutSWFallback seconds of freeze for no benefit — the
Windows server consistently does not deliver an IDR in response to
ForceRefresh in post-stall scenarios.

Skip straight to reconnect when usingSWFallback is true.  For pure SW
sessions (no prior HW stall) the existing one-retry budget is kept.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v0.8.5

Toggle v0.8.5's commit message
Fix isAuxChromaBlank: require majority of samples to be non-zero

Previously, a single sampled position with Cb ≥ 8 was enough to declare
the LC=2 aux frame 'has real chroma data'. Windows Server's stream2 IDR
frame can contain isolated codec-initialisation artefacts (e.g. Cb=9 at
a few scattered pixels) while the rest of the frame is still zero.
That one stray pixel fooled the check into combining a mostly-zero chroma
frame with real luma, producing bright-green blocks at connection startup.

Switch from 'any non-zero sample → not blank' to 'majority of sampled
positions must exceed threshold → not blank'. The 6×2 = 12 sampled
values now all need at least 7 to be ≥ 8 before the frame is accepted.
A real desktop always has consistent non-zero Cb/Cr; the artefact case
passes only 1–2 samples, so it is correctly treated as still blank.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v0.8.4

Toggle v0.8.4's commit message
Don't reconnect on decoder broken

v0.8.3

Toggle v0.8.3's commit message
rdpgfx: degrade LC=2 gracefully when stream2 IDR never arrives

When the server sends stream2 P-frames in LC=0 packets but never sends
a stream2 IDR (even after repeated ForceRefresh keyframe requests),
the previous code would reconnect after auxDecoderMaxIDRRetries attempts.
Since the server behaviour is consistent, reconnecting reproduces the
same failure loop.

Add lc2PermanentlyDegraded flag. After exhausting retries with
lc2EverDecoded=false, set the flag and degrade silently to LC=0-only
instead of reconnecting. decodeAVC444LC2 skips LC=2 frames without
arming the renegotiation timer, stopping the endless cycle.

If the server later delivers a stream2 IDR, primeAuxDecoder clears the
flag and recovers the aux decoder. RESET_GRAPHICS also clears the flag
for a clean slate on the next AVC444 sequence.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v0.8.2

Toggle v0.8.2's commit message
optimize

v0.8.1

Toggle v0.8.1's commit message
remove example/example

v0.8.0

Toggle v0.8.0's commit message
h264: add V4L2 M2M hardware decoder probe (Raspberry Pi / Linux SoC)

The av_hwdevice_iterate_types loop does not expose h264_v4l2m2m since
it is a standalone FFmpeg codec rather than an hwdevice-backed decoder.
Probe it explicitly after the hwdevice loop so that Linux SoCs (e.g.
Raspberry Pi 4/5, Rockchip, Allwinner) can use their kernel V4L2 M2M
H.264 hardware decoder when FFmpeg is compiled with V4L2 M2M support.

h264_v4l2m2m outputs NV12 frames directly in CPU-accessible memory, so
no av_hwframe_transfer_data step is needed.  The existing NV12 handling
path in convertFrame() processes these frames correctly.

Changes:
- Add grdp_find_v4l2m2m() C helper wrapping avcodec_find_decoder_by_name
- Add #cgo nocallback grdp_find_v4l2m2m directive
- In newH264DecoderInternal: after hwdevice loop, try h264_v4l2m2m;
  on success replace the codec context, set useHW=true,
  hwNeedsZeroCheck=false, and skip the duplicate avcodec_open2 call
  via the new alreadyOpened flag
- On macOS or FFmpeg builds without V4L2, grdp_find_v4l2m2m returns
  nil and the probe is a no-op

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v0.7.30

Toggle v0.7.30's commit message
Fix green screen and improve VT stall detection

- plugin/rdpgfx/avc.go: Add isAuxChromaBlank() to detect uninitialised
  AVC444v2 stream2 chroma (Cb=0/Cr=0).  Windows Server sends near-zero
  chroma in the stream2 IDR and only updates changed regions; combining
  zero chroma with any luma produces BGRA(0,135,0,255) — a bright green
  frame.  Drop the frame until real chroma data arrives.

- plugin/rdpgfx/h264_ffmpeg.go: Add mid-session null-frame stall
  detection (avcHWMidSessionNullFrameLimit=150).  Previously only the
  early session window (hwSentCount<50) used null-frame counting; mid-
  session stalls waited for the 7-second CGo-safe timeout.  150 null
  frames ≈ 5 s at 30 fps — safely above normal GOP-boundary noise (≤25)
  but 2 s before the safety valve, reducing observed freeze duration
  from ~17 s to ~11 s.

- example/gxui.go: Remove debug-level slog handler from main().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

v0.7.29

Toggle v0.7.29's commit message
rdpgfx: prime aux decoder before zero-fill drop check

When the main HW decoder (VideoToolbox) returns a zero-filled IOSurface,
decodeAVC444 and decodeAVC444WithI420 return early before reaching the
primeAuxDecoder call at the end of each function.  This silently discards
any stream2 IDR embedded in the dropped LC=0 frame, which can prevent the
aux decoder (h264dec2) from being created at the right time and causes a
full-screen green tint on the next LC=2 frame.

Move the primeAuxDecoder call to before the frame.Dropped check in both
functions.  stream2 is parsed independently of the VideoToolbox pipeline,
so its IDR data is always valid even when the main frame is zero-filled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>