Start
Video playback
A public YouTube video now plays to completion in the QEMU development runtime, with decoded frames and non-silent PCM captured from the virtual audio device. Local WebM and WebAudio tests also pass. Physical speakers and higher resolutions remain unverified. Repeated navigation later exhausted the guest memory pool and caused a browser page fault; this is a working short-playback milestone, not a claim of stable long-session browsing.
Latest stability pass#
The later October 3 run used kernel 8583de8f5609, QEMU WHPX with four CPUs and 8 GiB RAM, and a fresh disposable FAT16 browser disk. All four local VP8/Vorbis and VP9/Opus HTML5/MSE cases passed clock, pause, seek, and ending checks again. Their run IDs are 1791052762093-d6a6aae53178f, 1791052860858-8b7b2be08d929, 1791052915035-90795f3b5b8f7, and 1791052955655-1b4c69ae67ac2 in the fixture telemetry.
The mapping hint table now coalesces overlapping records and preserves live edges when an unmap split cannot allocate metadata. This corrects reproduced bookkeeping failures; it does not establish stable browser memory use. The same guest grew to approximately 3,683 MiB committed with 18 address spaces after initial browsing, the four local cases, and a YouTube navigation. The YouTube document had no video element at the sampled point and retained the old displayed frame. Creating another tab raised committed memory above 4,100 MiB. The 30-minute responsive browsing/playback target was not met.
Evidence is under ignored build/browser-stability-qemu/: kernel/source hashes, serial log, individual navigation reports, memory samples, and screenshots. The automatic sampler stopped when a diagnostic operation held the QMP connection; subsequent manual samples are separate. Do not interpret that sampling gap as a constant-memory interval. Diagnostic pauses and production tracing also make this unsuitable as an FPS benchmark.
The memory audit separates implemented metadata fixes from remaining retention and lifetime problems. This pass did not retest physical speakers or the Beelink, change the browser sandbox flags, or establish YouTube controls and longer playback.
Earlier playback evidence#
The October 3, 2026 runs used the staged Chrome/Chromium 152 runtime, QEMU WHPX, a disposable guest disk, and the native XerisOS kernel. That build has SHA-256 prefix c1a29d; the four video combinations below passed on the preceding 741cd537 build. Clips are short and 320x240, so these results do not establish sustained FPS or high-resolution playback quality.
| Check | Observed result |
|---|---|
| VP8/Vorbis and VP9/Opus, HTML5 | Both passed clock-rate, pause, seek, and ending checks |
| VP8/Vorbis and VP9/Opus, Media Source Extensions (MSE) | Both passed clock-rate, pause, seek, and ending checks |
| Local-fixture fullscreen | Enter and exit worked in QEMU; YouTube fullscreen remains unverified |
| Fully downloaded three-second WAV, played from a Blob URL | Clock advanced 0.918373 s in 1.0017 s; reached its end; captured 440 Hz PCM |
| WebAudio oscillator | Clock advanced 2.0053 s in 2.002 s; captured 440 Hz PCM |
| ALSA device discovery | Before: zero hints. After: one real playback hint, hw:CARD=XerisHDA,DEV=0, which opened successfully |
| Guest libasound device setup | All 16 rate/channel/device configurations passed after negotiation fixes |
| Guest PCM handle lifetime | Passed: closing an older stream preserves the replacement's prepared state; snd_pcm_drop succeeds |
| YouTube website/player | Public 19.021 s clip completed at 320x240, unmuted at volume 1; 288 total frames, 13 dropped, and captured PCM |
Evidence is local and ignored by Git:
build/media-playback/telemetry.jsonlcontains the four video runs and Blob WAV run1791009088381-fde2edd70689b8, including clock measurements.build/youtube-qemu/blob-tone-pcm.jsonrecords 264,550 nonzero sample values across both channels, spanning 3.179274 s from first to last active sample.build/youtube-qemu/hints-webaudio-pcm.jsonrecords 171,216 nonzero sample values across both channels, spanning 1.965 s. Both captures are stereo, 44.1 kHz, with a measured tone near 440 Hz.build/youtube-qemu/alsa-hints-before.logandalsa-hints-after.logpreserve the discovery comparison and guest probe results.build/youtube-qemu/youtube-hints-pcm.jsonrecords 1,667,826 nonzero sample values and 19.1814 s from first to last active sample. The actual website test usedhttps://www.youtube.com/watch?v=jNQXAC9IVRw; bounded one-second samples showed approximately normal clock progress throughended: true, with 251,930 decoded audio bytes. This was website playback, not a downloaded test asset. The separate YouTube controls attempt did not complete because a later page load stalled.build/youtube-qemu/youtube-success-and-oom.logpreserves that successful playback and the later fault after further navigation. The kernel reportedcommitted=4862MB dry=1before the failure in the 8 GiB guest. The broader out-of-memory/page-table rollback repair was not applied. A separate earlier loading stall remained in a Blink hash-table insertion loop; its cause has not been established.build/youtube-qemu/youtube-controls-loading-stall.logrecords a fresh-run loading stall without physical pool exhaustion (dry=0). A bounded 9.74 s observation found no recurrence of the earlier Blink loop. The cause remains unverified; it must not be attributed solely to the out-of-memory failure.
Physical speaker output has not been verified. Frame counters include seeking and are not a frame-pacing benchmark. Earlier PCM completion records used the video element's state by mistake; use the newer element-specific clock records and separate PCM captures. An empty capture segment is not evidence of silence being submitted to the device.
These results follow fixes for expired scheduler waits, ALSA negotiation and status/control ioctls, per-handle playback ownership, and HDA consumption across ring wrap and underruns. ALSA readiness now honors the negotiated buffer and avail_min; protected BSP maintenance clears consumed samples. Adding a hint for the real hardware PCM also corrected WebAudio's device discovery: its earlier clock advanced through Chromium's fake output path without producing any captured PCM.
Prepare a disposable runtime#
Use a separate test disk/profile and a kernel/symbol pair from the same build. The browser and its runtime libraries are separate inputs; they are not included by these test tools. Keep the tested browser version and launch arguments with the run's evidence.
Before creating the guest data image, ensure its staged payload includes:
FONTS/UI.TTF, copied from the repository'sInter-Regular.ttf, with its font license retained in any distributed package.XKBMAP.TXT, copied fromassets/XKBMAP.TXT, withassets/xkb-data.copyrightretained when distributing it.- The complete existing browser/runtime payload, including its loader and required shared libraries.
Missing fonts can make the browser render incorrectly. Missing XKBMAP.TXT prevents the Wayland keyboard map from being supplied. Check the serial log for font activation and for keymap: no /XKBMAP.TXT before debugging codecs. Use QEMU user-mode networking for the host fixture address below, and an HDA device plus an audio backend when testing sound. Record audio to a disposable WAV if useful; check its samples for actual non-silent output, not merely that a file exists.
Run the local baseline#
From the repository root with Python 3; Node.js is needed only for the JavaScript regression checks:
python tools/media-playback/server.py --download --prepare
python tools/media-playback/test_server.py
node tools/media-playback/test_clock.js
node tools/media-playback/test_blob_tone.js
python tools/media-playback/server.py --port 8765The downloader uses pinned official Chromium test clips and generates a 440 Hz WAV. Downloads, their license/provenance, and telemetry stay under ignored build/media-playback/; no YouTube content is downloaded. The server binds only host loopback and serves an explicit list of test resources.
Open these in the guest browser:
| URL | Test |
|---|---|
http://10.0.2.2:8765/?auto=1 |
VP8/Vorbis HTML5 |
http://10.0.2.2:8765/?auto=1&clip=vp9 |
VP9/Opus HTML5 |
http://10.0.2.2:8765/?auto=mse |
VP8/Vorbis MSE |
http://10.0.2.2:8765/?auto=mse&clip=vp9 |
VP9/Opus MSE |
Run all four when validating a change. For audio without network delivery during playback, click Download WAV baseline, wait for a successful download, then click Play downloaded WAV. The URL tone remains a separate network-path check; a full buffered range alone does not prove all bytes remain cached. Use the sound, tone, and fullscreen buttons with a real click. Tone results have scope: progress-only and audibleOutput: unverified: a moving media clock does not prove audio reached the device. Listen or validate captured PCM separately. Stop the server with Ctrl+C when finished. See the fixture README for telemetry details and limitations.
Remaining work and acceptance criteria#
- Resolve intermittent page-loading stalls and memory-pressure failures. Retain the passing playback baseline while diagnosing each failure; neither the earlier hash-table loop nor hint-table pressure explains every stall.
- Complete YouTube pause/resume, seeking, fullscreen enter/exit, and quality change checks. Preserve player state, selected codecs, browser diagnostics, and captured PCM alongside the completed 19-second website playback run.
- Test more videos and longer playback. Investigate network buffering separately from the passing Blob WAV baseline; the earlier URL tone still had delivery stalls. Do not substitute downloaded/converted YouTube content for website tests.
- Repeat longer clips, browser navigation, and simultaneous activity while measuring frame pacing, dropped frames, and audio/video sync. The IPC, keyboard-locking, timer, and audio regressions do not replace runtime tests.
- Repeat on the Beelink at realistic resolutions and verify physical speaker output. Keep production tracing disabled during timing measurements.
Relevant host regressions (a host C compiler is required; pass --cc if needed):
python tools/test_abi_audio.py
python tools/test_abi_fionread.py
python tools/test_hda_stream_ring.py
python tools/test_bsp_audio.py
python tools/test_scheduler_deadlines.py
python tools/test_scm_send.py
python tools/test_socket_shutdown.py
python tools/test_wayland_fullscreen.py
python tools/test_wayland_keys.pyFor the real-libasound regression, build tools/build_alsa_guest_probe.ps1 against the staged runtime, stage its ALSAPROBE.ELF beside the loader/libraries, and run /ALSAPROBE.ELF in the disposable guest. Its default run checks device discovery and opening, handle lifetime, and all 16 format configurations.
The native Video app remains a separate, silent MJPEG player with an 8 MiB file cap and 512x512 frame limit. Its VIDEO.MJP path is not the browser/YouTube playback path.