Fix playback speed change not working on DTS and other passthrough audio formats

This commit is contained in:
HALİL İBRAHİM ÖZDEMİR 2026-04-02 11:49:27 +03:00
parent 44965795cf
commit 6e32d95961
4 changed files with 57 additions and 19 deletions

View file

@ -16,16 +16,16 @@ internal class PlaybackSpeedAwareAudioOutputProvider(
private var playbackSpeed: Float = 1f
@Volatile
private var forcePcmForCurrentEac3Session: Boolean = false
private var forcePcmForCurrentSession: Boolean = false
fun updatePlaybackSpeed(speed: Float, selectedAudioIsEac3: Boolean = false) {
fun updatePlaybackSpeed(speed: Float, selectedAudioRequiresPcmForSpeed: Boolean = false) {
val normalizedSpeed = speed.takeIf { it > 0f } ?: 1f
val wasForcingPcm = forcePcmForCurrentEac3Session
if (selectedAudioIsEac3 && normalizedSpeed != 1f) {
forcePcmForCurrentEac3Session = true
val wasForcingPcm = forcePcmForCurrentSession
if (selectedAudioRequiresPcmForSpeed && normalizedSpeed != 1f) {
forcePcmForCurrentSession = true
}
playbackSpeed = normalizedSpeed
val isForcingPcm = forcePcmForCurrentEac3Session
val isForcingPcm = forcePcmForCurrentSession
if (wasForcingPcm != isForcingPcm) {
listeners.forEach(AudioOutputProvider.Listener::onFormatSupportChanged)
}
@ -52,13 +52,33 @@ internal class PlaybackSpeedAwareAudioOutputProvider(
}
private fun shouldForcePcm(format: Format): Boolean {
if (!forcePcmForCurrentEac3Session) {
if (!forcePcmForCurrentSession) {
return false
}
return when (format.sampleMimeType) {
MimeTypes.AUDIO_E_AC3,
MimeTypes.AUDIO_E_AC3_JOC -> true
else -> format.codecs?.contains("ec-3", ignoreCase = true) == true
val mimeType = format.sampleMimeType
if (mimeType != null && (
mimeType == MimeTypes.AUDIO_E_AC3 ||
mimeType == MimeTypes.AUDIO_E_AC3_JOC ||
mimeType == MimeTypes.AUDIO_AC3 ||
mimeType == MimeTypes.AUDIO_AC4 ||
mimeType == MimeTypes.AUDIO_TRUEHD ||
mimeType == MimeTypes.AUDIO_DTS ||
mimeType == MimeTypes.AUDIO_DTS_HD ||
mimeType == MimeTypes.AUDIO_DTS_EXPRESS ||
mimeType.startsWith("audio/vnd.dts")
)
) {
return true
}
val codecs = format.codecs
if (codecs != null) {
return codecs.contains("ac-3", ignoreCase = true) ||
codecs.contains("ac-4", ignoreCase = true) ||
codecs.contains("ec-3", ignoreCase = true) ||
codecs.contains("dts", ignoreCase = true) ||
codecs.contains("truehd", ignoreCase = true) ||
codecs.contains("dtshd", ignoreCase = true)
}
return false
}
}

View file

@ -231,7 +231,7 @@ internal fun PlayerRuntimeController.initializePlayer(url: String, headers: Map<
setAudioAttributes(audioAttributes, true)
playbackSpeedAwareAudioOutputProvider?.updatePlaybackSpeed(
_uiState.value.playbackSpeed,
selectedAudioIsEac3(this)
selectedAudioRequiresPcmForSpeed(this)
)
setPlaybackSpeed(_uiState.value.playbackSpeed)

View file

@ -560,10 +560,10 @@ fun PlayerRuntimeController.onEvent(event: PlayerEvent) {
}
}
is PlayerEvent.OnSetPlaybackSpeed -> {
val selectedAudioIsEac3 = _exoPlayer?.let(::selectedAudioIsEac3) == true
val requiresPcm = _exoPlayer?.let(::selectedAudioRequiresPcmForSpeed) == true
playbackSpeedAwareAudioOutputProvider?.updatePlaybackSpeed(
event.speed,
selectedAudioIsEac3 = selectedAudioIsEac3
selectedAudioRequiresPcmForSpeed = requiresPcm
)
_exoPlayer?.let { player ->
player.setPlaybackSpeed(event.speed)

View file

@ -42,18 +42,36 @@ internal fun PlayerRuntimeController.showSeekOverlayTemporarily() {
}
}
internal fun PlayerRuntimeController.selectedAudioIsEac3(player: Player): Boolean {
internal fun PlayerRuntimeController.selectedAudioRequiresPcmForSpeed(player: Player): Boolean {
player.currentTracks.groups.forEach { trackGroup ->
if (trackGroup.type != C.TRACK_TYPE_AUDIO) return@forEach
for (i in 0 until trackGroup.length) {
if (!trackGroup.isTrackSelected(i)) continue
val format = trackGroup.getTrackFormat(i)
val sampleMimeType = format.sampleMimeType
if (sampleMimeType == MimeTypes.AUDIO_E_AC3 || sampleMimeType == MimeTypes.AUDIO_E_AC3_JOC) {
val mimeType = format.sampleMimeType
if (mimeType != null && (
mimeType == MimeTypes.AUDIO_E_AC3 ||
mimeType == MimeTypes.AUDIO_E_AC3_JOC ||
mimeType == MimeTypes.AUDIO_AC3 ||
mimeType == MimeTypes.AUDIO_AC4 ||
mimeType == MimeTypes.AUDIO_TRUEHD ||
mimeType == MimeTypes.AUDIO_DTS ||
mimeType == MimeTypes.AUDIO_DTS_HD ||
mimeType == MimeTypes.AUDIO_DTS_EXPRESS ||
mimeType.startsWith("audio/vnd.dts")
)) {
return true
}
if (format.codecs?.contains("ec-3", ignoreCase = true) == true) {
return true
val codecs = format.codecs
if (codecs != null) {
if (codecs.contains("ac-3", ignoreCase = true) ||
codecs.contains("ac-4", ignoreCase = true) ||
codecs.contains("ec-3", ignoreCase = true) ||
codecs.contains("dts", ignoreCase = true) ||
codecs.contains("truehd", ignoreCase = true) ||
codecs.contains("dtshd", ignoreCase = true)) {
return true
}
}
}
}