Fixing Fire TV Cube surround audio, one unnecessary transcode at a time
Surround dropouts on my Fire TV Cube led to two Dolby transport forks, a disposable transcode, and an argument about which box should decode the audio.
My Fire TV Cube kept cutting out when streaming games with surround sound. That eventually became Apollo Dolby and Artemis Dolby Transport, my forks of Apollo and its Android client.
I wanted reliable 5.1 audio. Apparently, that required an audio transport project.
The standard path is straightforward: Apollo encodes audio as Opus, the client decodes it, and Android receives multichannel PCM through AudioTrack. The troublesome part was that last handoff. On some Fire TV and Amlogic devices, six-channel PCM playback can crash or restart Android’s audio service—the failure mode this project targets.
Encoded Dolby playback takes a different path through the device’s audio stack. That gives you the slightly irritating situation where a box can handle surround sound in a movie app while struggling with it in a game-streaming client. Same device, same HDMI connection, same speakers. Different way of asking.
I didn’t have a precise diagnosis of the underlying firmware defect, but I had a useful direction to try: stop feeding Android six-channel PCM and give it AC-3 instead.
Before changing both ends of the stream, I put together a client-side proof of concept. Receive Opus, decode it to PCM, re-encode it as Dolby, then submit the encoded audio to Android.
As a permanent design, this had very little to recommend it. Two lossy encoding stages, extra client-side work, and another place to accumulate latency. As an experiment, it answered the question quickly.
It seemed to work.
That was the interesting result. The network transport was still Opus, but changing the format submitted to Android appeared to avoid the surround-audio problem. The extra transcode had earned its existence. Now I could get rid of it.
The natural next step was to move Dolby encoding onto the host and replace Opus entirely for this mode. Apollo would capture 5.1 PCM and encode it directly into AC-3 or E-AC-3. Artemis would receive complete encoded frames and submit them to an AudioTrack configured for that format. No audio decoding or re-encoding inside the client.
That became the two forks. The transport is explicitly negotiated, so unmodified clients continue using Opus. The Android client has an Off / AC-3 / E-AC-3 setting, and the Dolby path is limited to 48 kHz 5.1. Stereo, 7.1, and unsupported configurations stay on the standard path.
The E-AC-3 implementation uses 16 ms audio frames, compared with 32 ms for AC-3. That gives it a shorter host-side accumulation interval, though it isn’t an end-to-end latency guarantee: the device’s output buffering still gets a say. In actual use on my Cube, latency has been very low.
At this point, I also wanted the Dolby stream to pass through the Cube untouched and reach my AVR for decoding. The client was already leaving it encoded. Finishing the trip seemed reasonable.
I spent a considerable amount of effort trying to make that happen.
The Cube kept decoding it itself.
Submitting encoded audio to Android and getting bitstream passthrough over HDMI are two separate things. I had control over the first. Fire OS had opinions about the second. My AVR was sitting there perfectly capable of decoding Dolby, but the Cube apparently didn’t believe in delegating.
With the recent firmware on my third-generation Cube, I couldn’t get Dolby passthrough working in this setup. I vaguely remember it working with Kodi around the time the third-generation Cube first launched, but I could be remembering that wrong. Kodi may also have used a different output path. Without a controlled comparison, I can’t call this a firmware regression.
What I could establish was that the surround dropouts were gone.
Even with the Cube still doing the decoding, feeding it encoded Dolby worked well. My best explanation is that this avoided the problematic application-supplied multichannel PCM path. Decoding still happened inside the device, but entering its audio stack through a different route changed the result.
Somewhere along the way, I had stopped debugging interrupted audio and started arguing with the Cube about where decoding should happen. The original problem was already fixed.
If you want to try it, you’ll need both Apollo Dolby and Artemis Dolby Transport. The Android build installs alongside standard Artemis, so you can keep both and compare. The repositories document the build and configuration details.
Other Android TV devices may pass the encoded stream through to the AVR as intended; that depends on the device, firmware, and output configuration. On my Cube, I got stable 5.1 and very low latency in use.
The Cube still insists on doing the decoding. At least it has stopped taking breaks.