diff --git a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java index a29aeb68ae..e8eaf641eb 100644 --- a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java +++ b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java @@ -136,7 +136,7 @@ public final class FfmpegAudioRenderer extends DecoderAudioRenderer { .setSampleMimeType(MimeTypes.AUDIO_RAW) .setChannelCount(decoder.getChannelCount()) .setSampleRate(decoder.getSampleRate()) - .setEncoding(decoder.getEncoding()) + .setPcmEncoding(decoder.getEncoding()) .build(); } diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java index 1d6ba75ce8..615b60c3e7 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java @@ -279,7 +279,7 @@ public final class FlacExtractor implements Extractor { .setMaxInputSize(streamMetadata.getMaxDecodedFrameSize()) .setChannelCount(streamMetadata.channels) .setSampleRate(streamMetadata.sampleRate) - .setEncoding(getPcmEncoding(streamMetadata.bitsPerSample)) + .setPcmEncoding(getPcmEncoding(streamMetadata.bitsPerSample)) .setMetadata(metadata) .build(); output.format(mediaFormat); diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Format.java b/library/common/src/main/java/com/google/android/exoplayer2/Format.java index 749dea28a7..d564b2318e 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Format.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Format.java @@ -96,7 +96,7 @@ import java.util.List; *
Gapless offload is not supported by all devices and there is no API to query its support. As
- * a result this detection is currently based on manual testing. TODO(internal b/158191844): Add
- * an SDK API to query offload gapless support.
+ * @param format The {@link Format}.
+ * @param audioCapabilities The device audio capabilities.
+ * @return The encoding and channel config to use, or {@code null} if passthrough of the format is
+ * unsupported.
*/
- private static boolean isOffloadGaplessSupported() {
- return Util.SDK_INT >= 30 && Util.MODEL.startsWith("Pixel");
- }
+ @Nullable
+ private static Pair Gapless offload is not supported by all devices and there is no API to query its support. As
+ * a result this detection is currently based on manual testing.
+ */
+ // TODO(internal b/158191844): Add an SDK API to query offload gapless support.
+ private static boolean isOffloadedGaplessPlaybackSupported() {
+ return Util.SDK_INT >= 30 && Util.MODEL.startsWith("Pixel");
+ }
+
+ private static boolean isOffloadedPlayback(AudioTrack audioTrack) {
+ return Util.SDK_INT >= 29 && audioTrack.isOffloadedPlayback();
+ }
+
+ private static AudioTrack initializeKeepSessionIdAudioTrack(int audioSessionId) {
+ int sampleRate = 4000; // Equal to private AudioTrack.MIN_SAMPLE_RATE.
+ int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
+ @C.PcmEncoding int encoding = C.ENCODING_PCM_16BIT;
+ int bufferSize = 2; // Use a two byte buffer, as it is not actually used for playback.
+ return new AudioTrack(
+ C.STREAM_TYPE_DEFAULT,
+ sampleRate,
+ channelConfig,
+ encoding,
+ bufferSize,
+ MODE_STATIC,
+ audioSessionId);
+ }
+
private static int getMaximumEncodedRateBytesPerSecond(@C.Encoding int encoding) {
switch (encoding) {
case C.ENCODING_MP3:
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
index 9e3fbe58f1..4af503e845 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
@@ -290,7 +290,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
protected boolean usePassthrough(Format format) {
- return getPassthroughEncoding(format) != C.ENCODING_INVALID;
+ @Nullable String mimeType = format.sampleMimeType;
+ if (MimeTypes.AUDIO_RAW.equals(mimeType)) {
+ // PCM passthrough is not yet supported.
+ return false;
+ }
+ return audioSink.supportsFormat(format);
}
@Override
@@ -345,7 +350,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
return Util.areEqual(oldFormat.sampleMimeType, newFormat.sampleMimeType)
&& oldFormat.channelCount == newFormat.channelCount
&& oldFormat.sampleRate == newFormat.sampleRate
- && oldFormat.encoding == newFormat.encoding
+ && oldFormat.pcmEncoding == newFormat.pcmEncoding
&& oldFormat.initializationDataEquals(newFormat)
&& !MimeTypes.AUDIO_OPUS.equals(oldFormat.sampleMimeType);
}
@@ -394,21 +399,26 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
Format audioSinkInputFormat;
@Nullable int[] channelMap = null;
if (codecPassthroughFormat != null) { // Raw codec passthrough
- audioSinkInputFormat = getFormatWithEncodingForPassthrough(codecPassthroughFormat);
+ audioSinkInputFormat = codecPassthroughFormat;
} else if (getCodec() == null) { // Codec bypass passthrough
- audioSinkInputFormat = getFormatWithEncodingForPassthrough(outputFormat);
+ audioSinkInputFormat = outputFormat;
} else {
MediaFormat mediaFormat = getCodec().getOutputFormat();
@C.PcmEncoding int pcmEncoding;
if (mediaFormat.containsKey(VIVO_BITS_PER_SAMPLE_KEY)) {
pcmEncoding = Util.getPcmEncoding(mediaFormat.getInteger(VIVO_BITS_PER_SAMPLE_KEY));
} else {
- pcmEncoding = getPcmEncoding(outputFormat);
+ // If the format is anything other than PCM then we assume that the audio decoder will
+ // output 16-bit PCM.
+ pcmEncoding =
+ MimeTypes.AUDIO_RAW.equals(outputFormat.sampleMimeType)
+ ? outputFormat.pcmEncoding
+ : C.ENCODING_PCM_16BIT;
}
audioSinkInputFormat =
new Format.Builder()
.setSampleMimeType(MimeTypes.AUDIO_RAW)
- .setEncoding(pcmEncoding)
+ .setPcmEncoding(pcmEncoding)
.setEncoderDelay(outputFormat.encoderDelay)
.setEncoderPadding(outputFormat.encoderPadding)
.setChannelCount(mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT))
@@ -430,45 +440,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
}
- /**
- * Returns the {@link C.Encoding} constant to use for passthrough of the given format, or {@link
- * C#ENCODING_INVALID} if passthrough is not possible.
- *
- * @param format The format for which to get the encoding.
- * @return The {@link C.Encoding} corresponding to the format, or {@link C#ENCODING_INVALID} if
- * the format is not supported.
- */
- @C.Encoding
- protected int getPassthroughEncoding(Format format) {
- @Nullable String mimeType = format.sampleMimeType;
- if (MimeTypes.AUDIO_RAW.equals(mimeType)) {
- // PCM passthrough is not supported.
- return C.ENCODING_INVALID;
- }
- if (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType)) {
- // E-AC3 JOC is object-based so the output channel count is arbitrary.
- Format eAc3JocFormat =
- format
- .buildUpon()
- .setChannelCount(Format.NO_VALUE)
- .setEncoding(C.ENCODING_E_AC3_JOC)
- .build();
- if (audioSink.supportsFormat(eAc3JocFormat)) {
- return C.ENCODING_E_AC3_JOC;
- }
- // E-AC3 receivers can decode JOC streams, but in 2-D rather than 3-D, so try to fall back.
- mimeType = MimeTypes.AUDIO_E_AC3;
- }
-
- @C.Encoding int encoding = MimeTypes.getEncoding(mimeType, format.codecs);
- Format passthroughFormat = format.buildUpon().setEncoding(encoding).build();
- if (audioSink.supportsFormat(passthroughFormat)) {
- return encoding;
- } else {
- return C.ENCODING_INVALID;
- }
- }
-
/**
* Called when the audio session id becomes known. The default implementation is a no-op. One
* reason for overriding this method would be to instantiate and enable a {@link Virtualizer} in
@@ -782,13 +753,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
}
- private Format getFormatWithEncodingForPassthrough(Format outputFormat) {
- @C.Encoding int passthroughEncoding = getPassthroughEncoding(outputFormat);
- // TODO(b/112299307): Passthrough can have become unavailable since usePassthrough was called.
- Assertions.checkState(passthroughEncoding != C.ENCODING_INVALID);
- return outputFormat.buildUpon().setEncoding(passthroughEncoding).build();
- }
-
/**
* Returns whether the device's decoders are known to not support setting the codec operating
* rate.
@@ -832,15 +796,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|| Util.DEVICE.startsWith("ms01"));
}
- @C.PcmEncoding
- private static int getPcmEncoding(Format format) {
- // If the format is anything other than PCM then we assume that the audio decoder will output
- // 16-bit PCM.
- return MimeTypes.AUDIO_RAW.equals(format.sampleMimeType)
- ? format.encoding
- : C.ENCODING_PCM_16BIT;
- }
-
private final class AudioSinkListener implements AudioSink.Listener {
@Override
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java
index 535e917299..f392e770bd 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java
@@ -88,7 +88,7 @@ public final class SilenceMediaSource extends BaseMediaSource {
.setSampleMimeType(MimeTypes.AUDIO_RAW)
.setChannelCount(CHANNEL_COUNT)
.setSampleRate(SAMPLE_RATE_HZ)
- .setEncoding(PCM_ENCODING)
+ .setPcmEncoding(PCM_ENCODING)
.build();
private static final MediaItem MEDIA_ITEM =
new MediaItem.Builder()
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java
index b64b14e501..e42ec07837 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java
@@ -24,6 +24,7 @@ import static org.robolectric.annotation.Config.TARGET_SDK;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.util.MimeTypes;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
@@ -213,7 +214,12 @@ public final class DefaultAudioSinkTest {
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
new AudioProcessor[0],
/* enableFloatOutput= */ false);
- Format floatFormat = STEREO_44_1_FORMAT.buildUpon().setEncoding(C.ENCODING_PCM_FLOAT).build();
+ Format floatFormat =
+ STEREO_44_1_FORMAT
+ .buildUpon()
+ .setSampleMimeType(MimeTypes.AUDIO_RAW)
+ .setPcmEncoding(C.ENCODING_PCM_FLOAT)
+ .build();
assertThat(defaultAudioSink.getFormatSupport(floatFormat))
.isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING);
}
@@ -226,7 +232,12 @@ public final class DefaultAudioSinkTest {
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
new AudioProcessor[0],
/* enableFloatOutput= */ true);
- Format floatFormat = STEREO_44_1_FORMAT.buildUpon().setEncoding(C.ENCODING_PCM_FLOAT).build();
+ Format floatFormat =
+ STEREO_44_1_FORMAT
+ .buildUpon()
+ .setSampleMimeType(MimeTypes.AUDIO_RAW)
+ .setPcmEncoding(C.ENCODING_PCM_FLOAT)
+ .build();
assertThat(defaultAudioSink.getFormatSupport(floatFormat))
.isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING);
}
@@ -239,14 +250,24 @@ public final class DefaultAudioSinkTest {
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
new AudioProcessor[0],
/* enableFloatOutput= */ true);
- Format floatFormat = STEREO_44_1_FORMAT.buildUpon().setEncoding(C.ENCODING_PCM_FLOAT).build();
+ Format floatFormat =
+ STEREO_44_1_FORMAT
+ .buildUpon()
+ .setSampleMimeType(MimeTypes.AUDIO_RAW)
+ .setPcmEncoding(C.ENCODING_PCM_FLOAT)
+ .build();
assertThat(defaultAudioSink.getFormatSupport(floatFormat))
.isEqualTo(SINK_FORMAT_SUPPORTED_DIRECTLY);
}
@Test
public void supportsFloatPcm() {
- Format floatFormat = STEREO_44_1_FORMAT.buildUpon().setEncoding(C.ENCODING_PCM_FLOAT).build();
+ Format floatFormat =
+ STEREO_44_1_FORMAT
+ .buildUpon()
+ .setSampleMimeType(MimeTypes.AUDIO_RAW)
+ .setPcmEncoding(C.ENCODING_PCM_FLOAT)
+ .build();
assertThat(defaultAudioSink.supportsFormat(floatFormat)).isTrue();
}
@@ -255,7 +276,12 @@ public final class DefaultAudioSinkTest {
DefaultAudioSink defaultAudioSink =
new DefaultAudioSink(
new AudioCapabilities(new int[] {C.ENCODING_AAC_LC}, 2), new AudioProcessor[0]);
- Format aacLcFormat = STEREO_44_1_FORMAT.buildUpon().setEncoding(C.ENCODING_AAC_LC).build();
+ Format aacLcFormat =
+ STEREO_44_1_FORMAT
+ .buildUpon()
+ .setSampleMimeType(MimeTypes.AUDIO_AAC)
+ .setPcmEncoding(C.ENCODING_AAC_LC)
+ .build();
assertThat(defaultAudioSink.supportsFormat(aacLcFormat)).isFalse();
}
@@ -267,7 +293,8 @@ public final class DefaultAudioSinkTest {
throws AudioSink.ConfigurationException {
Format format =
new Format.Builder()
- .setEncoding(C.ENCODING_PCM_16BIT)
+ .setSampleMimeType(MimeTypes.AUDIO_RAW)
+ .setPcmEncoding(C.ENCODING_PCM_16BIT)
.setChannelCount(channelCount)
.setSampleRate(SAMPLE_RATE_44_1)
.setEncoderDelay(trimStartFrames)
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java
index 081b591b1f..305cb5b54e 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java
@@ -56,7 +56,7 @@ public class MediaCodecAudioRendererTest {
private static final Format AUDIO_AAC =
new Format.Builder()
.setSampleMimeType(MimeTypes.AUDIO_AAC)
- .setEncoding(C.ENCODING_PCM_16BIT)
+ .setPcmEncoding(C.ENCODING_PCM_16BIT)
.setChannelCount(2)
.setSampleRate(44100)
.setEncoderDelay(100)
@@ -274,7 +274,7 @@ public class MediaCodecAudioRendererTest {
private static Format getAudioSinkFormat(Format inputFormat) {
return new Format.Builder()
.setSampleMimeType(MimeTypes.AUDIO_RAW)
- .setEncoding(C.ENCODING_PCM_16BIT)
+ .setPcmEncoding(C.ENCODING_PCM_16BIT)
.setChannelCount(inputFormat.channelCount)
.setSampleRate(inputFormat.sampleRate)
.setEncoderDelay(inputFormat.encoderDelay)
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/C2Mp3TimestampTrackerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/C2Mp3TimestampTrackerTest.java
index ca5ba9a878..1108b882e4 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/C2Mp3TimestampTrackerTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/C2Mp3TimestampTrackerTest.java
@@ -18,7 +18,6 @@ package com.google.android.exoplayer2.mediacodec;
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.Format;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.util.MimeTypes;
@@ -34,7 +33,6 @@ public final class C2Mp3TimestampTrackerTest {
private static final Format AUDIO_MP3 =
new Format.Builder()
.setSampleMimeType(MimeTypes.AUDIO_MPEG)
- .setEncoding(C.ENCODING_PCM_16BIT)
.setChannelCount(2)
.setSampleRate(44_100)
.build();
diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
index f566493ada..0d3965321c 100644
--- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
+++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
@@ -2098,7 +2098,7 @@ public class MatroskaExtractor implements Extractor {
formatBuilder
.setChannelCount(channelCount)
.setSampleRate(sampleRate)
- .setEncoding(pcmEncoding);
+ .setPcmEncoding(pcmEncoding);
} else if (MimeTypes.isVideo(mimeType)) {
type = C.TRACK_TYPE_VIDEO;
if (displayUnit == Track.DISPLAY_UNIT_PIXELS) {
diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
index de2f4b5d9b..1593b90bea 100644
--- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
+++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
@@ -404,7 +404,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
chunkOffsetsBytes[chunkIterator.index] = chunkIterator.offset;
chunkSampleCounts[chunkIterator.index] = chunkIterator.numSamples;
}
- int fixedSampleSize = Util.getPcmFrameSize(track.format.encoding, track.format.channelCount);
+ int fixedSampleSize =
+ Util.getPcmFrameSize(track.format.pcmEncoding, track.format.channelCount);
FixedSampleSizeRechunker.Results rechunkedResults =
FixedSampleSizeRechunker.rechunk(
fixedSampleSize, chunkOffsetsBytes, chunkSampleCounts, timestampDeltaInTimeUnits);
@@ -1325,7 +1326,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
.setCodecs(codecs)
.setChannelCount(channelCount)
.setSampleRate(sampleRate)
- .setEncoding(pcmEncoding)
+ .setPcmEncoding(pcmEncoding)
.setInitializationData(
initializationData == null ? null : Collections.singletonList(initializationData))
.setDrmInitData(drmInitData)
diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java
index ffd5a19e0d..1d7b6b9c6e 100644
--- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java
+++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java
@@ -231,7 +231,7 @@ public final class WavExtractor implements Extractor {
.setMaxInputSize(targetSampleSizeBytes)
.setChannelCount(header.numChannels)
.setSampleRate(header.frameRateHz)
- .setEncoding(pcmEncoding)
+ .setPcmEncoding(pcmEncoding)
.build();
}
@@ -373,7 +373,7 @@ public final class WavExtractor implements Extractor {
.setMaxInputSize(numOutputFramesToBytes(targetSampleSizeFrames, numChannels))
.setChannelCount(header.numChannels)
.setSampleRate(header.frameRateHz)
- .setEncoding(C.ENCODING_PCM_16BIT)
+ .setPcmEncoding(C.ENCODING_PCM_16BIT)
.build();
}
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java
index 3ea2211ac2..ead5bd24d9 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java
@@ -57,7 +57,7 @@ public final class CapturingAudioSink extends ForwardingAudioSink implements Dum
throws ConfigurationException {
interceptedData.add(
new DumpableConfiguration(
- inputFormat.encoding, inputFormat.channelCount, inputFormat.sampleRate));
+ inputFormat.pcmEncoding, inputFormat.channelCount, inputFormat.sampleRate));
super.configure(inputFormat, specifiedBufferSize, outputChannels);
}