androidx / androidx/media

DefaultAudioSink pending-data accounting breaks expanding AudioOutput transcoding (TrueHD to MAT)

Open
#3,329 4 comments 0 reactions 1 assignee View on GitHub

@tianyif is already working on this.

Since Jul 17, 2026.

closed-by-bot question
Dominant language
Java
Stars
3k
Forks
955
Avg merge
12d 14h
Merged PRs (30d)
2

Description

Version

Media3 1.10.1

More version details

No response

Devices that reproduce the issue
  • UGOOS AM9 Pro, Android 14 (API 34), Amlogic platform
  • HDMI output connected to a receiver that supports Dolby TrueHD
Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Not tested

Reproduction steps
  1. Configure DefaultAudioSink with a custom AudioOutputProvider.
  2. Return FORMAT_SUPPORTED_WITH_TRANSCODING for Dolby TrueHD.
  3. In the AudioOutput, repacketize each TrueHD encoded input buffer into one or more MAT/IEC 61937 carrier buffers.
  4. Use non-blocking output writes. When only part of the generated carrier data can be written:
    • retain the remaining generated carrier data internally;
    • return false from AudioOutput.write();
    • finish writing it on subsequent calls with the same input buffer.
  5. Play the Dolby TrueHD track from the main playlist of the retail Blu-ray release of Zootopia (2016).

The issue is particularly visible around a branched play-item boundary at approximately 10:29. With other TrueHD titles, the same output implementation can stall almost immediately at approximately 118-130 ms.

Expected result

DefaultAudioSink should remain ready while either encoded input has not played out or the custom AudioOutput still has internally generated output data pending.

An AudioOutputProvider using the documented internal-transcoding support should be able to expand or repacketize encoded input without patching DefaultAudioSink.

The API should provide a way for AudioOutput to report its pending internal data or output-domain frame accounting.

Actual result

Playback can become stuck in BUFFERING at approximately 118-130 ms. The upstream buffered position continues to grow, and AudioTrack/HAL remains healthy, but the audio renderer stops making progress.

The root cause is a frame-domain mismatch in DefaultAudioSink:

  1. drainOutputBuffer() increments writtenEncodedFrames only after the original encoded input buffer has been fully handled.
  2. During a partial write, the custom AudioOutput may already have submitted MAT carrier data, so its output playhead advances while DefaultAudioSink.writtenEncodedFrames remains unchanged.
  3. hasPendingData() calls hasAudioOutputPendingData(getWrittenFrames()).
  4. hasAudioOutputPendingData() converts audioOutput.getPositionUs() to frames using audioOutput.getSampleRate(), then compares that output-domain playhead value with writtenEncodedFrames derived from the input encoded access units.
  5. For an expanding transform such as TrueHD to MAT/IEC 61937, these values are not necessarily in the same frame domain. The carrier playhead can catch up to or overtake the stale input-frame count.
  6. hasPendingData() then returns false even though the custom AudioOutput still has generated carrier data pending. The renderer reports that it is not ready and playback can deadlock in BUFFERING.

AudioOutput currently cannot report its own pending internal data or written output-frame count. Clamping getPositionUs() or prematurely reporting the input buffer as fully handled only masks the mismatch and causes incorrect position or drain behavior elsewhere.

Possible solutions include:

  • adding AudioOutput.hasPendingData();
  • exposing submitted/written frames in the actual output domain;
  • returning richer write accounting than a fullyHandled boolean; or
  • delegating pending-data accounting to AudioOutput when FORMAT_SUPPORTED_WITH_TRANSCODING is used.
Media

No media is attached.

The observed source is the Dolby TrueHD track from the main playlist of the retail Blu-ray release of Zootopia (2016). I cannot publicly share this copyrighted media.

The underlying issue does not depend on the exact media bytes: it can be reproduced synthetically with an AudioOutput that expands one encoded input buffer into multiple output buffers and forces partial non-blocking writes.

Bug Report
  • You will email the zip file produced by adb bugreport to android-media-github@google.com after filing this issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.