diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 879edb2af42..41456b8cfc8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -30,6 +30,9 @@ * Add experimental support for parsing subtitles during extraction. You can enable this using `MediaSource.Factory.experimentalParseSubtitlesDuringExtraction()`. + * Fix issue that OPUS and VORBIS channel layouts are wrong for 3, 5, 6, 7 + and 8 channels + ([#8396](https://github.com/google/ExoPlayer/issues/8396)). * Transformer: * Add support for flattening H.265/HEVC SEF slow motion videos. * Increase transmuxing speed, especially for 'remove video' edits. diff --git a/libraries/decoder_opus/build.gradle b/libraries/decoder_opus/build.gradle index 8b88ff82b41..af01cad0137 100644 --- a/libraries/decoder_opus/build.gradle +++ b/libraries/decoder_opus/build.gradle @@ -33,6 +33,7 @@ dependencies { compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion testImplementation project(modulePrefix + 'test-utils') testImplementation 'org.robolectric:robolectric:' + robolectricVersion + androidTestImplementation project(modulePrefix + 'test-utils') androidTestImplementation 'androidx.test:runner:' + androidxTestRunnerVersion androidTestImplementation 'androidx.test.ext:junit:' + androidxTestJUnitVersion } diff --git a/libraries/decoder_opus/src/androidTest/java/androidx/media3/decoder/opus/OpusPlaybackTest.java b/libraries/decoder_opus/src/androidTest/java/androidx/media3/decoder/opus/OpusPlaybackTest.java index 9459bba0738..93f3a4d733a 100644 --- a/libraries/decoder_opus/src/androidTest/java/androidx/media3/decoder/opus/OpusPlaybackTest.java +++ b/libraries/decoder_opus/src/androidTest/java/androidx/media3/decoder/opus/OpusPlaybackTest.java @@ -15,7 +15,7 @@ */ package androidx.media3.decoder.opus; -import static org.junit.Assert.fail; +import static com.google.common.truth.Truth.assertWithMessage; import android.content.Context; import android.net.Uri; @@ -28,9 +28,13 @@ import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.Renderer; import androidx.media3.exoplayer.RenderersFactory; +import androidx.media3.exoplayer.audio.AudioSink; +import androidx.media3.exoplayer.audio.DefaultAudioSink; import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.ProgressiveMediaSource; import androidx.media3.extractor.mkv.MatroskaExtractor; +import androidx.media3.test.utils.CapturingAudioSink; +import androidx.media3.test.utils.DumpFileAsserts; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Before; @@ -41,49 +45,69 @@ @RunWith(AndroidJUnit4.class) public class OpusPlaybackTest { - private static final String BEAR_OPUS_URI = "asset:///media/mka/bear-opus.mka"; - private static final String BEAR_OPUS_NEGATIVE_GAIN_URI = - "asset:///media/mka/bear-opus-negative-gain.mka"; + private static final String BEAR_OPUS = "mka/bear-opus.mka"; + private static final String BEAR_OPUS_NEGATIVE_GAIN = "mka/bear-opus-negative-gain.mka"; + private static final String OPUS_5POINT1 = "mka/opus-5.1.mka"; @Before public void setUp() { - if (!OpusLibrary.isAvailable()) { - fail("Opus library not available."); - } + assertWithMessage("Opus library not available").that(OpusLibrary.isAvailable()).isTrue(); + assertWithMessage("Dump files were generated for x86_64") + .that(System.getProperty("os.arch")) + .isEqualTo("x86_64"); + } + + @Test + public void playBasicOpus() throws Exception { + playUri(BEAR_OPUS); } @Test - public void basicPlayback() throws Exception { - playUri(BEAR_OPUS_URI); + public void playWithNegativeGain() throws Exception { + playUri(BEAR_OPUS_NEGATIVE_GAIN); } @Test - public void basicPlaybackNegativeGain() throws Exception { - playUri(BEAR_OPUS_NEGATIVE_GAIN_URI); + public void play5Point1() throws Exception { + playUri(OPUS_5POINT1); } - private void playUri(String uri) throws Exception { + private void playUri(String fileName) throws Exception { + CapturingAudioSink audioSink = + new CapturingAudioSink( + new DefaultAudioSink.Builder(ApplicationProvider.getApplicationContext()).build()); + TestPlaybackRunnable testPlaybackRunnable = - new TestPlaybackRunnable(Uri.parse(uri), ApplicationProvider.getApplicationContext()); + new TestPlaybackRunnable( + Uri.parse("asset:///media/" + fileName), + ApplicationProvider.getApplicationContext(), + audioSink); Thread thread = new Thread(testPlaybackRunnable); thread.start(); thread.join(); + if (testPlaybackRunnable.playbackException != null) { throw testPlaybackRunnable.playbackException; } + DumpFileAsserts.assertOutput( + ApplicationProvider.getApplicationContext(), + audioSink, + "audiosinkdumps/" + fileName + ".audiosink.dump"); } private static class TestPlaybackRunnable implements Player.Listener, Runnable { private final Context context; private final Uri uri; + private final AudioSink audioSink; @Nullable private ExoPlayer player; @Nullable private PlaybackException playbackException; - public TestPlaybackRunnable(Uri uri, Context context) { + public TestPlaybackRunnable(Uri uri, Context context, AudioSink audioSink) { this.uri = uri; this.context = context; + this.audioSink = audioSink; } @Override @@ -95,7 +119,9 @@ public void run() { audioRendererEventListener, textRendererOutput, metadataRendererOutput) -> - new Renderer[] {new LibopusAudioRenderer(eventHandler, audioRendererEventListener)}; + new Renderer[] { + new LibopusAudioRenderer(eventHandler, audioRendererEventListener, audioSink) + }; player = new ExoPlayer.Builder(context, renderersFactory).build(); player.addListener(this); MediaSource mediaSource = diff --git a/libraries/decoder_opus/src/main/java/androidx/media3/decoder/opus/LibopusAudioRenderer.java b/libraries/decoder_opus/src/main/java/androidx/media3/decoder/opus/LibopusAudioRenderer.java index a31bdc523d8..c916a6e23aa 100644 --- a/libraries/decoder_opus/src/main/java/androidx/media3/decoder/opus/LibopusAudioRenderer.java +++ b/libraries/decoder_opus/src/main/java/androidx/media3/decoder/opus/LibopusAudioRenderer.java @@ -29,6 +29,7 @@ import androidx.media3.exoplayer.audio.AudioSink; import androidx.media3.exoplayer.audio.AudioSink.SinkFormatSupport; import androidx.media3.exoplayer.audio.DecoderAudioRenderer; +import androidx.media3.extractor.VorbisUtil; /** Decodes and renders audio using the native Opus decoder. */ @UnstableApi @@ -140,6 +141,12 @@ protected final Format getOutputFormat(OpusDecoder decoder) { return Util.getPcmFormat(pcmEncoding, decoder.channelCount, OpusDecoder.SAMPLE_RATE); } + @Nullable + @Override + protected int[] getChannelMapping(OpusDecoder decoder) { + return VorbisUtil.getVorbisToAndroidChannelLayoutMapping(decoder.channelCount); + } + /** * Returns true if support for padding removal from the end of decoder output buffer should be * enabled. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java index 1f263bee747..bc895f68463 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java @@ -373,6 +373,18 @@ protected abstract T createDecoder(Format format, @Nullable CryptoConfig cryptoC @ForOverride protected abstract Format getOutputFormat(T decoder); + /** + * Returns the channel layout mapping that should be applied when sending this data to the output, + * or null to not change the channel layout. + * + * @param decoder The decoder. + */ + @ForOverride + @Nullable + protected int[] getChannelMapping(T decoder) { + return null; + } + /** * Evaluates whether the existing decoder can be reused for a new {@link Format}. * @@ -443,7 +455,7 @@ private boolean drainOutputBuffer() .setSelectionFlags(inputFormat.selectionFlags) .setRoleFlags(inputFormat.roleFlags) .build(); - audioSink.configure(outputFormat, /* specifiedBufferSize= */ 0, /* outputChannels= */ null); + audioSink.configure(outputFormat, /* specifiedBufferSize= */ 0, getChannelMapping(decoder)); audioTrackNeedsConfigure = false; } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java index 5e7c854ea70..32d74fe6dfc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java @@ -63,6 +63,7 @@ import androidx.media3.exoplayer.mediacodec.MediaCodecSelector; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil.DecoderQueryException; +import androidx.media3.extractor.VorbisUtil; import com.google.common.collect.ImmutableList; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -108,6 +109,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media private int codecMaxInputSize; private boolean codecNeedsDiscardChannelsWorkaround; + private boolean codecNeedsVorbisToAndroidChannelMappingWorkaround; @Nullable private Format inputFormat; /** Codec used for DRM decryption only in passthrough and offload. */ @@ -435,6 +437,8 @@ protected MediaCodecAdapter.Configuration getMediaCodecConfiguration( float codecOperatingRate) { codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats()); codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name); + codecNeedsVorbisToAndroidChannelMappingWorkaround = + codecNeedsVorbisToAndroidChannelMappingWorkaround(codecInfo.name); MediaFormat mediaFormat = getMediaFormat(format, codecInfo.codecMimeType, codecMaxInputSize, codecOperatingRate); // Store the input MIME type if we're only using the codec for decryption. @@ -567,6 +571,9 @@ protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaF for (int i = 0; i < format.channelCount; i++) { channelMap[i] = i; } + } else if (codecNeedsVorbisToAndroidChannelMappingWorkaround) { + channelMap = + VorbisUtil.getVorbisToAndroidChannelLayoutMapping(audioSinkInputFormat.channelCount); } } try { @@ -972,6 +979,19 @@ private static boolean codecNeedsDiscardChannelsWorkaround(String codecName) { || Util.DEVICE.startsWith("heroqlte")); } + /** + * Returns whether the decoder is known to output PCM samples in VORBIS order, which does not + * match the channel layout required by AudioTrack. + * + *
See https://github.com/google/ExoPlayer/issues/8396#issuecomment-1833867901. + */ + private static boolean codecNeedsVorbisToAndroidChannelMappingWorkaround(String codecName) { + return codecName.equals("OMX.google.opus.decoder") + || codecName.equals("c2.android.opus.decoder") + || codecName.equals("OMX.google.vorbis.decoder") + || codecName.equals("c2.android.vorbis.decoder"); + } + private final class AudioSinkListener implements AudioSink.Listener { @Override diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/VorbisUtil.java b/libraries/extractor/src/main/java/androidx/media3/extractor/VorbisUtil.java index c9bd6f0f57c..8ba2c7f68c3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/VorbisUtil.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/VorbisUtil.java @@ -142,6 +142,31 @@ public Mode(boolean blockFlag, int windowType, int transformType, int mapping) { private static final String TAG = "VorbisUtil"; + /** + * Returns the mapping from VORBIS channel layout to the channel layout expected by Android, or + * null if the mapping is unchanged. + * + *
See https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-140001.2.3 and + * https://developer.android.com/reference/android/media/AudioFormat#channelMask. + */ + @Nullable + public static int[] getVorbisToAndroidChannelLayoutMapping(int channelCount) { + switch (channelCount) { + case 3: + return new int[] {0, 2, 1}; + case 5: + return new int[] {0, 2, 1, 3, 4}; + case 6: + return new int[] {0, 2, 1, 5, 3, 4}; + case 7: + return new int[] {0, 2, 1, 6, 5, 3, 4}; + case 8: + return new int[] {0, 2, 1, 7, 5, 6, 3, 4}; + default: + return null; + } + } + /** * Returns ilog(x), which is the index of the highest set bit in {@code x}. * diff --git a/libraries/test_data/src/test/assets/audiosinkdumps/mka/bear-opus-negative-gain.mka.audiosink.dump b/libraries/test_data/src/test/assets/audiosinkdumps/mka/bear-opus-negative-gain.mka.audiosink.dump new file mode 100644 index 00000000000..fc8e0618b7a --- /dev/null +++ b/libraries/test_data/src/test/assets/audiosinkdumps/mka/bear-opus-negative-gain.mka.audiosink.dump @@ -0,0 +1,418 @@ +AudioSink: + buffer count = 137 + discontinuity: + config: + pcmEncoding = 2 + channelCount = 2 + sampleRate = 48000 + buffer #0: + time = 1000000000000 + data = 1534249025 + buffer #1: + time = 1000000021000 + data = -1160621457 + buffer #2: + time = 1000000041000 + data = 1524340283 + buffer #3: + time = 1000000061000 + data = 1163800337 + buffer #4: + time = 1000000081000 + data = -105012593 + buffer #5: + time = 1000000101000 + data = -2133201155 + buffer #6: + time = 1000000121000 + data = -1879319991 + buffer #7: + time = 1000000141000 + data = -1281296657 + buffer #8: + time = 1000000161000 + data = -2065886367 + buffer #9: + time = 1000000181000 + data = -216960911 + buffer #10: + time = 1000000201000 + data = 1555599959 + buffer #11: + time = 1000000221000 + data = 339234007 + buffer #12: + time = 1000000241000 + data = 1461360461 + buffer #13: + time = 1000000261000 + data = 802335433 + buffer #14: + time = 1000000281000 + data = -862054125 + buffer #15: + time = 1000000301000 + data = -935372767 + buffer #16: + time = 1000000321000 + data = -694406241 + buffer #17: + time = 1000000341000 + data = 893036393 + buffer #18: + time = 1000000361000 + data = 1936536415 + buffer #19: + time = 1000000381000 + data = 1344446245 + buffer #20: + time = 1000000401000 + data = -1313590607 + buffer #21: + time = 1000000421000 + data = -2072467231 + buffer #22: + time = 1000000441000 + data = -427939557 + buffer #23: + time = 1000000461000 + data = -2126178587 + buffer #24: + time = 1000000481000 + data = 523515531 + buffer #25: + time = 1000000501000 + data = -151874963 + buffer #26: + time = 1000000521000 + data = -1396642939 + buffer #27: + time = 1000000541000 + data = -1235361655 + buffer #28: + time = 1000000561000 + data = -158077129 + buffer #29: + time = 1000000581000 + data = -1682415467 + buffer #30: + time = 1000000601000 + data = -1176101729 + buffer #31: + time = 1000000621000 + data = -704032195 + buffer #32: + time = 1000000641000 + data = 465894015 + buffer #33: + time = 1000000661000 + data = -27288869 + buffer #34: + time = 1000000681000 + data = -1719466173 + buffer #35: + time = 1000000701000 + data = 1439624139 + buffer #36: + time = 1000000721000 + data = -862685959 + buffer #37: + time = 1000000741000 + data = -635768969 + buffer #38: + time = 1000000761000 + data = 1463029887 + buffer #39: + time = 1000000781000 + data = -1660855877 + buffer #40: + time = 1000000801000 + data = 1307112171 + buffer #41: + time = 1000000821000 + data = -1282716603 + buffer #42: + time = 1000000841000 + data = 352659209 + buffer #43: + time = 1000000861000 + data = 521820619 + buffer #44: + time = 1000000881000 + data = -1386568797 + buffer #45: + time = 1000000901000 + data = 627203727 + buffer #46: + time = 1000000921000 + data = -1289682109 + buffer #47: + time = 1000000941000 + data = -1079104491 + buffer #48: + time = 1000000961000 + data = 1860165669 + buffer #49: + time = 1000000981000 + data = -1869109675 + buffer #50: + time = 1000001001000 + data = 642741353 + buffer #51: + time = 1000001021000 + data = 321535061 + buffer #52: + time = 1000001041000 + data = -1387246105 + buffer #53: + time = 1000001061000 + data = 63597643 + buffer #54: + time = 1000001081000 + data = -2008268735 + buffer #55: + time = 1000001101000 + data = 1401930041 + buffer #56: + time = 1000001121000 + data = -1293882917 + buffer #57: + time = 1000001141000 + data = 1996131816 + buffer #58: + time = 1000001161000 + data = 625350541 + buffer #59: + time = 1000001181000 + data = 1963066731 + buffer #60: + time = 1000001201000 + data = -848788739 + buffer #61: + time = 1000001221000 + data = -2713635 + buffer #62: + time = 1000001241000 + data = -144652795 + buffer #63: + time = 1000001261000 + data = 1348675533 + buffer #64: + time = 1000001281000 + data = -1613237007 + buffer #65: + time = 1000001301000 + data = -576658469 + buffer #66: + time = 1000001321000 + data = 613589157 + buffer #67: + time = 1000001341000 + data = -81666115 + buffer #68: + time = 1000001361000 + data = 570568075 + buffer #69: + time = 1000001381000 + data = -977502779 + buffer #70: + time = 1000001401000 + data = -493504513 + buffer #71: + time = 1000001421000 + data = -1786740767 + buffer #72: + time = 1000001441000 + data = 1075704113 + buffer #73: + time = 1000001461000 + data = -507001669 + buffer #74: + time = 1000001481000 + data = 1865026165 + buffer #75: + time = 1000001501000 + data = -1482835121 + buffer #76: + time = 1000001521000 + data = -882264031 + buffer #77: + time = 1000001541000 + data = 1642205437 + buffer #78: + time = 1000001561000 + data = -1624391337 + buffer #79: + time = 1000001581000 + data = -1550504967 + buffer #80: + time = 1000001601000 + data = -557983941 + buffer #81: + time = 1000001621000 + data = 936743857 + buffer #82: + time = 1000001641000 + data = 1915767603 + buffer #83: + time = 1000001661000 + data = -957349897 + buffer #84: + time = 1000001681000 + data = -1523883729 + buffer #85: + time = 1000001701000 + data = -1907882389 + buffer #86: + time = 1000001721000 + data = 1710427017 + buffer #87: + time = 1000001741000 + data = 2041871971 + buffer #88: + time = 1000001761000 + data = -1935830573 + buffer #89: + time = 1000001781000 + data = -1484122457 + buffer #90: + time = 1000001801000 + data = -1721714237 + buffer #91: + time = 1000001821000 + data = -1862918205 + buffer #92: + time = 1000001841000 + data = -1299355491 + buffer #93: + time = 1000001861000 + data = 1493349553 + buffer #94: + time = 1000001881000 + data = -1606489393 + buffer #95: + time = 1000001901000 + data = 1513605233 + buffer #96: + time = 1000001921000 + data = 475299923 + buffer #97: + time = 1000001941000 + data = 827883163 + buffer #98: + time = 1000001961000 + data = -2054932563 + buffer #99: + time = 1000001981000 + data = -1285258495 + buffer #100: + time = 1000002001000 + data = -382554715 + buffer #101: + time = 1000002021000 + data = -1226363337 + buffer #102: + time = 1000002041000 + data = 1553128795 + buffer #103: + time = 1000002061000 + data = 595466823 + buffer #104: + time = 1000002081000 + data = 44383055 + buffer #105: + time = 1000002101000 + data = -1353640975 + buffer #106: + time = 1000002121000 + data = -499720723 + buffer #107: + time = 1000002141000 + data = 596762589 + buffer #108: + time = 1000002161000 + data = -737253557 + buffer #109: + time = 1000002181000 + data = 434152121 + buffer #110: + time = 1000002201000 + data = -377488175 + buffer #111: + time = 1000002221000 + data = -872643307 + buffer #112: + time = 1000002241000 + data = 392889643 + buffer #113: + time = 1000002261000 + data = 1559385479 + buffer #114: + time = 1000002281000 + data = -1016360257 + buffer #115: + time = 1000002301000 + data = 1137740967 + buffer #116: + time = 1000002321000 + data = 1807943865 + buffer #117: + time = 1000002341000 + data = 1589236519 + buffer #118: + time = 1000002361000 + data = -1689916739 + buffer #119: + time = 1000002381000 + data = -2074624057 + buffer #120: + time = 1000002401000 + data = 1010393293 + buffer #121: + time = 1000002421000 + data = 992155873 + buffer #122: + time = 1000002441000 + data = 789944685 + buffer #123: + time = 1000002461000 + data = -728251655 + buffer #124: + time = 1000002481000 + data = -1837900467 + buffer #125: + time = 1000002501000 + data = 2025029553 + buffer #126: + time = 1000002521000 + data = 1823368377 + buffer #127: + time = 1000002541000 + data = -2016719635 + buffer #128: + time = 1000002561000 + data = 1499897473 + buffer #129: + time = 1000002581000 + data = -795228127 + buffer #130: + time = 1000002601000 + data = 1268719372 + buffer #131: + time = 1000002621000 + data = -652325514 + buffer #132: + time = 1000002641000 + data = 1604795863 + buffer #133: + time = 1000002661000 + data = -269114601 + buffer #134: + time = 1000002681000 + data = -245362327 + buffer #135: + time = 1000002701000 + data = -1845456361 + buffer #136: + time = 1000002721000 + data = 1641596033 diff --git a/libraries/test_data/src/test/assets/audiosinkdumps/mka/bear-opus.mka.audiosink.dump b/libraries/test_data/src/test/assets/audiosinkdumps/mka/bear-opus.mka.audiosink.dump new file mode 100644 index 00000000000..898ac3e5bb7 --- /dev/null +++ b/libraries/test_data/src/test/assets/audiosinkdumps/mka/bear-opus.mka.audiosink.dump @@ -0,0 +1,418 @@ +AudioSink: + buffer count = 137 + discontinuity: + config: + pcmEncoding = 2 + channelCount = 2 + sampleRate = 48000 + buffer #0: + time = 1000000000000 + data = 461391165 + buffer #1: + time = 1000000021000 + data = -1494234631 + buffer #2: + time = 1000000041000 + data = -1348054745 + buffer #3: + time = 1000000061000 + data = -1758505301 + buffer #4: + time = 1000000081000 + data = 1366089079 + buffer #5: + time = 1000000101000 + data = -1953302292 + buffer #6: + time = 1000000121000 + data = 753127127 + buffer #7: + time = 1000000141000 + data = 1292510747 + buffer #8: + time = 1000000161000 + data = 1760183507 + buffer #9: + time = 1000000181000 + data = -612797173 + buffer #10: + time = 1000000201000 + data = 1191417243 + buffer #11: + time = 1000000221000 + data = 306938793 + buffer #12: + time = 1000000241000 + data = -1805059003 + buffer #13: + time = 1000000261000 + data = -1244408253 + buffer #14: + time = 1000000281000 + data = 1849714991 + buffer #15: + time = 1000000301000 + data = 1434909193 + buffer #16: + time = 1000000321000 + data = 1295410777 + buffer #17: + time = 1000000341000 + data = 798387017 + buffer #18: + time = 1000000361000 + data = -1842500139 + buffer #19: + time = 1000000381000 + data = -537558975 + buffer #20: + time = 1000000401000 + data = -865314001 + buffer #21: + time = 1000000421000 + data = -1228907283 + buffer #22: + time = 1000000441000 + data = 405402534 + buffer #23: + time = 1000000461000 + data = -48148804 + buffer #24: + time = 1000000481000 + data = 316203935 + buffer #25: + time = 1000000501000 + data = 1569875061 + buffer #26: + time = 1000000521000 + data = -577923263 + buffer #27: + time = 1000000541000 + data = 1253991191 + buffer #28: + time = 1000000561000 + data = -1919619915 + buffer #29: + time = 1000000581000 + data = -528210197 + buffer #30: + time = 1000000601000 + data = -593003471 + buffer #31: + time = 1000000621000 + data = -346269411 + buffer #32: + time = 1000000641000 + data = 1722538477 + buffer #33: + time = 1000000661000 + data = 65346303 + buffer #34: + time = 1000000681000 + data = 674665393 + buffer #35: + time = 1000000701000 + data = 484371033 + buffer #36: + time = 1000000721000 + data = 1939490371 + buffer #37: + time = 1000000741000 + data = -956998781 + buffer #38: + time = 1000000761000 + data = 505868187 + buffer #39: + time = 1000000781000 + data = -655354697 + buffer #40: + time = 1000000801000 + data = 969158001 + buffer #41: + time = 1000000821000 + data = 88027563 + buffer #42: + time = 1000000841000 + data = -27892467 + buffer #43: + time = 1000000861000 + data = 293575265 + buffer #44: + time = 1000000881000 + data = -448672637 + buffer #45: + time = 1000000901000 + data = -1334913343 + buffer #46: + time = 1000000921000 + data = 222694541 + buffer #47: + time = 1000000941000 + data = -684016193 + buffer #48: + time = 1000000961000 + data = 1117082881 + buffer #49: + time = 1000000981000 + data = -501258253 + buffer #50: + time = 1000001001000 + data = -758352901 + buffer #51: + time = 1000001021000 + data = -1029798287 + buffer #52: + time = 1000001041000 + data = 1034158153 + buffer #53: + time = 1000001061000 + data = -1738847863 + buffer #54: + time = 1000001081000 + data = 916932341 + buffer #55: + time = 1000001101000 + data = 2014170363 + buffer #56: + time = 1000001121000 + data = 1137704245 + buffer #57: + time = 1000001141000 + data = -1130311423 + buffer #58: + time = 1000001161000 + data = 839607413 + buffer #59: + time = 1000001181000 + data = -112583739 + buffer #60: + time = 1000001201000 + data = -1650310917 + buffer #61: + time = 1000001221000 + data = 1941827263 + buffer #62: + time = 1000001241000 + data = 319651573 + buffer #63: + time = 1000001261000 + data = 60654423 + buffer #64: + time = 1000001281000 + data = -537622393 + buffer #65: + time = 1000001301000 + data = -870383681 + buffer #66: + time = 1000001321000 + data = 133623087 + buffer #67: + time = 1000001341000 + data = 1834968703 + buffer #68: + time = 1000001361000 + data = 1246178931 + buffer #69: + time = 1000001381000 + data = -894780345 + buffer #70: + time = 1000001401000 + data = 728460994 + buffer #71: + time = 1000001421000 + data = -766920809 + buffer #72: + time = 1000001441000 + data = -1367786341 + buffer #73: + time = 1000001461000 + data = -1755652579 + buffer #74: + time = 1000001481000 + data = 260449489 + buffer #75: + time = 1000001501000 + data = -1473710797 + buffer #76: + time = 1000001521000 + data = -1190235977 + buffer #77: + time = 1000001541000 + data = 267038741 + buffer #78: + time = 1000001561000 + data = 1141421081 + buffer #79: + time = 1000001581000 + data = -1610907069 + buffer #80: + time = 1000001601000 + data = 618796265 + buffer #81: + time = 1000001621000 + data = -1215656683 + buffer #82: + time = 1000001641000 + data = -1114458459 + buffer #83: + time = 1000001661000 + data = -1636339315 + buffer #84: + time = 1000001681000 + data = 64202531 + buffer #85: + time = 1000001701000 + data = 962072159 + buffer #86: + time = 1000001721000 + data = 1465578491 + buffer #87: + time = 1000001741000 + data = 763913335 + buffer #88: + time = 1000001761000 + data = -1776945453 + buffer #89: + time = 1000001781000 + data = 1963578515 + buffer #90: + time = 1000001801000 + data = 1396849729 + buffer #91: + time = 1000001821000 + data = -1757880153 + buffer #92: + time = 1000001841000 + data = -1513072133 + buffer #93: + time = 1000001861000 + data = -825468317 + buffer #94: + time = 1000001881000 + data = -1119517569 + buffer #95: + time = 1000001901000 + data = -1682539351 + buffer #96: + time = 1000001921000 + data = -338936383 + buffer #97: + time = 1000001941000 + data = 640258829 + buffer #98: + time = 1000001961000 + data = 518391013 + buffer #99: + time = 1000001981000 + data = 1113464779 + buffer #100: + time = 1000002001000 + data = 1163161749 + buffer #101: + time = 1000002021000 + data = 1357608283 + buffer #102: + time = 1000002041000 + data = 266681923 + buffer #103: + time = 1000002061000 + data = -1129113563 + buffer #104: + time = 1000002081000 + data = 440062567 + buffer #105: + time = 1000002101000 + data = 1780617875 + buffer #106: + time = 1000002121000 + data = 1016591629 + buffer #107: + time = 1000002141000 + data = 693345049 + buffer #108: + time = 1000002161000 + data = -1351515719 + buffer #109: + time = 1000002181000 + data = -2005668853 + buffer #110: + time = 1000002201000 + data = -1391283515 + buffer #111: + time = 1000002221000 + data = 699543167 + buffer #112: + time = 1000002241000 + data = 968177873 + buffer #113: + time = 1000002261000 + data = 781911753 + buffer #114: + time = 1000002281000 + data = -1748840997 + buffer #115: + time = 1000002301000 + data = 691162133 + buffer #116: + time = 1000002321000 + data = 173373191 + buffer #117: + time = 1000002341000 + data = -1415383261 + buffer #118: + time = 1000002361000 + data = 435979225 + buffer #119: + time = 1000002381000 + data = -1887475753 + buffer #120: + time = 1000002401000 + data = -1656188097 + buffer #121: + time = 1000002421000 + data = -594044985 + buffer #122: + time = 1000002441000 + data = -227823323 + buffer #123: + time = 1000002461000 + data = 491582213 + buffer #124: + time = 1000002481000 + data = 1197541921 + buffer #125: + time = 1000002501000 + data = 1310154681 + buffer #126: + time = 1000002521000 + data = -720743991 + buffer #127: + time = 1000002541000 + data = 1519328143 + buffer #128: + time = 1000002561000 + data = 430216935 + buffer #129: + time = 1000002581000 + data = -174631187 + buffer #130: + time = 1000002601000 + data = -1359584639 + buffer #131: + time = 1000002621000 + data = 1891986822 + buffer #132: + time = 1000002641000 + data = -584811423 + buffer #133: + time = 1000002661000 + data = 387775129 + buffer #134: + time = 1000002681000 + data = -2025905685 + buffer #135: + time = 1000002701000 + data = -984159847 + buffer #136: + time = 1000002721000 + data = 1641596033 diff --git a/libraries/test_data/src/test/assets/audiosinkdumps/mka/opus-5.1.mka.audiosink.dump b/libraries/test_data/src/test/assets/audiosinkdumps/mka/opus-5.1.mka.audiosink.dump new file mode 100644 index 00000000000..c921c9c7bbb --- /dev/null +++ b/libraries/test_data/src/test/assets/audiosinkdumps/mka/opus-5.1.mka.audiosink.dump @@ -0,0 +1,422 @@ +AudioSink: + buffer count = 138 + discontinuity: + config: + pcmEncoding = 2 + channelCount = 6 + sampleRate = 48000 + outputChannels = [0, 2, 1, 5, 3, 4] + buffer #0: + time = 1000000000000 + data = 376017869 + buffer #1: + time = 1000000021000 + data = -1501081867 + buffer #2: + time = 1000000041000 + data = -1886525659 + buffer #3: + time = 1000000061000 + data = 1927220572 + buffer #4: + time = 1000000081000 + data = 1788008940 + buffer #5: + time = 1000000101000 + data = -15902575 + buffer #6: + time = 1000000121000 + data = -1301740855 + buffer #7: + time = 1000000141000 + data = 621832609 + buffer #8: + time = 1000000161000 + data = -1588303803 + buffer #9: + time = 1000000181000 + data = 423082548 + buffer #10: + time = 1000000201000 + data = 808505936 + buffer #11: + time = 1000000221000 + data = -1092493157 + buffer #12: + time = 1000000241000 + data = -725659694 + buffer #13: + time = 1000000261000 + data = -722218981 + buffer #14: + time = 1000000281000 + data = 280616064 + buffer #15: + time = 1000000301000 + data = 1182192471 + buffer #16: + time = 1000000321000 + data = 375143304 + buffer #17: + time = 1000000341000 + data = -474611788 + buffer #18: + time = 1000000361000 + data = 315949873 + buffer #19: + time = 1000000381000 + data = -1751860033 + buffer #20: + time = 1000000401000 + data = -2141575433 + buffer #21: + time = 1000000421000 + data = -1759699799 + buffer #22: + time = 1000000441000 + data = -1006359333 + buffer #23: + time = 1000000461000 + data = -243379314 + buffer #24: + time = 1000000481000 + data = -1627306664 + buffer #25: + time = 1000000501000 + data = -757395606 + buffer #26: + time = 1000000521000 + data = -903517963 + buffer #27: + time = 1000000541000 + data = 758333744 + buffer #28: + time = 1000000561000 + data = -353919780 + buffer #29: + time = 1000000581000 + data = 1573994512 + buffer #30: + time = 1000000601000 + data = 454984797 + buffer #31: + time = 1000000621000 + data = 121370022 + buffer #32: + time = 1000000641000 + data = -1549807559 + buffer #33: + time = 1000000661000 + data = -660414046 + buffer #34: + time = 1000000681000 + data = -2068819284 + buffer #35: + time = 1000000701000 + data = -1759557231 + buffer #36: + time = 1000000721000 + data = -216211463 + buffer #37: + time = 1000000741000 + data = -270655305 + buffer #38: + time = 1000000761000 + data = 1904218932 + buffer #39: + time = 1000000781000 + data = -457511627 + buffer #40: + time = 1000000801000 + data = -916250571 + buffer #41: + time = 1000000821000 + data = -1352402544 + buffer #42: + time = 1000000841000 + data = -1406715357 + buffer #43: + time = 1000000861000 + data = -160423302 + buffer #44: + time = 1000000881000 + data = -562315050 + buffer #45: + time = 1000000901000 + data = -1285137896 + buffer #46: + time = 1000000921000 + data = 967514144 + buffer #47: + time = 1000000941000 + data = -443593130 + buffer #48: + time = 1000000961000 + data = -2053337994 + buffer #49: + time = 1000000981000 + data = 1306897911 + buffer #50: + time = 1000001001000 + data = -629261608 + buffer #51: + time = 1000001021000 + data = -197988143 + buffer #52: + time = 1000001041000 + data = 1951060329 + buffer #53: + time = 1000001061000 + data = 1516494919 + buffer #54: + time = 1000001081000 + data = 1742589018 + buffer #55: + time = 1000001101000 + data = 1121562002 + buffer #56: + time = 1000001121000 + data = -1596344281 + buffer #57: + time = 1000001141000 + data = -969305045 + buffer #58: + time = 1000001161000 + data = 364275722 + buffer #59: + time = 1000001181000 + data = -233188688 + buffer #60: + time = 1000001201000 + data = -1021462703 + buffer #61: + time = 1000001221000 + data = 1064140860 + buffer #62: + time = 1000001241000 + data = -236898679 + buffer #63: + time = 1000001261000 + data = -359764648 + buffer #64: + time = 1000001281000 + data = -1723302464 + buffer #65: + time = 1000001301000 + data = 2076862288 + buffer #66: + time = 1000001321000 + data = 2015097443 + buffer #67: + time = 1000001341000 + data = -955703828 + buffer #68: + time = 1000001361000 + data = 1573244659 + buffer #69: + time = 1000001381000 + data = -1421036943 + buffer #70: + time = 1000001401000 + data = 1938324900 + buffer #71: + time = 1000001421000 + data = 1088878684 + buffer #72: + time = 1000001441000 + data = 1597579555 + buffer #73: + time = 1000001461000 + data = 1497574278 + buffer #74: + time = 1000001481000 + data = -1756604247 + buffer #75: + time = 1000001501000 + data = 368515147 + buffer #76: + time = 1000001521000 + data = 512395852 + buffer #77: + time = 1000001541000 + data = 564365812 + buffer #78: + time = 1000001561000 + data = 1873249477 + buffer #79: + time = 1000001581000 + data = -1781707030 + buffer #80: + time = 1000001601000 + data = 1012903106 + buffer #81: + time = 1000001621000 + data = -1092012755 + buffer #82: + time = 1000001641000 + data = 952876824 + buffer #83: + time = 1000001661000 + data = -1424480890 + buffer #84: + time = 1000001681000 + data = 1120937431 + buffer #85: + time = 1000001701000 + data = -1626344703 + buffer #86: + time = 1000001721000 + data = 1882664532 + buffer #87: + time = 1000001741000 + data = -1175892393 + buffer #88: + time = 1000001761000 + data = 2077583079 + buffer #89: + time = 1000001781000 + data = -581217660 + buffer #90: + time = 1000001801000 + data = 377904743 + buffer #91: + time = 1000001821000 + data = -1084595157 + buffer #92: + time = 1000001841000 + data = 1289312847 + buffer #93: + time = 1000001861000 + data = 318127398 + buffer #94: + time = 1000001881000 + data = -1054665983 + buffer #95: + time = 1000001901000 + data = 1311800220 + buffer #96: + time = 1000001921000 + data = 1083373864 + buffer #97: + time = 1000001941000 + data = -1575279712 + buffer #98: + time = 1000001961000 + data = 1903786940 + buffer #99: + time = 1000001981000 + data = 968132978 + buffer #100: + time = 1000002001000 + data = 1732190865 + buffer #101: + time = 1000002021000 + data = 1820905719 + buffer #102: + time = 1000002041000 + data = 377136640 + buffer #103: + time = 1000002061000 + data = -461752511 + buffer #104: + time = 1000002081000 + data = -1669510266 + buffer #105: + time = 1000002101000 + data = 399842824 + buffer #106: + time = 1000002121000 + data = 939150450 + buffer #107: + time = 1000002141000 + data = -739412407 + buffer #108: + time = 1000002161000 + data = -1094682025 + buffer #109: + time = 1000002181000 + data = 1243234514 + buffer #110: + time = 1000002201000 + data = -299900960 + buffer #111: + time = 1000002221000 + data = 1491665369 + buffer #112: + time = 1000002241000 + data = 195073085 + buffer #113: + time = 1000002261000 + data = -1719454940 + buffer #114: + time = 1000002281000 + data = -744492884 + buffer #115: + time = 1000002301000 + data = 821067246 + buffer #116: + time = 1000002321000 + data = -1434851338 + buffer #117: + time = 1000002341000 + data = 779094816 + buffer #118: + time = 1000002361000 + data = -330715311 + buffer #119: + time = 1000002381000 + data = 1225236580 + buffer #120: + time = 1000002401000 + data = 1592040991 + buffer #121: + time = 1000002421000 + data = -996563326 + buffer #122: + time = 1000002441000 + data = -494589605 + buffer #123: + time = 1000002461000 + data = -1330262588 + buffer #124: + time = 1000002481000 + data = -1486074683 + buffer #125: + time = 1000002501000 + data = 484577868 + buffer #126: + time = 1000002521000 + data = 273883133 + buffer #127: + time = 1000002541000 + data = -11420506 + buffer #128: + time = 1000002561000 + data = 1904154495 + buffer #129: + time = 1000002581000 + data = 516576999 + buffer #130: + time = 1000002601000 + data = 845202278 + buffer #131: + time = 1000002621000 + data = 178229514 + buffer #132: + time = 1000002641000 + data = 153624742 + buffer #133: + time = 1000002661000 + data = -26049833 + buffer #134: + time = 1000002681000 + data = -1951469655 + buffer #135: + time = 1000002701000 + data = 1564577937 + buffer #136: + time = 1000002721000 + data = -660822929 + buffer #137: + time = 1000002741000 + data = -1352825612 diff --git a/libraries/test_data/src/test/assets/media/mka/opus-5.1.mka b/libraries/test_data/src/test/assets/media/mka/opus-5.1.mka new file mode 100644 index 00000000000..2a2adbd5cf9 Binary files /dev/null and b/libraries/test_data/src/test/assets/media/mka/opus-5.1.mka differ diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/CapturingAudioSink.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/CapturingAudioSink.java index c56108e660b..b0285b1516b 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/CapturingAudioSink.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/CapturingAudioSink.java @@ -45,7 +45,10 @@ public void configure(Format inputFormat, int specifiedBufferSize, @Nullable int throws ConfigurationException { interceptedData.add( new DumpableConfiguration( - inputFormat.pcmEncoding, inputFormat.channelCount, inputFormat.sampleRate)); + inputFormat.pcmEncoding, + inputFormat.channelCount, + inputFormat.sampleRate, + outputChannels)); super.configure(inputFormat, specifiedBufferSize, outputChannels); } @@ -103,12 +106,17 @@ private static final class DumpableConfiguration implements Dumper.Dumpable { private final @C.PcmEncoding int inputPcmEncoding; private final int inputChannelCount; private final int inputSampleRate; + @Nullable private final int[] outputChannels; public DumpableConfiguration( - @C.PcmEncoding int inputPcmEncoding, int inputChannelCount, int inputSampleRate) { + @C.PcmEncoding int inputPcmEncoding, + int inputChannelCount, + int inputSampleRate, + @Nullable int[] outputChannels) { this.inputPcmEncoding = inputPcmEncoding; this.inputChannelCount = inputChannelCount; this.inputSampleRate = inputSampleRate; + this.outputChannels = outputChannels; } @Override @@ -117,8 +125,11 @@ public void dump(Dumper dumper) { .startBlock("config") .add("pcmEncoding", inputPcmEncoding) .add("channelCount", inputChannelCount) - .add("sampleRate", inputSampleRate) - .endBlock(); + .add("sampleRate", inputSampleRate); + if (outputChannels != null) { + dumper.add("outputChannels", Arrays.toString(outputChannels)); + } + dumper.endBlock(); } }