diff --git a/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index d4042a99b1..f9a97d961f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -24,6 +24,7 @@ import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableByteArray; +import com.google.android.exoplayer2.util.Util; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -516,7 +517,7 @@ public final class Ac3Util { int endIndex = buffer.limit() - TRUEHD_SYNCFRAME_PREFIX_LENGTH; for (int i = startIndex; i <= endIndex; i++) { // The syncword ends 0xBA for TrueHD or 0xBB for MLP. - if ((buffer.getInt(i + 4) & 0xFEFFFFFF) == 0xBA6F72F8) { + if ((Util.getBigEndianInt(buffer, i + 4) & 0xFFFFFFFE) == 0xF8726FBA) { return i - startIndex; } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java index 60fe1a39d4..6d8ca9e4b5 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -60,6 +60,8 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.math.BigDecimal; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; @@ -1859,6 +1861,21 @@ public final class Util { return initialValue; } + /** + * Absolute get method for reading an int value in {@link ByteOrder#BIG_ENDIAN} in a {@link + * ByteBuffer}. Same as {@link ByteBuffer#getInt(int)} except the buffer's order as returned by + * {@link ByteBuffer#order()} is ignored and {@link ByteOrder#BIG_ENDIAN} is used instead. + * + * @param buffer The buffer from which to read an int in big endian. + * @param index The index from which the bytes will be read. + * @return The int value at the given index with the buffer bytes ordered most significant to + * least significant. + */ + public static int getBigEndianInt(ByteBuffer buffer, int index) { + int value = buffer.getInt(index); + return buffer.order() == ByteOrder.BIG_ENDIAN ? value : Integer.reverseBytes(value); + } + /** * Returns the {@link C.NetworkType} of the current network connection. * diff --git a/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java b/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java index 825988cf48..2e523a32c6 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/util/UtilTest.java @@ -27,6 +27,8 @@ import static com.google.common.truth.Truth.assertThat; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.testutil.TestUtil; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; @@ -789,6 +791,30 @@ public class UtilTest { assertThat(result).isEqualTo(0x4); } + @Test + public void getBigEndianInt_fromBigEndian() { + byte[] bytes = {0x1F, 0x2E, 0x3D, 0x4C}; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); + + assertThat(Util.getBigEndianInt(byteBuffer, 0)).isEqualTo(0x1F2E3D4C); + } + + @Test + public void getBigEndianInt_fromLittleEndian() { + byte[] bytes = {(byte) 0xC2, (byte) 0xD3, (byte) 0xE4, (byte) 0xF5}; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); + + assertThat(Util.getBigEndianInt(byteBuffer, 0)).isEqualTo(0xC2D3E4F5); + } + + @Test + public void getBigEndianInt_unaligned() { + byte[] bytes = {9, 8, 7, 6, 5}; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); + + assertThat(Util.getBigEndianInt(byteBuffer, 1)).isEqualTo(0x08070605); + } + @Test public void inflate_withDeflatedData_success() { byte[] testData = TestUtil.buildTestData(/*arbitrary test data size*/ 256 * 1024); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index a0aebdfe66..78699d41f4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -1242,7 +1242,8 @@ public final class DefaultAudioSink implements AudioSink { private static int getFramesPerEncodedSample(@C.Encoding int encoding, ByteBuffer buffer) { switch (encoding) { case C.ENCODING_MP3: - return MpegAudioUtil.parseMpegAudioFrameSampleCount(buffer.get(buffer.position())); + int headerDataInBigEndian = Util.getBigEndianInt(buffer, buffer.position()); + return MpegAudioUtil.parseMpegAudioFrameSampleCount(headerDataInBigEndian); case C.ENCODING_AAC_LC: return AacUtil.AAC_LC_AUDIO_SAMPLE_COUNT; case C.ENCODING_AAC_HE_V1: