Posters from Better Posters (and any other WebP source) now decode on Samsung Tizen. If you are on Tizen, update.
The missing posters were WebP all along
A photo of the on-screen log from a Samsung QN90A settled it:
[tex] decode falhou (Unsupported image format) tam=14312 magica=52494646
52494646 is RIFF — a WebP file. I had dismissed this theory earlier in the week after testing only Metahub, which returns JPEG regardless of the Accept header, and I wrongly generalised that to every artwork source. Better Posters serves WebP.
The app already had a WebP decoder (src/webp.c), but it only knew one way in: dlopen the system libwebp. That works on webOS and macOS. In WebAssembly there is no dlopen — the header compiles and every call returns NULL — so on Tizen it had been failing silently since the day it was written. Emscripten has no libwebp port either; asking SDL_image for "webp" breaks its own build.
The decoder was there the whole time. The app runs inside a browser, and browsers read WebP natively. What was missing was a bridge from an asynchronous browser API to a synchronous decode thread. The decode thread now allocates a small state block, hands the bytes to the main thread and sleeps on a futex; the main thread only starts createImageBitmap and returns to the frame loop, and when the promise resolves the bitmap goes through a 2D canvas, becomes RGBA, and an Atomics.notify wakes the decode thread. The frame loses a drawImage plus a getImageData of one poster — sub-millisecond.
Two choices worth naming, because the obvious alternatives are worse:
- A futex, not Asyncify. Asyncify would be shorter, but it would put stack unwinding inside a pthread Worker on an operation that runs hundreds of times per session.
- The main thread, not the worker. A worker has no
document, so it would meanOffscreenCanvas— available in the TV's Chromium 76, but extra risk on hardware I do not have on the bench.
Verification
I do not own a Samsung, so "it compiles" would not have been good enough. There is a new browser-driven test, tests/webp-tizen.sh: it compiles the same src/webp.c with a pthread calling webp_carregar and serves the page with COOP/COEP (without both headers there is no SharedArrayBuffer, therefore no pthread, therefore no test). In a Chromium:
[webp] navegador decodificou o primeiro: 1477x980
ok webp 1477x980 formato=ABGR8888
pixel central rgba=229,9,19,255
webp: tudo ok
Same image and same dimensions as the native test, with a real pixel rather than a block of zeros, and the non-WebP input still returning NULL quietly. The dlopen branch still passes tests/webp.sh unchanged after the reorganisation, and the webOS build was run on an OLED65C9 at 60.0 fps with no crash report.
On the TV: open the log panel (red button) and look for [webp] navegador decodificou o primeiro: WxH. If that line appears, WebP artwork is decoding.
Closes #17, and the remaining part of #1.
Installing
Samsung Tizen 5.5+ — NuvioTV-1.0.15-tizen.wgt, unsigned; sign it with your own TV's DUID (steps in the v1.0.7 notes).
LG webOS 4.x — space.nuvio.native.legacy_1.0.15_arm.ipk. Nothing in this release changes webOS behaviour; everything from v1.0.14 is included.
Unofficial, and not affiliated with NuvioMedia.