Revert Format back to only containing audio encoding for PCM
PiperOrigin-RevId: 322683545
This commit is contained in:
parent
92029ed0ad
commit
6d92eebe51
@ -136,7 +136,7 @@ public final class FfmpegAudioRenderer extends DecoderAudioRenderer {
|
|||||||
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
||||||
.setChannelCount(decoder.getChannelCount())
|
.setChannelCount(decoder.getChannelCount())
|
||||||
.setSampleRate(decoder.getSampleRate())
|
.setSampleRate(decoder.getSampleRate())
|
||||||
.setEncoding(decoder.getEncoding())
|
.setPcmEncoding(decoder.getEncoding())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
.setMaxInputSize(streamMetadata.getMaxDecodedFrameSize())
|
.setMaxInputSize(streamMetadata.getMaxDecodedFrameSize())
|
||||||
.setChannelCount(streamMetadata.channels)
|
.setChannelCount(streamMetadata.channels)
|
||||||
.setSampleRate(streamMetadata.sampleRate)
|
.setSampleRate(streamMetadata.sampleRate)
|
||||||
.setEncoding(getPcmEncoding(streamMetadata.bitsPerSample))
|
.setPcmEncoding(getPcmEncoding(streamMetadata.bitsPerSample))
|
||||||
.setMetadata(metadata)
|
.setMetadata(metadata)
|
||||||
.build();
|
.build();
|
||||||
output.format(mediaFormat);
|
output.format(mediaFormat);
|
||||||
|
@ -96,7 +96,7 @@ import java.util.List;
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #channelCount}
|
* <li>{@link #channelCount}
|
||||||
* <li>{@link #sampleRate}
|
* <li>{@link #sampleRate}
|
||||||
* <li>{@link #encoding}
|
* <li>{@link #pcmEncoding}
|
||||||
* <li>{@link #encoderDelay}
|
* <li>{@link #encoderDelay}
|
||||||
* <li>{@link #encoderPadding}
|
* <li>{@link #encoderPadding}
|
||||||
* </ul>
|
* </ul>
|
||||||
@ -157,7 +157,7 @@ public final class Format implements Parcelable {
|
|||||||
|
|
||||||
private int channelCount;
|
private int channelCount;
|
||||||
private int sampleRate;
|
private int sampleRate;
|
||||||
@C.Encoding private int encoding;
|
@C.PcmEncoding private int pcmEncoding;
|
||||||
private int encoderDelay;
|
private int encoderDelay;
|
||||||
private int encoderPadding;
|
private int encoderPadding;
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
channelCount = NO_VALUE;
|
channelCount = NO_VALUE;
|
||||||
sampleRate = NO_VALUE;
|
sampleRate = NO_VALUE;
|
||||||
encoding = NO_VALUE;
|
pcmEncoding = NO_VALUE;
|
||||||
// Text specific.
|
// Text specific.
|
||||||
accessibilityChannel = NO_VALUE;
|
accessibilityChannel = NO_VALUE;
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
this.channelCount = format.channelCount;
|
this.channelCount = format.channelCount;
|
||||||
this.sampleRate = format.sampleRate;
|
this.sampleRate = format.sampleRate;
|
||||||
this.encoding = format.encoding;
|
this.pcmEncoding = format.pcmEncoding;
|
||||||
this.encoderDelay = format.encoderDelay;
|
this.encoderDelay = format.encoderDelay;
|
||||||
this.encoderPadding = format.encoderPadding;
|
this.encoderPadding = format.encoderPadding;
|
||||||
// Text specific.
|
// Text specific.
|
||||||
@ -530,13 +530,13 @@ public final class Format implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets {@link Format#encoding}. The default value is {@link #NO_VALUE}.
|
* Sets {@link Format#pcmEncoding}. The default value is {@link #NO_VALUE}.
|
||||||
*
|
*
|
||||||
* @param encoding The {@link Format#encoding}.
|
* @param pcmEncoding The {@link Format#pcmEncoding}.
|
||||||
* @return The builder.
|
* @return The builder.
|
||||||
*/
|
*/
|
||||||
public Builder setEncoding(@C.Encoding int encoding) {
|
public Builder setPcmEncoding(@C.PcmEncoding int pcmEncoding) {
|
||||||
this.encoding = encoding;
|
this.pcmEncoding = pcmEncoding;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,7 +618,7 @@ public final class Format implements Parcelable {
|
|||||||
colorInfo,
|
colorInfo,
|
||||||
channelCount,
|
channelCount,
|
||||||
sampleRate,
|
sampleRate,
|
||||||
encoding,
|
pcmEncoding,
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
accessibilityChannel,
|
accessibilityChannel,
|
||||||
@ -769,8 +769,6 @@ public final class Format implements Parcelable {
|
|||||||
public final int sampleRate;
|
public final int sampleRate;
|
||||||
/** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */
|
/** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */
|
||||||
@C.PcmEncoding public final int pcmEncoding;
|
@C.PcmEncoding public final int pcmEncoding;
|
||||||
/** The {@link C.Encoding} for audio. Set to {@link #NO_VALUE} for other media types. */
|
|
||||||
@C.Encoding public final int encoding;
|
|
||||||
/**
|
/**
|
||||||
* The number of frames to trim from the start of the decoded audio stream, or 0 if not
|
* The number of frames to trim from the start of the decoded audio stream, or 0 if not
|
||||||
* applicable.
|
* applicable.
|
||||||
@ -1008,7 +1006,7 @@ public final class Format implements Parcelable {
|
|||||||
int maxInputSize,
|
int maxInputSize,
|
||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
@C.Encoding int encoding,
|
@C.PcmEncoding int pcmEncoding,
|
||||||
@Nullable List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
@ -1026,7 +1024,7 @@ public final class Format implements Parcelable {
|
|||||||
.setDrmInitData(drmInitData)
|
.setDrmInitData(drmInitData)
|
||||||
.setChannelCount(channelCount)
|
.setChannelCount(channelCount)
|
||||||
.setSampleRate(sampleRate)
|
.setSampleRate(sampleRate)
|
||||||
.setEncoding(encoding)
|
.setPcmEncoding(pcmEncoding)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,7 +1038,7 @@ public final class Format implements Parcelable {
|
|||||||
int maxInputSize,
|
int maxInputSize,
|
||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
@C.Encoding int encoding,
|
@C.PcmEncoding int pcmEncoding,
|
||||||
int encoderDelay,
|
int encoderDelay,
|
||||||
int encoderPadding,
|
int encoderPadding,
|
||||||
@Nullable List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@ -1062,7 +1060,7 @@ public final class Format implements Parcelable {
|
|||||||
.setDrmInitData(drmInitData)
|
.setDrmInitData(drmInitData)
|
||||||
.setChannelCount(channelCount)
|
.setChannelCount(channelCount)
|
||||||
.setSampleRate(sampleRate)
|
.setSampleRate(sampleRate)
|
||||||
.setEncoding(encoding)
|
.setPcmEncoding(pcmEncoding)
|
||||||
.setEncoderDelay(encoderDelay)
|
.setEncoderDelay(encoderDelay)
|
||||||
.setEncoderPadding(encoderPadding)
|
.setEncoderPadding(encoderPadding)
|
||||||
.build();
|
.build();
|
||||||
@ -1244,7 +1242,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
@C.Encoding int encoding,
|
@C.PcmEncoding int pcmEncoding,
|
||||||
int encoderDelay,
|
int encoderDelay,
|
||||||
int encoderPadding,
|
int encoderPadding,
|
||||||
// Text specific.
|
// Text specific.
|
||||||
@ -1282,8 +1280,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
this.channelCount = channelCount;
|
this.channelCount = channelCount;
|
||||||
this.sampleRate = sampleRate;
|
this.sampleRate = sampleRate;
|
||||||
this.encoding = encoding;
|
this.pcmEncoding = pcmEncoding;
|
||||||
this.pcmEncoding = toPcmEncoding(encoding);
|
|
||||||
this.encoderDelay = encoderDelay == NO_VALUE ? 0 : encoderDelay;
|
this.encoderDelay = encoderDelay == NO_VALUE ? 0 : encoderDelay;
|
||||||
this.encoderPadding = encoderPadding == NO_VALUE ? 0 : encoderPadding;
|
this.encoderPadding = encoderPadding == NO_VALUE ? 0 : encoderPadding;
|
||||||
// Text specific.
|
// Text specific.
|
||||||
@ -1337,8 +1334,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
channelCount = in.readInt();
|
channelCount = in.readInt();
|
||||||
sampleRate = in.readInt();
|
sampleRate = in.readInt();
|
||||||
encoding = in.readInt();
|
pcmEncoding = in.readInt();
|
||||||
pcmEncoding = toPcmEncoding(encoding);
|
|
||||||
encoderDelay = in.readInt();
|
encoderDelay = in.readInt();
|
||||||
encoderPadding = in.readInt();
|
encoderPadding = in.readInt();
|
||||||
// Text specific.
|
// Text specific.
|
||||||
@ -1569,7 +1565,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
result = 31 * result + channelCount;
|
result = 31 * result + channelCount;
|
||||||
result = 31 * result + sampleRate;
|
result = 31 * result + sampleRate;
|
||||||
result = 31 * result + encoding;
|
result = 31 * result + pcmEncoding;
|
||||||
result = 31 * result + encoderDelay;
|
result = 31 * result + encoderDelay;
|
||||||
result = 31 * result + encoderPadding;
|
result = 31 * result + encoderPadding;
|
||||||
// Text specific.
|
// Text specific.
|
||||||
@ -1606,7 +1602,7 @@ public final class Format implements Parcelable {
|
|||||||
&& stereoMode == other.stereoMode
|
&& stereoMode == other.stereoMode
|
||||||
&& channelCount == other.channelCount
|
&& channelCount == other.channelCount
|
||||||
&& sampleRate == other.sampleRate
|
&& sampleRate == other.sampleRate
|
||||||
&& encoding == other.encoding
|
&& pcmEncoding == other.pcmEncoding
|
||||||
&& encoderDelay == other.encoderDelay
|
&& encoderDelay == other.encoderDelay
|
||||||
&& encoderPadding == other.encoderPadding
|
&& encoderPadding == other.encoderPadding
|
||||||
&& accessibilityChannel == other.accessibilityChannel
|
&& accessibilityChannel == other.accessibilityChannel
|
||||||
@ -1727,7 +1723,7 @@ public final class Format implements Parcelable {
|
|||||||
// Audio specific.
|
// Audio specific.
|
||||||
dest.writeInt(channelCount);
|
dest.writeInt(channelCount);
|
||||||
dest.writeInt(sampleRate);
|
dest.writeInt(sampleRate);
|
||||||
dest.writeInt(encoding);
|
dest.writeInt(pcmEncoding);
|
||||||
dest.writeInt(encoderDelay);
|
dest.writeInt(encoderDelay);
|
||||||
dest.writeInt(encoderPadding);
|
dest.writeInt(encoderPadding);
|
||||||
// Text specific.
|
// Text specific.
|
||||||
@ -1747,9 +1743,4 @@ public final class Format implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@C.PcmEncoding
|
|
||||||
private static int toPcmEncoding(@C.Encoding int encoding) {
|
|
||||||
return Util.isEncodingLinearPcm(encoding) ? encoding : NO_VALUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1446,7 +1446,7 @@ public final class Util {
|
|||||||
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
||||||
.setChannelCount(channels)
|
.setChannelCount(channels)
|
||||||
.setSampleRate(sampleRate)
|
.setSampleRate(sampleRate)
|
||||||
.setEncoding(pcmEncoding)
|
.setPcmEncoding(pcmEncoding)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1503,7 +1503,7 @@ public final class Util {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the audio track channel configuration for the given channel count, or {@link
|
* Returns the audio track channel configuration for the given channel count, or {@link
|
||||||
* AudioFormat#CHANNEL_INVALID} if output is not poossible.
|
* AudioFormat#CHANNEL_INVALID} if output is not possible.
|
||||||
*
|
*
|
||||||
* @param channelCount The number of channels in the input audio.
|
* @param channelCount The number of channels in the input audio.
|
||||||
* @return The channel configuration or {@link AudioFormat#CHANNEL_INVALID} if output is not
|
* @return The channel configuration or {@link AudioFormat#CHANNEL_INVALID} if output is not
|
||||||
|
@ -22,6 +22,7 @@ import android.media.AudioTrack;
|
|||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.util.Pair;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
@ -31,6 +32,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
|
|||||||
import com.google.android.exoplayer2.audio.AudioProcessor.UnhandledAudioFormatException;
|
import com.google.android.exoplayer2.audio.AudioProcessor.UnhandledAudioFormatException;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Log;
|
import com.google.android.exoplayer2.util.Log;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -441,12 +443,13 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
@Override
|
@Override
|
||||||
@SinkFormatSupport
|
@SinkFormatSupport
|
||||||
public int getFormatSupport(Format format) {
|
public int getFormatSupport(Format format) {
|
||||||
if (format.encoding == C.ENCODING_INVALID) {
|
if (MimeTypes.AUDIO_RAW.equals(format.sampleMimeType)) {
|
||||||
return SINK_FORMAT_UNSUPPORTED;
|
if (!Util.isEncodingLinearPcm(format.pcmEncoding)) {
|
||||||
}
|
Log.w(TAG, "Invalid PCM encoding: " + format.pcmEncoding);
|
||||||
if (Util.isEncodingLinearPcm(format.encoding)) {
|
return SINK_FORMAT_UNSUPPORTED;
|
||||||
if (format.encoding == C.ENCODING_PCM_16BIT
|
}
|
||||||
|| (enableFloatOutput && format.encoding == C.ENCODING_PCM_FLOAT)) {
|
if (format.pcmEncoding == C.ENCODING_PCM_16BIT
|
||||||
|
|| (enableFloatOutput && format.pcmEncoding == C.ENCODING_PCM_FLOAT)) {
|
||||||
return SINK_FORMAT_SUPPORTED_DIRECTLY;
|
return SINK_FORMAT_SUPPORTED_DIRECTLY;
|
||||||
}
|
}
|
||||||
// We can resample all linear PCM encodings to 16-bit integer PCM, which AudioTrack is
|
// We can resample all linear PCM encodings to 16-bit integer PCM, which AudioTrack is
|
||||||
@ -456,7 +459,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
if (enableOffload && isOffloadedPlaybackSupported(format, audioAttributes)) {
|
if (enableOffload && isOffloadedPlaybackSupported(format, audioAttributes)) {
|
||||||
return SINK_FORMAT_SUPPORTED_DIRECTLY;
|
return SINK_FORMAT_SUPPORTED_DIRECTLY;
|
||||||
}
|
}
|
||||||
if (isPassthroughPlaybackSupported(format)) {
|
if (isPassthroughPlaybackSupported(format, audioCapabilities)) {
|
||||||
return SINK_FORMAT_SUPPORTED_DIRECTLY;
|
return SINK_FORMAT_SUPPORTED_DIRECTLY;
|
||||||
}
|
}
|
||||||
return SINK_FORMAT_UNSUPPORTED;
|
return SINK_FORMAT_UNSUPPORTED;
|
||||||
@ -482,15 +485,15 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
@OutputMode int outputMode;
|
@OutputMode int outputMode;
|
||||||
@C.Encoding int outputEncoding;
|
@C.Encoding int outputEncoding;
|
||||||
int outputSampleRate;
|
int outputSampleRate;
|
||||||
int outputChannelCount;
|
|
||||||
int outputChannelConfig;
|
int outputChannelConfig;
|
||||||
int outputPcmFrameSize;
|
int outputPcmFrameSize;
|
||||||
|
|
||||||
if (Util.isEncodingLinearPcm(inputFormat.encoding)) {
|
if (MimeTypes.AUDIO_RAW.equals(inputFormat.sampleMimeType)) {
|
||||||
inputPcmFrameSize = Util.getPcmFrameSize(inputFormat.encoding, inputFormat.channelCount);
|
Assertions.checkArgument(Util.isEncodingLinearPcm(inputFormat.pcmEncoding));
|
||||||
|
|
||||||
|
inputPcmFrameSize = Util.getPcmFrameSize(inputFormat.pcmEncoding, inputFormat.channelCount);
|
||||||
boolean useFloatOutput =
|
boolean useFloatOutput =
|
||||||
enableFloatOutput && Util.isEncodingHighResolutionPcm(inputFormat.encoding);
|
enableFloatOutput && Util.isEncodingHighResolutionPcm(inputFormat.pcmEncoding);
|
||||||
availableAudioProcessors =
|
availableAudioProcessors =
|
||||||
useFloatOutput ? toFloatPcmAvailableAudioProcessors : toIntPcmAvailableAudioProcessors;
|
useFloatOutput ? toFloatPcmAvailableAudioProcessors : toIntPcmAvailableAudioProcessors;
|
||||||
canApplyPlaybackParameters = !useFloatOutput;
|
canApplyPlaybackParameters = !useFloatOutput;
|
||||||
@ -510,7 +513,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
AudioProcessor.AudioFormat outputFormat =
|
AudioProcessor.AudioFormat outputFormat =
|
||||||
new AudioProcessor.AudioFormat(
|
new AudioProcessor.AudioFormat(
|
||||||
inputFormat.sampleRate, inputFormat.channelCount, inputFormat.encoding);
|
inputFormat.sampleRate, inputFormat.channelCount, inputFormat.pcmEncoding);
|
||||||
for (AudioProcessor audioProcessor : availableAudioProcessors) {
|
for (AudioProcessor audioProcessor : availableAudioProcessors) {
|
||||||
try {
|
try {
|
||||||
AudioProcessor.AudioFormat nextFormat = audioProcessor.configure(outputFormat);
|
AudioProcessor.AudioFormat nextFormat = audioProcessor.configure(outputFormat);
|
||||||
@ -525,30 +528,41 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
outputMode = OUTPUT_MODE_PCM;
|
outputMode = OUTPUT_MODE_PCM;
|
||||||
outputEncoding = outputFormat.encoding;
|
outputEncoding = outputFormat.encoding;
|
||||||
outputSampleRate = outputFormat.sampleRate;
|
outputSampleRate = outputFormat.sampleRate;
|
||||||
outputChannelCount = outputFormat.channelCount;
|
outputChannelConfig = Util.getAudioTrackChannelConfig(outputFormat.channelCount);
|
||||||
outputChannelConfig = Util.getAudioTrackChannelConfig(outputChannelCount);
|
outputPcmFrameSize = Util.getPcmFrameSize(outputEncoding, outputFormat.channelCount);
|
||||||
outputPcmFrameSize = Util.getPcmFrameSize(outputEncoding, outputChannelCount);
|
|
||||||
} else {
|
} else {
|
||||||
inputPcmFrameSize = C.LENGTH_UNSET;
|
inputPcmFrameSize = C.LENGTH_UNSET;
|
||||||
availableAudioProcessors = new AudioProcessor[0];
|
availableAudioProcessors = new AudioProcessor[0];
|
||||||
canApplyPlaybackParameters = false;
|
canApplyPlaybackParameters = false;
|
||||||
outputEncoding = inputFormat.encoding;
|
|
||||||
outputSampleRate = inputFormat.sampleRate;
|
outputSampleRate = inputFormat.sampleRate;
|
||||||
outputChannelCount = inputFormat.channelCount;
|
|
||||||
outputPcmFrameSize = C.LENGTH_UNSET;
|
outputPcmFrameSize = C.LENGTH_UNSET;
|
||||||
if (enableOffload && isOffloadedPlaybackSupported(inputFormat, audioAttributes)) {
|
if (enableOffload && isOffloadedPlaybackSupported(inputFormat, audioAttributes)) {
|
||||||
outputMode = OUTPUT_MODE_OFFLOAD;
|
outputMode = OUTPUT_MODE_OFFLOAD;
|
||||||
outputChannelConfig = Util.getAudioTrackChannelConfig(outputChannelCount);
|
outputEncoding =
|
||||||
|
MimeTypes.getEncoding(
|
||||||
|
Assertions.checkNotNull(inputFormat.sampleMimeType), inputFormat.codecs);
|
||||||
|
outputChannelConfig = Util.getAudioTrackChannelConfig(inputFormat.channelCount);
|
||||||
} else {
|
} else {
|
||||||
outputMode = OUTPUT_MODE_PASSTHROUGH;
|
outputMode = OUTPUT_MODE_PASSTHROUGH;
|
||||||
outputChannelConfig = getChannelConfigForPassthrough(inputFormat.channelCount);
|
@Nullable
|
||||||
|
Pair<Integer, Integer> encodingAndChannelConfig =
|
||||||
|
getEncodingAndChannelConfigForPassthrough(inputFormat, audioCapabilities);
|
||||||
|
if (encodingAndChannelConfig == null) {
|
||||||
|
throw new ConfigurationException("Unable to configure passthrough for: " + inputFormat);
|
||||||
|
}
|
||||||
|
outputEncoding = encodingAndChannelConfig.first;
|
||||||
|
outputChannelConfig = encodingAndChannelConfig.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputChannelConfig == AudioFormat.CHANNEL_INVALID) {
|
if (outputEncoding == C.ENCODING_INVALID) {
|
||||||
throw new ConfigurationException("Unsupported channel count: " + outputChannelCount);
|
throw new ConfigurationException(
|
||||||
|
"Invalid output encoding (mode=" + outputMode + ") for: " + inputFormat);
|
||||||
|
}
|
||||||
|
if (outputChannelConfig == AudioFormat.CHANNEL_INVALID) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
"Invalid output channel config (mode=" + outputMode + ") for: " + inputFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration pendingConfiguration =
|
Configuration pendingConfiguration =
|
||||||
new Configuration(
|
new Configuration(
|
||||||
inputPcmFrameSize,
|
inputPcmFrameSize,
|
||||||
@ -1276,60 +1290,67 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
: writtenEncodedFrames;
|
: writtenEncodedFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPassthroughPlaybackSupported(Format format) {
|
private static boolean isPassthroughPlaybackSupported(
|
||||||
// Check for encodings that are known to work for passthrough with the implementation in this
|
Format format, @Nullable AudioCapabilities audioCapabilities) {
|
||||||
// class. This avoids trying to use passthrough with an encoding where the device/app reports
|
return getEncodingAndChannelConfigForPassthrough(format, audioCapabilities) != null;
|
||||||
// it's capable but it is untested or known to be broken (for example AAC-LC).
|
|
||||||
return audioCapabilities != null
|
|
||||||
&& audioCapabilities.supportsEncoding(format.encoding)
|
|
||||||
&& (format.encoding == C.ENCODING_AC3
|
|
||||||
|| format.encoding == C.ENCODING_E_AC3
|
|
||||||
|| format.encoding == C.ENCODING_E_AC3_JOC
|
|
||||||
|| format.encoding == C.ENCODING_AC4
|
|
||||||
|| format.encoding == C.ENCODING_DTS
|
|
||||||
|| format.encoding == C.ENCODING_DTS_HD
|
|
||||||
|| format.encoding == C.ENCODING_DOLBY_TRUEHD)
|
|
||||||
&& (format.channelCount == Format.NO_VALUE
|
|
||||||
|| format.channelCount <= audioCapabilities.getMaxChannelCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isOffloadedPlaybackSupported(
|
|
||||||
Format format, AudioAttributes audioAttributes) {
|
|
||||||
if (Util.SDK_INT < 29) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int channelConfig = Util.getAudioTrackChannelConfig(format.channelCount);
|
|
||||||
AudioFormat audioFormat = getAudioFormat(format.sampleRate, channelConfig, format.encoding);
|
|
||||||
if (!AudioManager.isOffloadedPlaybackSupported(
|
|
||||||
audioFormat, audioAttributes.getAudioAttributesV21())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
boolean notGapless = format.encoderDelay == 0 && format.encoderPadding == 0;
|
|
||||||
return notGapless || isOffloadGaplessSupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the device supports gapless in offload playback.
|
* Returns the encoding and channel config to use when configuring an {@link AudioTrack} in
|
||||||
|
* passthrough mode for the specified {@link Format}. Returns {@code null} if passthrough of the
|
||||||
|
* format is unsupported.
|
||||||
*
|
*
|
||||||
* <p>Gapless offload is not supported by all devices and there is no API to query its support. As
|
* @param format The {@link Format}.
|
||||||
* a result this detection is currently based on manual testing. TODO(internal b/158191844): Add
|
* @param audioCapabilities The device audio capabilities.
|
||||||
* an SDK API to query offload gapless support.
|
* @return The encoding and channel config to use, or {@code null} if passthrough of the format is
|
||||||
|
* unsupported.
|
||||||
*/
|
*/
|
||||||
private static boolean isOffloadGaplessSupported() {
|
@Nullable
|
||||||
return Util.SDK_INT >= 30 && Util.MODEL.startsWith("Pixel");
|
private static Pair<Integer, Integer> getEncodingAndChannelConfigForPassthrough(
|
||||||
}
|
Format format, @Nullable AudioCapabilities audioCapabilities) {
|
||||||
|
if (audioCapabilities == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isOffloadedPlayback(AudioTrack audioTrack) {
|
@C.Encoding
|
||||||
return Util.SDK_INT >= 29 && audioTrack.isOffloadedPlayback();
|
int encoding =
|
||||||
}
|
MimeTypes.getEncoding(Assertions.checkNotNull(format.sampleMimeType), format.codecs);
|
||||||
|
// Check for encodings that are known to work for passthrough with the implementation in this
|
||||||
|
// class. This avoids trying to use passthrough with an encoding where the device/app reports
|
||||||
|
// it's capable but it is untested or known to be broken (for example AAC-LC).
|
||||||
|
boolean supportedEncoding =
|
||||||
|
encoding == C.ENCODING_AC3
|
||||||
|
|| encoding == C.ENCODING_E_AC3
|
||||||
|
|| encoding == C.ENCODING_E_AC3_JOC
|
||||||
|
|| encoding == C.ENCODING_AC4
|
||||||
|
|| encoding == C.ENCODING_DTS
|
||||||
|
|| encoding == C.ENCODING_DTS_HD
|
||||||
|
|| encoding == C.ENCODING_DOLBY_TRUEHD;
|
||||||
|
if (!supportedEncoding) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static AudioTrack initializeKeepSessionIdAudioTrack(int audioSessionId) {
|
// E-AC3 JOC is object based, so any channel count specified in the format is arbitrary. Use 6,
|
||||||
int sampleRate = 4000; // Equal to private AudioTrack.MIN_SAMPLE_RATE.
|
// since the E-AC3 compatible part of the stream is 5.1.
|
||||||
int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
|
int channelCount = encoding == C.ENCODING_E_AC3_JOC ? 6 : format.channelCount;
|
||||||
@C.PcmEncoding int encoding = C.ENCODING_PCM_16BIT;
|
if (channelCount > audioCapabilities.getMaxChannelCount()) {
|
||||||
int bufferSize = 2; // Use a two byte buffer, as it is not actually used for playback.
|
return null;
|
||||||
return new AudioTrack(C.STREAM_TYPE_DEFAULT, sampleRate, channelConfig, encoding, bufferSize,
|
}
|
||||||
MODE_STATIC, audioSessionId);
|
|
||||||
|
int channelConfig = getChannelConfigForPassthrough(channelCount);
|
||||||
|
if (channelConfig == AudioFormat.CHANNEL_INVALID) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audioCapabilities.supportsEncoding(encoding)) {
|
||||||
|
return Pair.create(encoding, channelConfig);
|
||||||
|
} else if (encoding == C.ENCODING_E_AC3_JOC
|
||||||
|
&& audioCapabilities.supportsEncoding(C.ENCODING_E_AC3)) {
|
||||||
|
// E-AC3 receivers support E-AC3 JOC streams (but decode in 2-D rather than 3-D).
|
||||||
|
return Pair.create(C.ENCODING_E_AC3, channelConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getChannelConfigForPassthrough(int channelCount) {
|
private static int getChannelConfigForPassthrough(int channelCount) {
|
||||||
@ -1354,6 +1375,60 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
return Util.getAudioTrackChannelConfig(channelCount);
|
return Util.getAudioTrackChannelConfig(channelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isOffloadedPlaybackSupported(
|
||||||
|
Format format, AudioAttributes audioAttributes) {
|
||||||
|
if (Util.SDK_INT < 29) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@C.Encoding
|
||||||
|
int encoding =
|
||||||
|
MimeTypes.getEncoding(Assertions.checkNotNull(format.sampleMimeType), format.codecs);
|
||||||
|
if (encoding == C.ENCODING_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int channelConfig = Util.getAudioTrackChannelConfig(format.channelCount);
|
||||||
|
if (channelConfig == AudioFormat.CHANNEL_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AudioFormat audioFormat = getAudioFormat(format.sampleRate, channelConfig, encoding);
|
||||||
|
if (!AudioManager.isOffloadedPlaybackSupported(
|
||||||
|
audioFormat, audioAttributes.getAudioAttributesV21())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean notGapless = format.encoderDelay == 0 && format.encoderPadding == 0;
|
||||||
|
return notGapless || isOffloadedGaplessPlaybackSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the device supports gapless in offload playback.
|
||||||
|
*
|
||||||
|
* <p>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) {
|
private static int getMaximumEncodedRateBytesPerSecond(@C.Encoding int encoding) {
|
||||||
switch (encoding) {
|
switch (encoding) {
|
||||||
case C.ENCODING_MP3:
|
case C.ENCODING_MP3:
|
||||||
|
@ -290,7 +290,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean usePassthrough(Format format) {
|
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
|
@Override
|
||||||
@ -345,7 +350,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
return Util.areEqual(oldFormat.sampleMimeType, newFormat.sampleMimeType)
|
return Util.areEqual(oldFormat.sampleMimeType, newFormat.sampleMimeType)
|
||||||
&& oldFormat.channelCount == newFormat.channelCount
|
&& oldFormat.channelCount == newFormat.channelCount
|
||||||
&& oldFormat.sampleRate == newFormat.sampleRate
|
&& oldFormat.sampleRate == newFormat.sampleRate
|
||||||
&& oldFormat.encoding == newFormat.encoding
|
&& oldFormat.pcmEncoding == newFormat.pcmEncoding
|
||||||
&& oldFormat.initializationDataEquals(newFormat)
|
&& oldFormat.initializationDataEquals(newFormat)
|
||||||
&& !MimeTypes.AUDIO_OPUS.equals(oldFormat.sampleMimeType);
|
&& !MimeTypes.AUDIO_OPUS.equals(oldFormat.sampleMimeType);
|
||||||
}
|
}
|
||||||
@ -394,21 +399,26 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
Format audioSinkInputFormat;
|
Format audioSinkInputFormat;
|
||||||
@Nullable int[] channelMap = null;
|
@Nullable int[] channelMap = null;
|
||||||
if (codecPassthroughFormat != null) { // Raw codec passthrough
|
if (codecPassthroughFormat != null) { // Raw codec passthrough
|
||||||
audioSinkInputFormat = getFormatWithEncodingForPassthrough(codecPassthroughFormat);
|
audioSinkInputFormat = codecPassthroughFormat;
|
||||||
} else if (getCodec() == null) { // Codec bypass passthrough
|
} else if (getCodec() == null) { // Codec bypass passthrough
|
||||||
audioSinkInputFormat = getFormatWithEncodingForPassthrough(outputFormat);
|
audioSinkInputFormat = outputFormat;
|
||||||
} else {
|
} else {
|
||||||
MediaFormat mediaFormat = getCodec().getOutputFormat();
|
MediaFormat mediaFormat = getCodec().getOutputFormat();
|
||||||
@C.PcmEncoding int pcmEncoding;
|
@C.PcmEncoding int pcmEncoding;
|
||||||
if (mediaFormat.containsKey(VIVO_BITS_PER_SAMPLE_KEY)) {
|
if (mediaFormat.containsKey(VIVO_BITS_PER_SAMPLE_KEY)) {
|
||||||
pcmEncoding = Util.getPcmEncoding(mediaFormat.getInteger(VIVO_BITS_PER_SAMPLE_KEY));
|
pcmEncoding = Util.getPcmEncoding(mediaFormat.getInteger(VIVO_BITS_PER_SAMPLE_KEY));
|
||||||
} else {
|
} 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 =
|
audioSinkInputFormat =
|
||||||
new Format.Builder()
|
new Format.Builder()
|
||||||
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
||||||
.setEncoding(pcmEncoding)
|
.setPcmEncoding(pcmEncoding)
|
||||||
.setEncoderDelay(outputFormat.encoderDelay)
|
.setEncoderDelay(outputFormat.encoderDelay)
|
||||||
.setEncoderPadding(outputFormat.encoderPadding)
|
.setEncoderPadding(outputFormat.encoderPadding)
|
||||||
.setChannelCount(mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT))
|
.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
|
* 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
|
* 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
|
* Returns whether the device's decoders are known to not support setting the codec operating
|
||||||
* rate.
|
* rate.
|
||||||
@ -832,15 +796,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
|| Util.DEVICE.startsWith("ms01"));
|
|| 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 {
|
private final class AudioSinkListener implements AudioSink.Listener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,7 +88,7 @@ public final class SilenceMediaSource extends BaseMediaSource {
|
|||||||
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
||||||
.setChannelCount(CHANNEL_COUNT)
|
.setChannelCount(CHANNEL_COUNT)
|
||||||
.setSampleRate(SAMPLE_RATE_HZ)
|
.setSampleRate(SAMPLE_RATE_HZ)
|
||||||
.setEncoding(PCM_ENCODING)
|
.setPcmEncoding(PCM_ENCODING)
|
||||||
.build();
|
.build();
|
||||||
private static final MediaItem MEDIA_ITEM =
|
private static final MediaItem MEDIA_ITEM =
|
||||||
new MediaItem.Builder()
|
new MediaItem.Builder()
|
||||||
|
@ -24,6 +24,7 @@ import static org.robolectric.annotation.Config.TARGET_SDK;
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -213,7 +214,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
|
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
|
||||||
new AudioProcessor[0],
|
new AudioProcessor[0],
|
||||||
/* enableFloatOutput= */ false);
|
/* 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))
|
assertThat(defaultAudioSink.getFormatSupport(floatFormat))
|
||||||
.isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING);
|
.isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING);
|
||||||
}
|
}
|
||||||
@ -226,7 +232,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
|
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
|
||||||
new AudioProcessor[0],
|
new AudioProcessor[0],
|
||||||
/* enableFloatOutput= */ true);
|
/* 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))
|
assertThat(defaultAudioSink.getFormatSupport(floatFormat))
|
||||||
.isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING);
|
.isEqualTo(SINK_FORMAT_SUPPORTED_WITH_TRANSCODING);
|
||||||
}
|
}
|
||||||
@ -239,14 +250,24 @@ public final class DefaultAudioSinkTest {
|
|||||||
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
|
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES,
|
||||||
new AudioProcessor[0],
|
new AudioProcessor[0],
|
||||||
/* enableFloatOutput= */ true);
|
/* 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))
|
assertThat(defaultAudioSink.getFormatSupport(floatFormat))
|
||||||
.isEqualTo(SINK_FORMAT_SUPPORTED_DIRECTLY);
|
.isEqualTo(SINK_FORMAT_SUPPORTED_DIRECTLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void supportsFloatPcm() {
|
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();
|
assertThat(defaultAudioSink.supportsFormat(floatFormat)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +276,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
DefaultAudioSink defaultAudioSink =
|
DefaultAudioSink defaultAudioSink =
|
||||||
new DefaultAudioSink(
|
new DefaultAudioSink(
|
||||||
new AudioCapabilities(new int[] {C.ENCODING_AAC_LC}, 2), new AudioProcessor[0]);
|
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();
|
assertThat(defaultAudioSink.supportsFormat(aacLcFormat)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +293,8 @@ public final class DefaultAudioSinkTest {
|
|||||||
throws AudioSink.ConfigurationException {
|
throws AudioSink.ConfigurationException {
|
||||||
Format format =
|
Format format =
|
||||||
new Format.Builder()
|
new Format.Builder()
|
||||||
.setEncoding(C.ENCODING_PCM_16BIT)
|
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
||||||
|
.setPcmEncoding(C.ENCODING_PCM_16BIT)
|
||||||
.setChannelCount(channelCount)
|
.setChannelCount(channelCount)
|
||||||
.setSampleRate(SAMPLE_RATE_44_1)
|
.setSampleRate(SAMPLE_RATE_44_1)
|
||||||
.setEncoderDelay(trimStartFrames)
|
.setEncoderDelay(trimStartFrames)
|
||||||
|
@ -56,7 +56,7 @@ public class MediaCodecAudioRendererTest {
|
|||||||
private static final Format AUDIO_AAC =
|
private static final Format AUDIO_AAC =
|
||||||
new Format.Builder()
|
new Format.Builder()
|
||||||
.setSampleMimeType(MimeTypes.AUDIO_AAC)
|
.setSampleMimeType(MimeTypes.AUDIO_AAC)
|
||||||
.setEncoding(C.ENCODING_PCM_16BIT)
|
.setPcmEncoding(C.ENCODING_PCM_16BIT)
|
||||||
.setChannelCount(2)
|
.setChannelCount(2)
|
||||||
.setSampleRate(44100)
|
.setSampleRate(44100)
|
||||||
.setEncoderDelay(100)
|
.setEncoderDelay(100)
|
||||||
@ -274,7 +274,7 @@ public class MediaCodecAudioRendererTest {
|
|||||||
private static Format getAudioSinkFormat(Format inputFormat) {
|
private static Format getAudioSinkFormat(Format inputFormat) {
|
||||||
return new Format.Builder()
|
return new Format.Builder()
|
||||||
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
.setSampleMimeType(MimeTypes.AUDIO_RAW)
|
||||||
.setEncoding(C.ENCODING_PCM_16BIT)
|
.setPcmEncoding(C.ENCODING_PCM_16BIT)
|
||||||
.setChannelCount(inputFormat.channelCount)
|
.setChannelCount(inputFormat.channelCount)
|
||||||
.setSampleRate(inputFormat.sampleRate)
|
.setSampleRate(inputFormat.sampleRate)
|
||||||
.setEncoderDelay(inputFormat.encoderDelay)
|
.setEncoderDelay(inputFormat.encoderDelay)
|
||||||
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.mediacodec;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
@ -34,7 +33,6 @@ public final class C2Mp3TimestampTrackerTest {
|
|||||||
private static final Format AUDIO_MP3 =
|
private static final Format AUDIO_MP3 =
|
||||||
new Format.Builder()
|
new Format.Builder()
|
||||||
.setSampleMimeType(MimeTypes.AUDIO_MPEG)
|
.setSampleMimeType(MimeTypes.AUDIO_MPEG)
|
||||||
.setEncoding(C.ENCODING_PCM_16BIT)
|
|
||||||
.setChannelCount(2)
|
.setChannelCount(2)
|
||||||
.setSampleRate(44_100)
|
.setSampleRate(44_100)
|
||||||
.build();
|
.build();
|
||||||
|
@ -2098,7 +2098,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
formatBuilder
|
formatBuilder
|
||||||
.setChannelCount(channelCount)
|
.setChannelCount(channelCount)
|
||||||
.setSampleRate(sampleRate)
|
.setSampleRate(sampleRate)
|
||||||
.setEncoding(pcmEncoding);
|
.setPcmEncoding(pcmEncoding);
|
||||||
} else if (MimeTypes.isVideo(mimeType)) {
|
} else if (MimeTypes.isVideo(mimeType)) {
|
||||||
type = C.TRACK_TYPE_VIDEO;
|
type = C.TRACK_TYPE_VIDEO;
|
||||||
if (displayUnit == Track.DISPLAY_UNIT_PIXELS) {
|
if (displayUnit == Track.DISPLAY_UNIT_PIXELS) {
|
||||||
|
@ -404,7 +404,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
chunkOffsetsBytes[chunkIterator.index] = chunkIterator.offset;
|
chunkOffsetsBytes[chunkIterator.index] = chunkIterator.offset;
|
||||||
chunkSampleCounts[chunkIterator.index] = chunkIterator.numSamples;
|
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.Results rechunkedResults =
|
||||||
FixedSampleSizeRechunker.rechunk(
|
FixedSampleSizeRechunker.rechunk(
|
||||||
fixedSampleSize, chunkOffsetsBytes, chunkSampleCounts, timestampDeltaInTimeUnits);
|
fixedSampleSize, chunkOffsetsBytes, chunkSampleCounts, timestampDeltaInTimeUnits);
|
||||||
@ -1325,7 +1326,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
.setCodecs(codecs)
|
.setCodecs(codecs)
|
||||||
.setChannelCount(channelCount)
|
.setChannelCount(channelCount)
|
||||||
.setSampleRate(sampleRate)
|
.setSampleRate(sampleRate)
|
||||||
.setEncoding(pcmEncoding)
|
.setPcmEncoding(pcmEncoding)
|
||||||
.setInitializationData(
|
.setInitializationData(
|
||||||
initializationData == null ? null : Collections.singletonList(initializationData))
|
initializationData == null ? null : Collections.singletonList(initializationData))
|
||||||
.setDrmInitData(drmInitData)
|
.setDrmInitData(drmInitData)
|
||||||
|
@ -231,7 +231,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
.setMaxInputSize(targetSampleSizeBytes)
|
.setMaxInputSize(targetSampleSizeBytes)
|
||||||
.setChannelCount(header.numChannels)
|
.setChannelCount(header.numChannels)
|
||||||
.setSampleRate(header.frameRateHz)
|
.setSampleRate(header.frameRateHz)
|
||||||
.setEncoding(pcmEncoding)
|
.setPcmEncoding(pcmEncoding)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +373,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
.setMaxInputSize(numOutputFramesToBytes(targetSampleSizeFrames, numChannels))
|
.setMaxInputSize(numOutputFramesToBytes(targetSampleSizeFrames, numChannels))
|
||||||
.setChannelCount(header.numChannels)
|
.setChannelCount(header.numChannels)
|
||||||
.setSampleRate(header.frameRateHz)
|
.setSampleRate(header.frameRateHz)
|
||||||
.setEncoding(C.ENCODING_PCM_16BIT)
|
.setPcmEncoding(C.ENCODING_PCM_16BIT)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public final class CapturingAudioSink extends ForwardingAudioSink implements Dum
|
|||||||
throws ConfigurationException {
|
throws ConfigurationException {
|
||||||
interceptedData.add(
|
interceptedData.add(
|
||||||
new DumpableConfiguration(
|
new DumpableConfiguration(
|
||||||
inputFormat.encoding, inputFormat.channelCount, inputFormat.sampleRate));
|
inputFormat.pcmEncoding, inputFormat.channelCount, inputFormat.sampleRate));
|
||||||
super.configure(inputFormat, specifiedBufferSize, outputChannels);
|
super.configure(inputFormat, specifiedBufferSize, outputChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user