Files
RetroArch/settings
LibretroAdmin 2050622c21 gfx_thumbnail: optional preview audio for animated WebM thumbnails
New setting 'Animated Thumbnail Audio' (menu_thumbnail_preview_audio,
default off): while an animated WebM thumbnail is shown, its audio
track is decoded and looped through the audio mixer, and stops when
the thumbnail closes.

New libretro-common module formats/webm/rwebm_audio.c decodes the
first supported audio track of an in-memory WebM file to interleaved
s16 PCM (plus a convenience wrapper producing a complete in-memory
RIFF/WAVE):

- Opus goes straight through ropus: the CodecPrivate is the OpusHead,
  packets decode independently, pre-skip is dropped from the stream
  start and DiscardPadding trimmed from the packets carrying it.
- Vorbis has no packet-level decoder here, so the track is wrapped
  into a well-formed in-memory Ogg stream - Xiph-laced CodecPrivate
  split into the three header packets, one packet per page, correct
  page CRCs, granules derived from container timestamps with a small
  surplus on the final page - and handed to rvorbis.

Correctness: PCM output matches ffmpeg's decode of the same files at
the exact same sample count with a maximum difference of 1 LSB
(Vorbis) / 3 LSB, 100% within +-2 (Opus) - the fixed-point vs float
pipeline residue - and the Ogg synthesis is proven byte-exact by
decoding ffmpeg's own -c copy remux of the track through the same
rvorbis and comparing PCM. 300-case truncation/corruption fuzz over
both codecs runs clean under ASan/UBSan/LSan. The duration cap is
honoured exactly (5 s request yields exactly 240,000 frames at
48 kHz) and the generated WAV parses as valid 16-bit PCM.

Integration reuses the animated-thumbnail decode worker: the audio
decode runs as a job on the shared worker thread (a synchronous
fallback covers HAVE_THREADS=0 builds, a one-shot cost when the
preview opens), and the finished WAV is handed to the mixer from
gfx_thumbnail_animate (AUDIO_STREAM_TYPE_SYSTEM, WAV, looped; the
mixer copies the buffer, so the job frees its own). A single preview
stream exists at a time, identified by a distinctive stream name and
verified by name again before removal so an unrelated stream that
replaced it is never touched. Decoded PCM is capped at 90 s. The
extended concurrency hammer - the verbatim worker code with audio
jobs mixed into the video job load and hostile release timing -
passes 20,000 iterations under both TSan and ASan, and the video
thumbnail pipeline is regression-checked hash-identical on the
1080p VP8 and VP9 corpus files.

The setting row lives in the settings_def single-source system
(settings_def_menu_thumbnail_background.h, generalized to thumbnail
display settings), which generates the enum, labels, sublabel,
config persistence and menu entry; manual sites are the struct field,
the default, the displaylist row and the sublabel binding.
2026-07-15 03:44:48 +02:00
..