The prober never asks for the frame HDR10+ announces itself in #30

Closed
opened 2026-08-03 00:05:42 +02:00 by Claude · 1 comment
Collaborator

Settings::supports_first_video_frame is never measured, so the frame is never
read.

Ffprobe::supports_option (crates/jellyfin-ffmpeg/src/prober.rs) exists and
is right, and nothing outside the crate's own tests calls it. The only place
that builds a prober::Settings for a running server leaves the flag at its
false default, and arguments only appends -show_frames -only_first_vframe
when it is true — so no probe this server makes ever asks for the frame.

That frame is where HDR10+ and Dolby Vision announce themselves. Upstream
measures the option once at startup
(MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs, CheckSupportedProberOption)
and passes it for every local video afterwards, so a file whose dynamic range a
client would be told about is one this server reads as plain.

crates/jellyfin-ffmpeg/README.md already describes the flag as the one
argument measured from the binary rather than derived, which is what it will be
once something measures it.

`Settings::supports_first_video_frame` is never measured, so the frame is never read. `Ffprobe::supports_option` (`crates/jellyfin-ffmpeg/src/prober.rs`) exists and is right, and nothing outside the crate's own tests calls it. The only place that builds a `prober::Settings` for a running server leaves the flag at its `false` default, and `arguments` only appends `-show_frames -only_first_vframe` when it is true — so no probe this server makes ever asks for the frame. That frame is where HDR10+ and Dolby Vision announce themselves. Upstream measures the option once at startup (`MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs`, `CheckSupportedProberOption`) and passes it for every local video afterwards, so a file whose dynamic range a client would be told about is one this server reads as plain. `crates/jellyfin-ffmpeg/README.md` already describes the flag as the one argument measured from the binary rather than derived, which is what it will be once something measures it.
Author
Collaborator

Fixed in the merge of fix/30-hdr10plus.

The binary is asked once at startup whether it takes only_first_vframe, as
the encoder's own capabilities are measured, and the answer is handed to every
probe a scan makes. On this machine it answers no — the option is Jellyfin's
own build rather than a distro one — which is the case the flag exists for.

While wiring it: the frame was being asked for, parsed into
hdr10_plus_present_flag, and then dropped on the write. The insert named 46
columns and Hdr10PlusPresentFlag was not one of them, though every Dolby
Vision sibling was — so a video carrying HDR10+ read exactly like one without,
and /Items answered HDR10 where upstream answers HDR10Plus. That is the
whole of what this issue was worth, and it now has a test:
crates/jellyfin-db/tests/streams.rs writes a stream carrying every
dynamic-range field and reads the columns back.

Fixed in the merge of `fix/30-hdr10plus`. The binary is asked once at startup whether it takes `only_first_vframe`, as the encoder's own capabilities are measured, and the answer is handed to every probe a scan makes. On this machine it answers no — the option is Jellyfin's own build rather than a distro one — which is the case the flag exists for. While wiring it: the frame was being asked for, parsed into `hdr10_plus_present_flag`, and then dropped on the write. The insert named 46 columns and `Hdr10PlusPresentFlag` was not one of them, though every Dolby Vision sibling was — so a video carrying HDR10+ read exactly like one without, and `/Items` answered `HDR10` where upstream answers `HDR10Plus`. That is the whole of what this issue was worth, and it now has a test: `crates/jellyfin-db/tests/streams.rs` writes a stream carrying every dynamic-range field and reads the columns back.
Sign in to join this conversation.
No description provided.