ACR (Automatic Content Recognition) on Android TV requires capturing the audio currently playing on the device for fingerprint matching. ALSA loopback is the obvious first candidate. Spent a day proving it doesn’t work on the Amlogic S905X4 and figuring out why.
The loopback hardware isn’t broken — it’s listening to a wire that carries no signal. AudioFlinger writes PCM to TDM-B, but the Amlogic Audio HAL intercepts the audio before it reaches TDM-B’s hardware I/O pins. The HAL feeds it into the Dolby MS12 DSP for mixing and processing, then ships the result to HDMI TX via an internal SPDIF path that ALSA has zero visibility into. The loopback device points at TDMOUT_B’s hardware output pins — which are muted and carry nothing.
S905X4 Audio Hardware Architecture
7 PCM Devices and the Loopback Relationship
The S905X4 exposes 7 PCM devices on a single ALSA card (AML-AUGESOUND):
| Device | Type | Role |
|---|---|---|
| 0 | TDM-A | Unused (dummy) |
| 1 | TDM-B | AudioFlinger primary output (T9015 DAC) |
| 2 | TDM-C | I2S to HDMI |
| 3 | PDM | Microphone input |
| 4 | SPDIF | Digital audio I/O (optical/coaxial) |
| 5 | SPDIF-B | Secondary digital out |
| 6 | LOOPBACK-A | Capture-only loopback |
AudioFlinger writes to device 1 (TDM-B). The loopback mixer controls point at TDMOUT_B (control #22 → TDMIN_B, control #23 → TDMOUT_B). Looks like it should work.
Where the Audio Actually Goes
From ALSA userspace, TDM-B looks like a normal audio output — /proc/asound/card0/pcm1p/info shows nothing unusual. But the HAL intercepts the audio before it reaches TDM-B’s hardware pins:
AudioFlinger
→ ALSA Device 1 (TDM-B) — HAL handoff point
→ Amlogic Audio HAL
→ Dolby MS12 DSP (mixing, DRC, EQ)
→ Internal SPDIF encoder (not exposed to ALSA)
→ HDMI TX
The loopback device monitors TDMOUT_B’s hardware I/O pins. But TDM-B’s speaker output is muted (mixer control #69 SPK mute = On) because the HAL grabs the PCM before it reaches the pins. Loopback is pointed at an empty wire.
The key diagnostic control is #65 (HDMITX Audio Source Select), which reads Spdif. This directly tells you HDMI TX reads audio from the internal SPDIF bus, not from any TDM output. Once you know that, you know TDM-based loopback can never capture HDMI audio on this platform.
Test Verification
A/B Testing: Bypass HAL vs. Go Through AudioFlinger
To confirm it’s a routing issue and not broken loopback hardware, ran controlled A/B tests:
| Test | What was done | Loopback source | Result |
|---|---|---|---|
| 1 | tinyplay WAV directly to TDM-A (device 0) | TDMOUT_A | -18 dB (audio captured) |
| 2 | tinyplay WAV directly to TDM-C (device 2) | TDMOUT_C | -25 dB (audio captured) |
| 3 | Play a video, capture AudioFlinger output | TDMOUT_B | -999 dB (silence) |
| 4 | Unmute SPK, play UI sounds | TDMOUT_B | -999 dB (silence) |
Tests 1-2 bypass the HAL — tinyplay writes PCM directly to the ALSA device, audio actually reaches the hardware pins, and loopback captures it fine. Tests 3-4 go through AudioFlinger → HAL → MS12, where audio gets diverted before the pins.
The SPDIF Internal Loopback Trap
Mixer control #14 (Audio spdifin source) has a spdifout option that sounds like it routes SPDIF output back to input. Tested it — silence.
The reason: there are two different “SPDIF” paths on this platform:
- ALSA SPDIF (device 4): Physical SPDIF I/O for external optical/coaxial connections.
- HAL internal SPDIF: Post-MS12 DSP path to HDMI TX, not exposed to ALSA.
Control #14’s spdifout loops the ALSA SPDIF device back to itself — it doesn’t tap the HAL’s HDMI-bound path. These are different buses.
Note: This assessment is inferred from control naming and silence test results, not confirmed via kernel source or register dump.
Control #29’s Unused Routing Options
Control #29 (Audio In Source) has some potentially useful options: TDMIN_LB, LOOPBACK_A/B, SPDIFIN_LB, FRHDMIRX. These names suggest the SoC silicon might support internal routing of post-MS12 audio. But all resolved to null in testing.
Possible reasons: the driver doesn’t wire them up, they need complementary controls or DTS configuration, or specific sample rates. Without reviewing the kernel source (sound/soc/amlogic/auge/), it’s hard to say.
Alternative Approaches for ACR
With hardware loopback ruled out, two paths remain:
| Strategy | Capture point | Coverage | Limitation |
|---|---|---|---|
| AudioPlaybackCapture | AudioFlinger layer (above HAL) | Non-DRM content | Two blockers |
| HAL post-MS12 tap | After MS12 DSP (vendor modification) | All content incl. DRM | Requires chipset vendor support |
AudioPlaybackCapture’s Two Blockers
AudioPlaybackCapture works at the AudioFlinger layer, no hardware dependency, so the loopback routing problem doesn’t apply. But it has two blockers:
-
allowAudioPlaybackCapture=false: Apps like Netflix explicitly opt out in their manifest. AudioFlinger returns silent buffers for those sessions. -
Tunneled Playback: For Widevine L1 content (Netflix 4K, Disney+, etc.), audio decoding happens inside the TEE via Android’s tunneled playback path. The audio goes directly from the secure decoder to the HAL — it never enters AudioFlinger at all. AudioPlaybackCapture can’t capture what never reaches AudioFlinger. This is the more fundamental blocker, distinct from the manifest flag.
Actual coverage depends on the app mix — what fraction of viewing time is non-DRM, non-tunneled content (FAST channels, free ad-supported content, etc.).
HAL Post-MS12 Tap
For full coverage (DRM + tunneled + HDMI-in), a post-MS12 loopback tap at the HAL layer is needed. The null mixer options in control #29 hint the silicon might support it, but the chipset vendor needs to wire it up.
If filing a request with the vendor, the critical spec: the tap must output downmixed LPCM after decode but before re-encoding (e.g., before Dolby MAT packaging for eARC). A post-encode tap yields compressed bitstream, which is unusable for ACR fingerprinting.
Summary: Debug Methodology
The most effective debugging approach in this investigation was tracing backwards from the output. Control #65 (HDMITX Audio Source Select = Spdif) immediately reveals that HDMI TX reads from the internal SPDIF bus, not TDM. Checking that control first would have saved hours of loopback testing.
Specific takeaways:
- ALSA device numbers are misleading on this platform. Device 1 (TDM-B) looks like a normal audio output, but the HAL intercepts PCM before it reaches the hardware pins. This isn’t visible from userspace.
- MS12 is a black box from ALSA’s perspective. Once audio enters the DSP, the remaining path is entirely HAL-controlled with no ALSA visibility.
- Mixer control options existing doesn’t mean they work. The
spdifoutloopback route andSPDIFIN_LBinternal routing both exist as options but produce silence. Always measure withtinycap+sox— don’t trust control names. - When diagnosing SoC audio routing, check the output-side source select control first. It directly tells you which bus the audio comes from, eliminating the need to test each path individually.
Note: Test results are from a single Amlogic S905X4 SoC. Other Amlogic models (S905X3, S928X, etc.) may have different audio routing. Control #29’s internal routing options were not tested with DTS changes or other control combinations — the possibility of enabling them is not ruled out.