Repository navigation
Audio: per-TV Opus limits, and formats the player learns to avoid - #1034
Conversation
The device table already lists OPUS, but DP_AUDIO_CODECS never offered it, so
every Opus track went to the server for conversion and Force direct play failed.
- devcaps: opus is a pipeline-only audio codec, appended only when the device
table was actually read; the assumed fallback still omits it, and Force
direct play applies the same table gate (forced_feeds_audio).
- engine: the Load payload carries codec.audio "OPUS" plus contents.opusInfo
{channels, sampleRate 48, streamHeader = base64 OpusHead} (family 0 for 1-2
channels, Vorbis mapping family 1 for 3-8). An unknown width refuses the Load.
- transcoder: opus joins the copy-only lanes, last, so it is never the encode head.
Verified on an LG C5 (webOS 10.3): AV1 + Opus 5.1 MKV direct play, seeks and
next-episode autoplay. Known gap: a native switch between two Opus tracks of
different widths keeps the first track's channel count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 26bf886)
Signed-off-by: Dr-Amp <dr_amp@users.noreply.github.com>
…he server A C1 (webOS 6) stalls on 5.1 Opus once packets pass ~1500 bytes, with nothing in the log (GLinnik21#917, GLinnik21#918). Auto now caps Opus at two channels whatever a table row claims, so the profile's audio.channels limitation hands surround Opus to the server and the planner refuses it locally. Force Direct Play keeps no ceiling, as for every codec; a 5.1 Opus film played through on a C5 (webOS 10.3), which is what a later per-model allowance would rest on. Signed-off-by: Dr-Amp <dr_amp@users.noreply.github.com>
Signed-off-by: Dr-Amp <dr_amp@users.noreply.github.com>
Brings upstream main (e87ca65: FLAC decoded in the app and fed as PCM, GLinnik21#950) into the Opus branch. Conflicts, each resolved by keeping both sides: - Load audio code: upstream's FLAC PCM already takes 5, so Opus moves to 6 (audio_payload_codec, load_a_str, and the Opus Load test). - devcaps: forced_feeds_audio admits pipeline-only Opus and app-decoded FLAC on a read table. The audio list is DP_AUDIO_CODECS's subset, then Opus, then flac. OPUS_AUTO_MAX_CHANNELS and PCM_MAX_CHANNELS are both classified in ci/list-caps.ini. - engine: the opusInfo helpers and upstream's pcmInfo helpers are both kept. Signed-off-by: Dr-Amp <dr_amp@users.noreply.github.com>
… learns Builds on GLinnik21#992 (Opus direct play, stereo in Auto). Auto's stereo ceiling for Opus is unchanged. What a set announces for audio the pipeline decodes itself is now layered, in this order and logged at boot ("devcaps: ... audio layers:"): the device codec table, minus the codecs /etc/gst/gstcool.conf shows no decoder for, minus per-firmware exclusions (devcaps::EXCLUSIONS, keyed on the firmware codename, each row carrying its evidence), minus the refusals this install has learned. - LG C1 (webOS 6.5.3, "kisscurl-koli"), measured: stereo Opus plays; 6-channel Opus stalls the pipeline once packets pass 1500 bytes (1500 B CBR plays; 1536 B CBR and VBR noise stall after ~190 AUs, with no event); Vorbis is refused (type=18 num=200). The Opus row limits it to stereo, and Force Direct Play now holds a measured ceiling too (Caps::forced_feeds_audio_track), where it used to apply none. - A native Load that ends in type=18 num=200 before any picture, or a native surround feed that stalls (Load returned, no picture, both AU queues holding data, nothing accepted for 4 s), is learned as a refusal for that firmware, codec and channel count, and the play is retried once through the Retry path, which now has the server convert that audio. A known combination never retries, so it cannot loop; stereo is never learned from a stall. - A learned refusal records the firmware build (nyx core_os_release); at boot, entries of another build, and those an older record never tagged, are forgotten, so a firmware update gets a fresh native try. - Debug switches (debug builds): nativeaudiowide lifts the exclusions and learned entries, nativeaudiolearn keeps learning under it, nativeaudioforget clears the learned list at start. FLAC stays on the app-decoded PCM route (GLinnik21#950); native Vorbis is not fed (libpf's Vorbis element needs a caps streamheader the payload has no key for), and the exclusion row records the C1's refusal. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Tiago Pereira <1698241+tiper@users.noreply.github.com>
…caps merge Behaviour is unchanged. - engine.rs: drop the local `base64` helper; `opusInfo.streamHeader` is encoded with the existing `plx_base::b64::encode` (the keymanager and SPKI pin code already share it). The RFC 4648 vector test moves to `base/src/b64.rs`, next to the code it covers. - engine.rs: remove a stray blank line the PR added before an unrelated test. - devcaps.rs: the Opus Auto ceiling uses `BTreeMap::entry` instead of a get/insert pair, and the `table_gated` closure (used once negated, once as a filter) becomes a direct `PIPELINE_ONLY_AUDIO.contains` test on each side. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves the Preferences descriptor imports and count: GLinnik21#992's InstantDpadSeeking row (17 Setting rows) next to GLinnik21#1034's NativeAudioRefusal list row (5 list rows). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1034 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…his tree Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…21#937's shared step GLinnik21#937 made fail_engine_for_good (fail the Engine, enter Error, arm the pipeline release) the one place an Engine ends for good. The two sites this branch adds, the learned Load refusal and the learned native-audio stall, open-coded the old fail-and-Error pair and so skipped arming the release; they call the shared step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… learned refusals The refused-native-audio retry no longer restarts the play from the app loop. A type=18 num=200 refusal before the first frame, or the stall watchdog firing, is learned and then recovered on the pre-picture recovery path every failed open already uses: open_failure_action picks ConvertNativeAudio, route::dispatch_native_audio_conversion flies a ClaimWork::Encode under a FlightOwner::Recovery (today's rebuild, planned against the new capability answer), and land_recovery_flight reloads onto it. The viewer keeps the connecting spinner and never sees the error read-out. Removed: native_audio_retry, take_native_audio_retry, retry_after_native_audio_refusal. The install preference prefs.native_audio_refused is now the one list of learned refusals, changed through one method on the session (with_native_audio_refusal, which also retires another build's rows). devcaps keeps no list: it holds the Arc<Caps> answer derived from it and folds refusals into it monotonically (they only ever remove native audio), from a fresh refusal and from the stored record. The per-rebuild Box::leak snapshots and the second FORGOTTEN global are gone. The projection that runs under the session cache lock is now pure; the queued write it used to make re-entered that lock. Tests: a hostsim pump test that a native-audio refusal before the first frame ends in a recovery flight and not PlaybackState::Error (red before this change), one that a refused conversion fails once without looping, and devcaps/session tests for the fold and the single owner. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A direct play with native surround audio rebuilds as the plain Original remux (the server copies the video, converts only the audio), the same contract an undecodable audio-track pick asks for; only a subtitle the server must burn makes it a re-encode. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…y attempt (review fix) The refused-audio conversion's landing reopens the engine after a failed open but never advanced the attempt ledger, so a failure of the converted route was reported as the first fresh open instead of the app's own recovery. The other recovery flights (the rollback rebase, the auto-HLS install) record the reopen; the Retranscode arm of install_recovery_landing now does too, once the start transaction is prepared and before the install verdict. The flight test asserts the origin and ordinal after the landing. FlightRig gets begin_attempt so a rig route belongs to a report attempt (a ledger note from trace generation 0 changes nothing); the drop puts the generation and latches back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @tiper, the packet-size measurement on the C1 is exactly the evidence this needed, and the per-firmware table with its evidence strings is a nice shape. Merged. What I changed before merging:
Kept as you wrote them: the measurements, the exclusion table, the stall watchdog and packet-size evidence, the stored preference type with its stale-build handling, and your tests. Nothing here was run on a TV, so a C1 check of the converted 5.1 Opus route would be welcome. |
…1063) Tests pin that Force Direct Play refuses audio the install has learned the TV refuses before any Load, naming the codec and offering "Switch to Auto and play". No production change: the Forced gate reads the attempt's start value (#1054, #1062), and main has refused this case since #1034. - `forced_direct_play_refuses_a_learned_refusal_before_the_load`: Forced plus a stored `dca 6` row gives `ForcedFailure::Audio { codec: "DTS" }` and no part URL. - `forced_direct_play_plays_the_ac3_sibling_of_a_learned_dts`: with an AC3 sibling, Forced plays the sibling. - `the_play_start_value_lacks_an_applied_refusal`: the first test of the app's `start_caps()`. - Red observed by mutation (the wrapper returning the boot value; the Forced pick reading the global; the Forced arm using the codec-level check). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f alone Upstream's GLinnik21#992 and GLinnik21#1034 now feed stereo Opus to the television's own decoder, with the per-firmware exclusions and the learned refusals, and GLinnik21#950 feeds FLAC as PCM. That replaces FinNative's own native FLAC, Opus and Vorbis feed, which this commit used to carry: on the C1 its native FLAC was stereo only, where the PCM route already plays it, and Vorbis was refused at every channel count. What remains is the one rule the conversion needs beside them: with Convert audio on the TV, a track the TV's table decodes at its channel count is fed as it is, not converted to AC3. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The maintainer pushed "Simplify:" commits onto every PR of ours he merged (GLinnik21#839, GLinnik21#937, GLinnik21#1018, GLinnik21#1034), behaviour unchanged each time. The skill writes down what he changed (reuse the existing path, one owner per state, values over globals, one named step for a repeated sequence, no redundant guards, docs kept true) and the steps to take before opening an upstream PR so he does not have to. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@GLinnik21 Auto: converted by the server, plays with no error screen. Thanks for the rework, it’s cleaner than mine 🙂 |
Builds on #992. Its stereo cap in Auto is unchanged.
On my LG C1 (webOS 6.5.3), 5.1 Opus stalls silently once packets go over 1500 bytes, and Vorbis is refused. This adds:
FLAC stays on #950’s PCM route. Only measured on a C1 so far.