Skip to content

Fix black frames on Tizen 9/10 (2025+ / Micro RGB): renamed ppi_ve_* capture symbols - #14

Open
bashctrl wants to merge 2 commits into
reisxd:mainfrom
bashctrl:fix/tizen10-ppi-capture-symbols
Open

Fix black frames on Tizen 9/10 (2025+ / Micro RGB): renamed ppi_ve_* capture symbols#14
bashctrl wants to merge 2 commits into
reisxd:mainfrom
bashctrl:fix/tizen10-ppi-capture-symbols

Conversation

@bashctrl

@bashctrl bashctrl commented Jul 17, 2026

Copy link
Copy Markdown

Problem

On newer Samsung firmware (confirmed: 2026 R95H 65" Micro RGB, model MRA65R95HAWXXY, Tizen 10 / One UI Tizen), HyperTizen connects to Hyperion/HyperHDR and streams at full rate — but every frame is pure black.

Root cause: Samsung renamed the libvideoenhance.so RGB-measure entry points with a ppi_ prefix. The library on Tizen 10 exports:

ppi_ve_get_rgb_measure_condition
ppi_ve_set_rgb_measure_position
ppi_ve_get_rgb_measure_pixel

The existing ve_* imports no longer resolve, so GetCondition() hits EntryPointNotFoundException, the catch block swallows it, and GetColors() returns zero-filled arrays forever — black frames that look like a working stream. (This may also explain reports like #13 where newer TVs "connect but nothing happens".)

Fix

  • Add DllImports for the three ppi_ve_* entry points.
  • Add a runtime DetectApi() using NativeLibrary.TryGetExport that probes the library once and selects between cs_ve_* (legacy), ve_* (Tizen 7+), and ppi_ve_* (Tizen 9/10, 2025+). Falls back to the previous version-based heuristic if probing fails, so behavior on older TVs is unchanged.
  • Replace the inline IsTizen7OrHigher branches in GetCondition()/GetColors() with the dispatchers.

Verification (on the R95H, Tizen 10)

  • DetectApi()Ppi; measure condition returns 0 with 3840x2160, 2 capture slots, 16x16 density, 20ms sleep.
  • Pixel reads return live 10-bit color from playing video (e.g. (236,163,116), (502,519,585)), where the un-prefixed imports previously threw.
  • End-to-end: HyperTizen → HyperHDR v22 → Hue Entertainment area syncs correctly with on-screen content.

As far as I know this is the first confirmed working HyperTizen setup on a 2026 Micro RGB / Tizen 10 panel — happy to test follow-ups on this hardware.

Samsung renamed the libvideoenhance.so RGB-measure entry points with a
ppi_ prefix on newer firmware (confirmed on a 2026 R95H Micro RGB,
Tizen 10). The un-prefixed ve_* names no longer resolve, so
GetCondition() threw EntryPointNotFoundException (silently caught) and
the capturer streamed all-black frames while appearing to work.

Add DllImports for ppi_ve_get_rgb_measure_condition /
ppi_ve_set_rgb_measure_position / ppi_ve_get_rgb_measure_pixel and a
runtime DetectApi() using NativeLibrary.TryGetExport that selects
between the legacy cs_ve_*, ve_*, and new ppi_ve_* entry points, so
older TVs keep their existing behavior.

Verified on MRA65R95HAWXXY (65" Micro RGB, Tizen 10): measure condition
reports 3840x2160 and pixel reads return live color; end-to-end
HyperHDR -> Hue Entertainment sync works.
@bashctrl
bashctrl force-pushed the fix/tizen10-ppi-capture-symbols branch from 64e8ee7 to 63597e8 Compare July 17, 2026 03:48
DetectApi() now probes all three RGB-measure symbol sets (ppi_ve_/ve_/cs_ve_)
and returns an explicit Unsupported result when none of them are exported,
instead of silently falling back to the legacy symbols and throwing an
EntryPointNotFoundException at measure time.

GetCondition() short-circuits on Unsupported with a clear notification, and on
success posts a one-time notification and writes a "detectedApi" preference
(readable over the config websocket) recording which symbol set resolved plus
the dimensions the panel reported. This makes a "stream healthy but frames are
black" case diagnosable without attaching a debugger.
@bashctrl

Copy link
Copy Markdown
Author

Yeah, I reckon the branch is worth a shot.

The release build picks the capture symbols purely off the Tizen version number. Anything 7 or higher calls the ve_* functions, anything below calls the old cs_ve_* ones. Your monitor reports 6.5 so it'll be going down the cs_ve_* path. If the M7 doesn't actually export those (some of the newer panels export ve_* even on older-looking firmware), the call throws, the old code quietly swallows it, and you get exactly what you're seeing: a stream that looks healthy on the Hyperion side but every frame is black.

The branch stops guessing from the version and probes the library at runtime instead, so it picks whichever set the panel really exports (ppi_ve_, ve_, or cs_ve_). If your black frames are down to a symbol mismatch, that on its own should sort it.

Roughly three things it could be:

  1. wrong symbol set chosen by version. the branch fixes this by itself.
  2. right symbols, but the measure-condition call fails or comes back with zero width/height. the branch won't fix that, we'd have to dig.
  3. right symbols, condition looks sane, but the pixel reads come back black anyway. that'd mean the monitor's measure API isn't populating on this input path, which is a different beast to the TVs.

I've added a bit more to the branch to tell you which of those you're in. On startup it pops a notification with the API it resolved to and the dimensions it read, and it writes the same string to a detectedApi pref you can read back over its websocket once it's had a go at capturing (send {"event":1,"key":"detectedApi"} to ws://<monitor-ip>:8086). If none of the three symbol sets are present it now says so outright instead of streaming black at you.

If you'd rather go straight to the root of it, I've also got a diagnostic build that dumps the exported symbol names out of libvideoenhance.so, plus the condition and a handful of sample pixel reads. That'll show the real function names on 6.5 and whether the pixels are genuinely coming back zero.

One catch on handing you a ready-to-run file. Samsung packages are author and distributor signed and the signature is tied to the cert, so a tpk I sign won't install on your monitor. You'd need to re-sign it with your own Samsung cert profile, or just build it yourself since you're already set up for that. Happy to drop the diagnostic as a patch and a re-signable tpk if you want it.

So if you can build the branch, install it and tell me which API it resolved to and the dimensions it reports, that'll narrow it down quick. My money's on the first one.

@bashctrl

Copy link
Copy Markdown
Author

@eraylmz pushed the update, see above whenever you get a chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant