Fix DTS Express Audio Buffer Underflow Issue.
This commit is contained in:
parent
a12bde4f57
commit
25acaa1c81
@ -653,6 +653,9 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
boolean enableAudioTrackPlaybackParams;
|
boolean enableAudioTrackPlaybackParams;
|
||||||
boolean enableOffloadGapless = false;
|
boolean enableOffloadGapless = false;
|
||||||
|
|
||||||
|
if (inputFormat.sampleMimeType.contains("audio/vnd.dts")) {
|
||||||
|
DtsUtil.setCurrentMimeType(inputFormat.sampleMimeType);
|
||||||
|
}
|
||||||
if (MimeTypes.AUDIO_RAW.equals(inputFormat.sampleMimeType)) {
|
if (MimeTypes.AUDIO_RAW.equals(inputFormat.sampleMimeType)) {
|
||||||
Assertions.checkArgument(Util.isEncodingLinearPcm(inputFormat.pcmEncoding));
|
Assertions.checkArgument(Util.isEncodingLinearPcm(inputFormat.pcmEncoding));
|
||||||
|
|
||||||
@ -1459,6 +1462,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
playing = false;
|
playing = false;
|
||||||
offloadDisabledUntilNextConfiguration = false;
|
offloadDisabledUntilNextConfiguration = false;
|
||||||
|
DtsUtil.clearCurrentMimeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,6 +26,7 @@ import static java.lang.Math.max;
|
|||||||
import android.media.AudioTrack;
|
import android.media.AudioTrack;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
|
import androidx.media3.common.MimeTypes;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.exoplayer.audio.DefaultAudioSink.OutputMode;
|
import androidx.media3.exoplayer.audio.DefaultAudioSink.OutputMode;
|
||||||
import androidx.media3.extractor.AacUtil;
|
import androidx.media3.extractor.AacUtil;
|
||||||
@ -62,7 +63,11 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
* devices (e.g., Broadcom 7271).
|
* devices (e.g., Broadcom 7271).
|
||||||
*/
|
*/
|
||||||
private static final int AC3_BUFFER_MULTIPLICATION_FACTOR = 2;
|
private static final int AC3_BUFFER_MULTIPLICATION_FACTOR = 2;
|
||||||
|
/**
|
||||||
|
* Default multiplication factor to apply to DTS Express passthrough buffer to avoid underruns
|
||||||
|
* on some devices (e.g., Xiaomi A2 TV).
|
||||||
|
*/
|
||||||
|
private static final int DTSE_BUFFER_MULTIPLICATION_FACTOR = 4;
|
||||||
/** A builder to create {@link DefaultAudioTrackBufferSizeProvider} instances. */
|
/** A builder to create {@link DefaultAudioTrackBufferSizeProvider} instances. */
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
@ -72,7 +77,7 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
private int passthroughBufferDurationUs;
|
private int passthroughBufferDurationUs;
|
||||||
private int offloadBufferDurationUs;
|
private int offloadBufferDurationUs;
|
||||||
private int ac3BufferMultiplicationFactor;
|
private int ac3BufferMultiplicationFactor;
|
||||||
|
private int dtseBufferMultiplicationFactor;
|
||||||
/** Creates a new builder. */
|
/** Creates a new builder. */
|
||||||
public Builder() {
|
public Builder() {
|
||||||
minPcmBufferDurationUs = MIN_PCM_BUFFER_DURATION_US;
|
minPcmBufferDurationUs = MIN_PCM_BUFFER_DURATION_US;
|
||||||
@ -81,6 +86,7 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
passthroughBufferDurationUs = PASSTHROUGH_BUFFER_DURATION_US;
|
passthroughBufferDurationUs = PASSTHROUGH_BUFFER_DURATION_US;
|
||||||
offloadBufferDurationUs = OFFLOAD_BUFFER_DURATION_US;
|
offloadBufferDurationUs = OFFLOAD_BUFFER_DURATION_US;
|
||||||
ac3BufferMultiplicationFactor = AC3_BUFFER_MULTIPLICATION_FACTOR;
|
ac3BufferMultiplicationFactor = AC3_BUFFER_MULTIPLICATION_FACTOR;
|
||||||
|
dtseBufferMultiplicationFactor = DTSE_BUFFER_MULTIPLICATION_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,6 +149,17 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the multiplication factor to apply to the passthrough buffer for DTS Express to avoid
|
||||||
|
* underruns on some devices (e.g., Xiaomi A2 TV). Default is
|
||||||
|
* {@value #DTSE_BUFFER_MULTIPLICATION_FACTOR}.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setDtseBufferMultiplicationFactor(int dtseBufferMultiplicationFactor) {
|
||||||
|
this.dtseBufferMultiplicationFactor = dtseBufferMultiplicationFactor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Build the {@link DefaultAudioTrackBufferSizeProvider}. */
|
/** Build the {@link DefaultAudioTrackBufferSizeProvider}. */
|
||||||
public DefaultAudioTrackBufferSizeProvider build() {
|
public DefaultAudioTrackBufferSizeProvider build() {
|
||||||
return new DefaultAudioTrackBufferSizeProvider(this);
|
return new DefaultAudioTrackBufferSizeProvider(this);
|
||||||
@ -169,7 +186,11 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
* (e.g., Broadcom 7271).
|
* (e.g., Broadcom 7271).
|
||||||
*/
|
*/
|
||||||
public final int ac3BufferMultiplicationFactor;
|
public final int ac3BufferMultiplicationFactor;
|
||||||
|
/**
|
||||||
|
* The multiplication factor to apply to DTS Express passthrough buffer to avoid underruns on some
|
||||||
|
* devices (e.g., Xiaomi A2 TV).
|
||||||
|
*/
|
||||||
|
public final int dtseBufferMultiplicationFactor;
|
||||||
protected DefaultAudioTrackBufferSizeProvider(Builder builder) {
|
protected DefaultAudioTrackBufferSizeProvider(Builder builder) {
|
||||||
minPcmBufferDurationUs = builder.minPcmBufferDurationUs;
|
minPcmBufferDurationUs = builder.minPcmBufferDurationUs;
|
||||||
maxPcmBufferDurationUs = builder.maxPcmBufferDurationUs;
|
maxPcmBufferDurationUs = builder.maxPcmBufferDurationUs;
|
||||||
@ -177,6 +198,7 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
passthroughBufferDurationUs = builder.passthroughBufferDurationUs;
|
passthroughBufferDurationUs = builder.passthroughBufferDurationUs;
|
||||||
offloadBufferDurationUs = builder.offloadBufferDurationUs;
|
offloadBufferDurationUs = builder.offloadBufferDurationUs;
|
||||||
ac3BufferMultiplicationFactor = builder.ac3BufferMultiplicationFactor;
|
ac3BufferMultiplicationFactor = builder.ac3BufferMultiplicationFactor;
|
||||||
|
dtseBufferMultiplicationFactor = builder.dtseBufferMultiplicationFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -232,7 +254,20 @@ public class DefaultAudioTrackBufferSizeProvider
|
|||||||
int bufferSizeUs = passthroughBufferDurationUs;
|
int bufferSizeUs = passthroughBufferDurationUs;
|
||||||
if (encoding == C.ENCODING_AC3) {
|
if (encoding == C.ENCODING_AC3) {
|
||||||
bufferSizeUs *= ac3BufferMultiplicationFactor;
|
bufferSizeUs *= ac3BufferMultiplicationFactor;
|
||||||
|
} else if ((DtsUtil.getCurrentMimeType().contentEquals(MimeTypes.AUDIO_DTS_EXPRESS) && (bitrate
|
||||||
|
!= Format.NO_VALUE)))
|
||||||
|
// DTS Express for streaming uses a frame size (number of audio samples per channel per frame)
|
||||||
|
// of 4096. This requires a higher multiple for the buffersize computation.
|
||||||
|
// Need to use encoding DtsUtil.getCurrentMimeType(). ENCODING_DTS_HD cannot be used
|
||||||
|
// to represent DTS Express as some MTK firmware versions only recognises
|
||||||
|
// ENCODING_DTS for DTS Express passthrough playback.
|
||||||
|
// When bitrate is unknown (e.g. HLS-fMP4), the multiple below is not necessary as the buffer
|
||||||
|
// size is taken care of by getMaximumEncodedRateBytesPerSecond().
|
||||||
|
{
|
||||||
|
// This is necessary to prevent buffer underflow during playback in DASH DTS Express.
|
||||||
|
bufferSizeUs *= dtseBufferMultiplicationFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
int byteRate =
|
int byteRate =
|
||||||
bitrate != Format.NO_VALUE
|
bitrate != Format.NO_VALUE
|
||||||
? divide(bitrate, 8, RoundingMode.CEILING)
|
? divide(bitrate, 8, RoundingMode.CEILING)
|
||||||
|
@ -76,6 +76,19 @@ public final class DtsUtil {
|
|||||||
64, 112, 128, 192, 224, 256, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1920,
|
64, 112, 128, 192, 224, 256, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1920,
|
||||||
2048, 2304, 2560, 2688, 2816, 2823, 2944, 3072, 3840, 4096, 6144, 7680
|
2048, 2304, 2560, 2688, 2816, 2823, 2944, 3072, 3840, 4096, 6144, 7680
|
||||||
};
|
};
|
||||||
|
private static String currentMimeType;
|
||||||
|
|
||||||
|
public static void setCurrentMimeType(String currentMimeType) {
|
||||||
|
DtsUtil.currentMimeType = currentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCurrentMimeType() {
|
||||||
|
return currentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearCurrentMimeType() {
|
||||||
|
currentMimeType = "";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a given integer matches a DTS sync word. Synchronization and storage modes are
|
* Returns whether a given integer matches a DTS sync word. Synchronization and storage modes are
|
||||||
|
Loading…
x
Reference in New Issue
Block a user