Cleanup merged pull requests

This commit is contained in:
Oliver Woodman 2018-01-24 10:51:05 +00:00
parent 4d2e0bf122
commit d098effa69
7 changed files with 120 additions and 122 deletions

View File

@ -66,8 +66,12 @@
* Fix ID3 context reuse across segment format changes * Fix ID3 context reuse across segment format changes
([#3622](https://github.com/google/ExoPlayer/issues/3622)). ([#3622](https://github.com/google/ExoPlayer/issues/3622)).
* New Cast extension: Simplifies toggling between local and Cast playbacks. * New Cast extension: Simplifies toggling between local and Cast playbacks.
* Audio: Support TrueHD passthrough for rechunked samples in Matroska files * Audio:
([#2147](https://github.com/google/ExoPlayer/issues/2147)). * Support TrueHD passthrough for rechunked samples in Matroska files
([#2147](https://github.com/google/ExoPlayer/issues/2147)).
* Support resampling 24-bit and 32-bit integer to 32-bit float for high
resolution output in `DefaultAudioSink`
([#3635](https://github.com/google/ExoPlayer/pull/3635)).
* Captions: Initial support for PGS subtitles * Captions: Initial support for PGS subtitles
([#3008](https://github.com/google/ExoPlayer/issues/3008)). ([#3008](https://github.com/google/ExoPlayer/issues/3008)).
* CacheDataSource: Check periodically if it's possible to read from/write to * CacheDataSource: Check periodically if it's possible to read from/write to

View File

@ -164,7 +164,7 @@ public final class DefaultAudioSink implements AudioSink {
public static boolean failOnSpuriousAudioTimestamp = false; public static boolean failOnSpuriousAudioTimestamp = false;
@Nullable private final AudioCapabilities audioCapabilities; @Nullable private final AudioCapabilities audioCapabilities;
private final boolean canConvertHiResPcmToFloat; private final boolean enableConvertHighResIntPcmToFloat;
private final ChannelMappingAudioProcessor channelMappingAudioProcessor; private final ChannelMappingAudioProcessor channelMappingAudioProcessor;
private final TrimmingAudioProcessor trimmingAudioProcessor; private final TrimmingAudioProcessor trimmingAudioProcessor;
private final SonicAudioProcessor sonicAudioProcessor; private final SonicAudioProcessor sonicAudioProcessor;
@ -182,14 +182,14 @@ public final class DefaultAudioSink implements AudioSink {
private AudioTrack keepSessionIdAudioTrack; private AudioTrack keepSessionIdAudioTrack;
private AudioTrack audioTrack; private AudioTrack audioTrack;
private boolean isInputPcm; private boolean isInputPcm;
private boolean shouldUpResPCMAudio; private boolean shouldConvertHighResIntPcmToFloat;
private int inputSampleRate; private int inputSampleRate;
private int sampleRate; private int sampleRate;
private int channelConfig; private int channelConfig;
private @C.Encoding int outputEncoding; private @C.Encoding int outputEncoding;
private AudioAttributes audioAttributes; private AudioAttributes audioAttributes;
private boolean processingEnabled; private boolean processingEnabled;
private boolean canApplyPlaybackParams; private boolean canApplyPlaybackParameters;
private int bufferSize; private int bufferSize;
private long bufferSizeUs; private long bufferSizeUs;
@ -237,8 +237,6 @@ public final class DefaultAudioSink implements AudioSink {
private boolean hasData; private boolean hasData;
private long lastFeedElapsedRealtimeMs; private long lastFeedElapsedRealtimeMs;
/** /**
* @param audioCapabilities The audio capabilities for playback on this device. May be null if the * @param audioCapabilities The audio capabilities for playback on this device. May be null if the
* default capabilities (no encoded audio passthrough support) should be assumed. * default capabilities (no encoded audio passthrough support) should be assumed.
@ -247,7 +245,7 @@ public final class DefaultAudioSink implements AudioSink {
*/ */
public DefaultAudioSink(@Nullable AudioCapabilities audioCapabilities, public DefaultAudioSink(@Nullable AudioCapabilities audioCapabilities,
AudioProcessor[] audioProcessors) { AudioProcessor[] audioProcessors) {
this(audioCapabilities, audioProcessors, false); this(audioCapabilities, audioProcessors, /* enableConvertHighResIntPcmToFloat= */ false);
} }
/** /**
@ -255,15 +253,17 @@ public final class DefaultAudioSink implements AudioSink {
* default capabilities (no encoded audio passthrough support) should be assumed. * default capabilities (no encoded audio passthrough support) should be assumed.
* @param audioProcessors An array of {@link AudioProcessor}s that will process PCM audio before * @param audioProcessors An array of {@link AudioProcessor}s that will process PCM audio before
* output. May be empty. * output. May be empty.
* @param canConvertHiResPcmToFloat Flag to convert > 16bit PCM Audio to 32bit Float PCM Audio to * @param enableConvertHighResIntPcmToFloat Whether to enable conversion of high resolution
* avoid dithering the input audio. If enabled other audio processors that expect 16bit PCM * integer PCM to 32-bit float for output, if possible. Functionality that uses 16-bit integer
* are disabled * audio processing (for example, speed and pitch adjustment) will not be available when float
* output is in use.
*/ */
public DefaultAudioSink(@Nullable AudioCapabilities audioCapabilities, public DefaultAudioSink(
AudioProcessor[] audioProcessors, boolean canConvertHiResPcmToFloat) { @Nullable AudioCapabilities audioCapabilities,
AudioProcessor[] audioProcessors,
boolean enableConvertHighResIntPcmToFloat) {
this.audioCapabilities = audioCapabilities; this.audioCapabilities = audioCapabilities;
this.canConvertHiResPcmToFloat = canConvertHiResPcmToFloat; this.enableConvertHighResIntPcmToFloat = enableConvertHighResIntPcmToFloat;
releasingConditionVariable = new ConditionVariable(true); releasingConditionVariable = new ConditionVariable(true);
if (Util.SDK_INT >= 18) { if (Util.SDK_INT >= 18) {
try { try {
@ -285,10 +285,10 @@ public final class DefaultAudioSink implements AudioSink {
toIntPcmAvailableAudioProcessors[0] = new ResamplingAudioProcessor(); toIntPcmAvailableAudioProcessors[0] = new ResamplingAudioProcessor();
toIntPcmAvailableAudioProcessors[1] = channelMappingAudioProcessor; toIntPcmAvailableAudioProcessors[1] = channelMappingAudioProcessor;
toIntPcmAvailableAudioProcessors[2] = trimmingAudioProcessor; toIntPcmAvailableAudioProcessors[2] = trimmingAudioProcessor;
System.arraycopy(audioProcessors, 0, toIntPcmAvailableAudioProcessors, 3, audioProcessors.length); System.arraycopy(
audioProcessors, 0, toIntPcmAvailableAudioProcessors, 3, audioProcessors.length);
toIntPcmAvailableAudioProcessors[3 + audioProcessors.length] = sonicAudioProcessor; toIntPcmAvailableAudioProcessors[3 + audioProcessors.length] = sonicAudioProcessor;
toFloatPcmAvailableAudioProcessors = new AudioProcessor[1]; toFloatPcmAvailableAudioProcessors = new AudioProcessor[] {new FloatResamplingAudioProcessor()};
toFloatPcmAvailableAudioProcessors[0] = new FloatResamplingAudioProcessor();
playheadOffsets = new long[MAX_PLAYHEAD_OFFSET_COUNT]; playheadOffsets = new long[MAX_PLAYHEAD_OFFSET_COUNT];
volume = 1.0f; volume = 1.0f;
startMediaTimeState = START_NOT_SET; startMediaTimeState = START_NOT_SET;
@ -366,20 +366,20 @@ public final class DefaultAudioSink implements AudioSink {
int channelCount = inputChannelCount; int channelCount = inputChannelCount;
int sampleRate = inputSampleRate; int sampleRate = inputSampleRate;
isInputPcm = isEncodingPcm(inputEncoding); isInputPcm = isEncodingPcm(inputEncoding);
shouldUpResPCMAudio = canConvertHiResPcmToFloat && shouldConvertHighResIntPcmToFloat =
(inputEncoding == C.ENCODING_PCM_24BIT || inputEncoding == C.ENCODING_PCM_32BIT); enableConvertHighResIntPcmToFloat
&& isEncodingSupported(C.ENCODING_PCM_32BIT)
&& Util.isEncodingHighResolutionIntegerPcm(inputEncoding);
if (isInputPcm) { if (isInputPcm) {
pcmFrameSize = Util.getPcmFrameSize(inputEncoding, channelCount); pcmFrameSize = Util.getPcmFrameSize(inputEncoding, channelCount);
} }
@C.Encoding int encoding = inputEncoding; @C.Encoding int encoding = inputEncoding;
boolean processingEnabled = isInputPcm && inputEncoding != C.ENCODING_PCM_FLOAT; boolean processingEnabled = isInputPcm && inputEncoding != C.ENCODING_PCM_FLOAT;
canApplyPlaybackParams = processingEnabled && !shouldUpResPCMAudio; canApplyPlaybackParameters = processingEnabled && !shouldConvertHighResIntPcmToFloat;
if (processingEnabled) { if (processingEnabled) {
AudioProcessor[] availableAudioProcessors = shouldUpResPCMAudio ?
toFloatPcmAvailableAudioProcessors : toIntPcmAvailableAudioProcessors;
trimmingAudioProcessor.setTrimSampleCount(trimStartSamples, trimEndSamples); trimmingAudioProcessor.setTrimSampleCount(trimStartSamples, trimEndSamples);
channelMappingAudioProcessor.setChannelMap(outputChannels); channelMappingAudioProcessor.setChannelMap(outputChannels);
for (AudioProcessor audioProcessor : availableAudioProcessors) { for (AudioProcessor audioProcessor : getAvailableAudioProcessors()) {
try { try {
flush |= audioProcessor.configure(sampleRate, channelCount, encoding); flush |= audioProcessor.configure(sampleRate, channelCount, encoding);
} catch (AudioProcessor.UnhandledFormatException e) { } catch (AudioProcessor.UnhandledFormatException e) {
@ -489,9 +489,7 @@ public final class DefaultAudioSink implements AudioSink {
private void resetAudioProcessors() { private void resetAudioProcessors() {
ArrayList<AudioProcessor> newAudioProcessors = new ArrayList<>(); ArrayList<AudioProcessor> newAudioProcessors = new ArrayList<>();
AudioProcessor[] availableAudioProcessors = shouldUpResPCMAudio ? for (AudioProcessor audioProcessor : getAvailableAudioProcessors()) {
toFloatPcmAvailableAudioProcessors : toIntPcmAvailableAudioProcessors;
for (AudioProcessor audioProcessor : availableAudioProcessors) {
if (audioProcessor.isActive()) { if (audioProcessor.isActive()) {
newAudioProcessors.add(audioProcessor); newAudioProcessors.add(audioProcessor);
} else { } else {
@ -839,8 +837,7 @@ public final class DefaultAudioSink implements AudioSink {
@Override @Override
public PlaybackParameters setPlaybackParameters(PlaybackParameters playbackParameters) { public PlaybackParameters setPlaybackParameters(PlaybackParameters playbackParameters) {
if (isInitialized() && !canApplyPlaybackParams) { if (isInitialized() && !canApplyPlaybackParameters) {
// The playback parameters are always the default if processing is disabled.
this.playbackParameters = PlaybackParameters.DEFAULT; this.playbackParameters = PlaybackParameters.DEFAULT;
return this.playbackParameters; return this.playbackParameters;
} }
@ -1256,6 +1253,12 @@ public final class DefaultAudioSink implements AudioSink {
MODE_STATIC, audioSessionId); MODE_STATIC, audioSessionId);
} }
private AudioProcessor[] getAvailableAudioProcessors() {
return shouldConvertHighResIntPcmToFloat
? toFloatPcmAvailableAudioProcessors
: toIntPcmAvailableAudioProcessors;
}
private static boolean isEncodingPcm(@C.Encoding int encoding) { private static boolean isEncodingPcm(@C.Encoding int encoding) {
return encoding == C.ENCODING_PCM_8BIT || encoding == C.ENCODING_PCM_16BIT return encoding == C.ENCODING_PCM_8BIT || encoding == C.ENCODING_PCM_16BIT
|| encoding == C.ENCODING_PCM_24BIT || encoding == C.ENCODING_PCM_32BIT || encoding == C.ENCODING_PCM_24BIT || encoding == C.ENCODING_PCM_32BIT

View File

@ -15,31 +15,30 @@
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.audio;
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.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
/** /**
* An {@link AudioProcessor} that converts audio data to {@link C#ENCODING_PCM_16BIT}. * An {@link AudioProcessor} that converts 24-bit and 32-bit integer PCM audio to 32-bit float PCM
* audio.
*/ */
/* package */ final class FloatResamplingAudioProcessor implements AudioProcessor { /* package */ final class FloatResamplingAudioProcessor implements AudioProcessor {
private int sampleRateHz; private static final int FLOAT_NAN_AS_INT = Float.floatToIntBits(Float.NaN);
private static final double PCM_INT32_FLOAT = 1.0 / 0x7fffffff; private static final double PCM_32_BIT_INT_TO_PCM_32_BIT_FLOAT_FACTOR = 1.0 / 0x7FFFFFFF;
private int sampleRateHz;
private int channelCount; private int channelCount;
@C.PcmEncoding private @C.PcmEncoding int sourceEncoding;
private int sourceEncoding;
private ByteBuffer buffer; private ByteBuffer buffer;
private ByteBuffer outputBuffer; private ByteBuffer outputBuffer;
private boolean inputEnded; private boolean inputEnded;
/** /** Creates a new audio processor that converts audio data to {@link C#ENCODING_PCM_FLOAT}. */
* Creates a new audio processor that converts audio data to {@link C#ENCODING_PCM_16BIT}.
*/
public FloatResamplingAudioProcessor() { public FloatResamplingAudioProcessor() {
sampleRateHz = Format.NO_VALUE; sampleRateHz = Format.NO_VALUE;
channelCount = Format.NO_VALUE; channelCount = Format.NO_VALUE;
@ -50,31 +49,35 @@ import java.nio.ByteOrder;
@Override @Override
public boolean configure(int sampleRateHz, int channelCount, @C.Encoding int encoding) public boolean configure(int sampleRateHz, int channelCount, @C.Encoding int encoding)
throws AudioProcessor.UnhandledFormatException { throws UnhandledFormatException {
if (encoding != C.ENCODING_PCM_24BIT && encoding != C.ENCODING_PCM_32BIT) { if (!Util.isEncodingHighResolutionIntegerPcm(encoding)) {
throw new AudioProcessor.UnhandledFormatException(sampleRateHz, channelCount, encoding); throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
} }
if (this.sampleRateHz == sampleRateHz && this.channelCount == channelCount if (this.sampleRateHz == sampleRateHz
&& this.sourceEncoding == encoding) { && this.channelCount == channelCount
&& sourceEncoding == encoding) {
return false; return false;
} }
this.sampleRateHz = sampleRateHz; this.sampleRateHz = sampleRateHz;
this.channelCount = channelCount; this.channelCount = channelCount;
this.sourceEncoding = encoding; sourceEncoding = encoding;
return true; return true;
} }
@Override @Override
public boolean isActive() { public boolean isActive() {
return sourceEncoding == C.ENCODING_PCM_24BIT || sourceEncoding == C.ENCODING_PCM_32BIT; return Util.isEncodingHighResolutionIntegerPcm(sourceEncoding);
} }
@Override @Override
public int getOutputChannelCount() { return channelCount; } public int getOutputChannelCount() {
return channelCount;
}
@Override @Override
public int getOutputEncoding() { return C.ENCODING_PCM_FLOAT; } public int getOutputEncoding() {
return C.ENCODING_PCM_FLOAT;
}
@Override @Override
public int getOutputSampleRateHz() { public int getOutputSampleRateHz() {
@ -83,60 +86,36 @@ import java.nio.ByteOrder;
@Override @Override
public void queueInput(ByteBuffer inputBuffer) { public void queueInput(ByteBuffer inputBuffer) {
int offset = inputBuffer.position(); Assertions.checkState(isActive());
boolean isInput32Bit = sourceEncoding == C.ENCODING_PCM_32BIT;
int position = inputBuffer.position();
int limit = inputBuffer.limit(); int limit = inputBuffer.limit();
int size = limit - offset; int size = limit - position;
int resampledSize;
switch (sourceEncoding) {
case C.ENCODING_PCM_24BIT:
resampledSize = (size / 3) * 4;
break;
case C.ENCODING_PCM_32BIT:
resampledSize = size;
break;
case C.ENCODING_PCM_8BIT:
case C.ENCODING_PCM_16BIT:
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_INVALID:
case Format.NO_VALUE:
default:
// Never happens.
throw new IllegalStateException();
}
int resampledSize = isInput32Bit ? size : (size / 3) * 4;
if (buffer.capacity() < resampledSize) { if (buffer.capacity() < resampledSize) {
buffer = ByteBuffer.allocateDirect(resampledSize).order(ByteOrder.nativeOrder()); buffer = ByteBuffer.allocateDirect(resampledSize).order(ByteOrder.nativeOrder());
} else { } else {
buffer.clear(); buffer.clear();
} }
if (isInput32Bit) {
// Samples are little endian. for (int i = position; i < limit; i += 4) {
switch (sourceEncoding) { int pcm32BitInteger =
case C.ENCODING_PCM_24BIT: (inputBuffer.get(i) & 0xFF)
// 24->32 bit resampling. | ((inputBuffer.get(i + 1) & 0xFF) << 8)
for (int i = offset; i < limit; i += 3) { | ((inputBuffer.get(i + 2) & 0xFF) << 16)
int val = (inputBuffer.get(i) << 8) & 0x0000ff00 | (inputBuffer.get(i + 1) << 16) & 0x00ff0000 | | ((inputBuffer.get(i + 3) & 0xFF) << 24);
(inputBuffer.get(i + 2) << 24) & 0xff000000; writePcm32BitFloat(pcm32BitInteger, buffer);
writePcm32bitFloat(val, buffer); }
} } else {
break; for (int i = position; i < limit; i += 3) {
case C.ENCODING_PCM_32BIT: int pcm32BitInteger =
// 32->32 bit conversion. ((inputBuffer.get(i) & 0xFF) << 8)
for (int i = offset; i < limit; i += 4) { | ((inputBuffer.get(i + 1) & 0xFF) << 16)
int val = inputBuffer.get(i) & 0x000000ff | (inputBuffer.get(i) << 8) & 0x0000ff00 | | ((inputBuffer.get(i + 2) & 0xFF) << 24);
(inputBuffer.get(i + 1) << 16) & 0x00ff0000 | (inputBuffer.get(i + 2) << 24) & 0xff000000; writePcm32BitFloat(pcm32BitInteger, buffer);
writePcm32bitFloat(val, buffer); }
}
break;
case C.ENCODING_PCM_8BIT:
case C.ENCODING_PCM_16BIT:
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_INVALID:
case Format.NO_VALUE:
default:
// Never happens.
throw new IllegalStateException();
} }
inputBuffer.position(inputBuffer.limit()); inputBuffer.position(inputBuffer.limit());
@ -178,17 +157,17 @@ import java.nio.ByteOrder;
} }
/** /**
* Converts the provided value into 32-bit float PCM and writes to buffer. * Converts the provided 32-bit integer to a 32-bit float value and writes it to {@code buffer}.
* *
* @param val 32-bit int value to convert to 32-bit float [-1.0, 1.0] * @param pcm32BitInt The 32-bit integer value to convert to 32-bit float in [-1.0, 1.0].
* @param buffer The output buffer. * @param buffer The output buffer.
*/ */
private static void writePcm32bitFloat(int val, ByteBuffer buffer) { private static void writePcm32BitFloat(int pcm32BitInt, ByteBuffer buffer) {
float convVal = (float) (PCM_INT32_FLOAT * val); float pcm32BitFloat = (float) (PCM_32_BIT_INT_TO_PCM_32_BIT_FLOAT_FACTOR * pcm32BitInt);
int bits = Float.floatToIntBits(convVal); int floatBits = Float.floatToIntBits(pcm32BitFloat);
if (bits == 0x7fc00000) if (floatBits == FLOAT_NAN_AS_INT) {
bits = Float.floatToIntBits((float) 0.0); floatBits = Float.floatToIntBits((float) 0.0);
buffer.putInt(bits); }
buffer.putInt(floatBits);
} }
} }

View File

@ -21,7 +21,8 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
/** /**
* An {@link AudioProcessor} that converts audio data to {@link C#ENCODING_PCM_16BIT}. * An {@link AudioProcessor} that converts 8-bit, 24-bit and 32-bit integer PCM audio to 16-bit
* integer PCM audio.
*/ */
/* package */ final class ResamplingAudioProcessor implements AudioProcessor { /* package */ final class ResamplingAudioProcessor implements AudioProcessor {

View File

@ -27,21 +27,21 @@ import java.lang.reflect.InvocationTargetException;
* A {@link DataSource} that supports multiple URI schemes. The supported schemes are: * A {@link DataSource} that supports multiple URI schemes. The supported schemes are:
* *
* <ul> * <ul>
* <li>file: For fetching data from a local file (e.g. file:///path/to/media/media.mp4, or just * <li>file: For fetching data from a local file (e.g. file:///path/to/media/media.mp4, or just
* /path/to/media/media.mp4 because the implementation assumes that a URI without a scheme is a * /path/to/media/media.mp4 because the implementation assumes that a URI without a scheme is
* local file URI). * a local file URI).
* <li>asset: For fetching data from an asset in the application's apk (e.g. asset:///media.mp4). * <li>asset: For fetching data from an asset in the application's apk (e.g. asset:///media.mp4).
* <li>rawresource: For fetching data from a raw resource in the applications' apk * <li>rawresource: For fetching data from a raw resource in the application's apk (e.g.
* (e.g. rawresource:///resourceId, where rawResourceId is the integer identifier of the raw * rawresource:///resourceId, where rawResourceId is the integer identifier of the raw
* resource).</li> * resource).
* <li>content: For fetching data from a content URI (e.g. content://authority/path/123). * <li>content: For fetching data from a content URI (e.g. content://authority/path/123).
* <li>rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an * <li>rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an
* explicit dependency on ExoPlayer's RTMP extension.</li> * explicit dependency on ExoPlayer's RTMP extension.
* <li>data: For parsing data inlined in the URI as defined in RFC 2397.</li> * <li>data: For parsing data inlined in the URI as defined in RFC 2397.
* <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4), if * <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4),
* constructed using {@link #DefaultDataSource(Context, TransferListener, String, boolean)}, or * if constructed using {@link #DefaultDataSource(Context, TransferListener, String,
* any other schemes supported by a base data source if constructed using * boolean)}, or any other schemes supported by a base data source if constructed using {@link
* {@link #DefaultDataSource(Context, TransferListener, DataSource)}.</li> * #DefaultDataSource(Context, TransferListener, DataSource)}.
* </ul> * </ul>
*/ */
public final class DefaultDataSource implements DataSource { public final class DefaultDataSource implements DataSource {

View File

@ -58,6 +58,7 @@ public final class RawResourceDataSource implements DataSource {
return Uri.parse(RAW_RESOURCE_SCHEME + ":///" + rawResourceId); return Uri.parse(RAW_RESOURCE_SCHEME + ":///" + rawResourceId);
} }
/** The scheme part of a raw resource URI. */
public static final String RAW_RESOURCE_SCHEME = "rawresource"; public static final String RAW_RESOURCE_SCHEME = "rawresource";
private final Resources resources; private final Resources resources;

View File

@ -941,6 +941,16 @@ public final class Util {
} }
} }
/**
* Returns whether {@code encoding} is high resolution (> 16-bit) integer PCM.
*
* @param encoding The encoding of the audio data.
* @return Whether the encoding is high resolution integer PCM.
*/
public static boolean isEncodingHighResolutionIntegerPcm(@C.PcmEncoding int encoding) {
return encoding == C.ENCODING_PCM_24BIT || encoding == C.ENCODING_PCM_32BIT;
}
/** /**
* Returns the frame size for audio with {@code channelCount} channels in the specified encoding. * Returns the frame size for audio with {@code channelCount} channels in the specified encoding.
* *