Skip to content

Commit

Permalink
Use maximum bitrates for encoded output buffer sizes
Browse files Browse the repository at this point in the history
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:/google/moe
MOE_MIGRATED_REVID=206749222
  • Loading branch information
andrewlewis authored and ojw28 committed Aug 1, 2018
1 parent 02e9972 commit 7ead310
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
3 changes: 3 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
map.
* Add support for mu-law and A-law PCM with the ffmpeg extension
([#4360](https:/google/ExoPlayer/issues/4360)).
* Increase `AudioTrack` buffer sizes to the theoretical maximum required for
each encoding for passthrough playbacks
([#3803](https:/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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
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;
Expand Down Expand Up @@ -465,29 +466,22 @@ && isInitialized()
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);
}
}

Expand Down Expand Up @@ -1153,6 +1147,33 @@ private static int getChannelConfig(int channelCount, boolean isInputPcm) {
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);
Expand Down

0 comments on commit 7ead310

Please sign in to comment.