Commit 7ead3102 by andrewlewis Committed by Oliver Woodman

Use maximum bitrates for encoded output buffer sizes

There is some risk associated with this change, as audio track buffers come from
shared memory and limits may be device-specific. I've tested these sizes on
Nvidia Shield TV and Nexus Player on various builds. The maximum size allocated
is about 800 KB. We could implement support for retrying creating the audio
track if it fails to initialize, but it seems preferable to avoid the extra
complexity required to do that unless we know it's necessary to work around
device-specific limitations.

Issue: #3803

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=206749222
parent 02e99726
......@@ -18,6 +18,9 @@
map.
* Add support for mu-law and A-law PCM with the ffmpeg extension
([#4360](https://github.com/google/ExoPlayer/issues/4360)).
* Increase `AudioTrack` buffer sizes to the theoretical maximum required for
each encoding for passthrough playbacks
([#3803](https://github.com/google/ExoPlayer/issues/3803)).
* Allow apps to pass a `CacheKeyFactory` for setting custom cache keys when
creating a `CacheDataSource`.
* Turned on Java 8 compiler support for the ExoPlayer library. Apps that depend
......
......@@ -26,6 +26,7 @@ import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
......@@ -465,29 +466,22 @@ public final class DefaultAudioSink implements AudioSink {
outputEncoding = encoding;
outputPcmFrameSize =
isInputPcm ? Util.getPcmFrameSize(outputEncoding, channelCount) : C.LENGTH_UNSET;
if (specifiedBufferSize != 0) {
bufferSize = specifiedBufferSize;
} else if (isInputPcm) {
int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, outputEncoding);
bufferSize = specifiedBufferSize != 0 ? specifiedBufferSize : getDefaultBufferSize();
}
private int getDefaultBufferSize() {
if (isInputPcm) {
int minBufferSize =
AudioTrack.getMinBufferSize(outputSampleRate, outputChannelConfig, outputEncoding);
Assertions.checkState(minBufferSize != ERROR_BAD_VALUE);
int multipliedBufferSize = minBufferSize * BUFFER_MULTIPLICATION_FACTOR;
int minAppBufferSize = (int) durationUsToFrames(MIN_BUFFER_DURATION_US) * outputPcmFrameSize;
int maxAppBufferSize = (int) Math.max(minBufferSize,
durationUsToFrames(MAX_BUFFER_DURATION_US) * outputPcmFrameSize);
bufferSize = Util.constrainValue(multipliedBufferSize, minAppBufferSize, maxAppBufferSize);
return Util.constrainValue(multipliedBufferSize, minAppBufferSize, maxAppBufferSize);
} else {
// TODO: Set the minimum buffer size using getMinBufferSize when it takes the encoding into
// account. [Internal: b/25181305]
if (outputEncoding == C.ENCODING_AC3 || outputEncoding == C.ENCODING_E_AC3) {
// AC-3 allows bitrates up to 640 kbit/s.
bufferSize = (int) (PASSTHROUGH_BUFFER_DURATION_US * 80 * 1024 / C.MICROS_PER_SECOND);
} else if (outputEncoding == C.ENCODING_DTS) {
// DTS allows an 'open' bitrate, but we assume the maximum listed value: 1536 kbit/s.
bufferSize = (int) (PASSTHROUGH_BUFFER_DURATION_US * 192 * 1024 / C.MICROS_PER_SECOND);
} else /* outputEncoding == C.ENCODING_DTS_HD || outputEncoding == C.ENCODING_DOLBY_TRUEHD*/ {
// HD passthrough requires a larger buffer to avoid underrun.
bufferSize = (int) (PASSTHROUGH_BUFFER_DURATION_US * 192 * 6 * 1024 / C.MICROS_PER_SECOND);
}
int rate = getMaximumEncodedRateBytesPerSecond(outputEncoding);
return (int) (PASSTHROUGH_BUFFER_DURATION_US * rate / C.MICROS_PER_SECOND);
}
}
......@@ -1153,6 +1147,33 @@ public final class DefaultAudioSink implements AudioSink {
return Util.getAudioTrackChannelConfig(channelCount);
}
private static int getMaximumEncodedRateBytesPerSecond(@C.Encoding int encoding) {
switch (encoding) {
case C.ENCODING_AC3:
return 640 * 1000 / 8;
case C.ENCODING_E_AC3:
return 6144 * 1000 / 8;
case C.ENCODING_DTS:
// DTS allows an 'open' bitrate, but we assume the maximum listed value: 1536 kbit/s.
return 1536 * 1000 / 8;
case C.ENCODING_DTS_HD:
return 18000 * 1000 / 8;
case C.ENCODING_DOLBY_TRUEHD:
return 24500 * 1000 / 8;
case C.ENCODING_INVALID:
case C.ENCODING_PCM_16BIT:
case C.ENCODING_PCM_24BIT:
case C.ENCODING_PCM_32BIT:
case C.ENCODING_PCM_8BIT:
case C.ENCODING_PCM_A_LAW:
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_PCM_MU_LAW:
case Format.NO_VALUE:
default:
throw new IllegalArgumentException();
}
}
private static int getFramesPerEncodedSample(@C.Encoding int encoding, ByteBuffer buffer) {
if (encoding == C.ENCODING_DTS || encoding == C.ENCODING_DTS_HD) {
return DtsUtil.parseDtsAudioSampleCount(buffer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment