mirror of
https://github.com/samsonjs/media.git
synced 2026-04-12 12:25:47 +00:00
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
This commit is contained in:
parent
02e9972630
commit
7ead310219
2 changed files with 41 additions and 17 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue