From 043c2a5683b193a20e7afb8f645c433b377d1db1 Mon Sep 17 00:00:00 2001 From: Adam Bielinski Date: Tue, 28 May 2024 21:29:49 -0400 Subject: [PATCH] Add option to remove some available codecs for exoplayer --- .../org/jellyfin/mobile/app/AppPreferences.kt | 3 ++ .../deviceprofile/DeviceProfileBuilder.kt | 36 ++++++++++++++++--- .../mobile/settings/SettingsFragment.kt | 9 +++++ .../org/jellyfin/mobile/utils/Constants.kt | 1 + app/src/main/res/values/strings.xml | 3 ++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/jellyfin/mobile/app/AppPreferences.kt b/app/src/main/java/org/jellyfin/mobile/app/AppPreferences.kt index e4d02a523..f756ba7c5 100644 --- a/app/src/main/java/org/jellyfin/mobile/app/AppPreferences.kt +++ b/app/src/main/java/org/jellyfin/mobile/app/AppPreferences.kt @@ -117,6 +117,9 @@ class AppPreferences(context: Context) { val exoPlayerAllowBackgroundAudio: Boolean get() = sharedPreferences.getBoolean(Constants.PREF_EXOPLAYER_ALLOW_BACKGROUND_AUDIO, false) + val exoPlayerDisallowedCodecs: String? + get() = sharedPreferences.getString(Constants.PREF_EXOPLAYER_DISALLOWED_CODECS, "") + val exoPlayerDirectPlayAss: Boolean get() = sharedPreferences.getBoolean(Constants.PREF_EXOPLAYER_DIRECT_PLAY_ASS, false) diff --git a/app/src/main/java/org/jellyfin/mobile/player/deviceprofile/DeviceProfileBuilder.kt b/app/src/main/java/org/jellyfin/mobile/player/deviceprofile/DeviceProfileBuilder.kt index a1152bfb7..6dd52af97 100644 --- a/app/src/main/java/org/jellyfin/mobile/player/deviceprofile/DeviceProfileBuilder.kt +++ b/app/src/main/java/org/jellyfin/mobile/player/deviceprofile/DeviceProfileBuilder.kt @@ -25,6 +25,7 @@ class DeviceProfileBuilder( SUPPORTED_CONTAINER_FORMATS.size == AVAILABLE_VIDEO_CODECS.size && SUPPORTED_CONTAINER_FORMATS.size == AVAILABLE_AUDIO_CODECS.size, ) + // Load Android-supported codecs val videoCodecs: MutableMap = HashMap() val audioCodecs: MutableMap = HashMap() @@ -35,6 +36,7 @@ class DeviceProfileBuilder( for (mimeType in codecInfo.supportedTypes) { val codec = DeviceCodec.from(codecInfo.getCapabilitiesForType(mimeType)) ?: continue val name = codec.name + when (codec) { is DeviceCodec.Video -> { if (videoCodecs.containsKey(name)) { @@ -99,26 +101,36 @@ class DeviceProfileBuilder( val directPlayProfiles = ArrayList() val codecProfiles = ArrayList() + val disallowedCodecs: List = appPreferences.exoPlayerDisallowedCodecs?.split(",")?.map { it.trim() } ?: emptyList() + + for (i in SUPPORTED_CONTAINER_FORMATS.indices) { val container = SUPPORTED_CONTAINER_FORMATS[i] if (supportedVideoCodecs[i].isNotEmpty()) { + + val filteredVideoList: List = supportedVideoCodecs[i].filterNot { it in disallowedCodecs } + val filteredAudioList: List = supportedAudioCodecs[i].filterNot { it in disallowedCodecs } + containerProfiles.add(ContainerProfile(type = DlnaProfileType.VIDEO, container = container)) directPlayProfiles.add( DirectPlayProfile( type = DlnaProfileType.VIDEO, container = SUPPORTED_CONTAINER_FORMATS[i], - videoCodec = supportedVideoCodecs[i].joinToString(","), - audioCodec = supportedAudioCodecs[i].joinToString(","), + videoCodec = filteredVideoList.joinToString(","), + audioCodec = filteredAudioList.joinToString(","), ), ) } if (supportedAudioCodecs[i].isNotEmpty()) { + + val filteredAudioList: List = supportedAudioCodecs[i].filterNot { it in disallowedCodecs } + containerProfiles.add(ContainerProfile(type = DlnaProfileType.AUDIO, container = container)) directPlayProfiles.add( DirectPlayProfile( type = DlnaProfileType.AUDIO, container = SUPPORTED_CONTAINER_FORMATS[i], - audioCodec = supportedAudioCodecs[i].joinToString(","), + audioCodec = filteredAudioList.joinToString(","), ), ) } @@ -131,10 +143,26 @@ class DeviceProfileBuilder( else -> getSubtitleProfiles(EXO_EMBEDDED_SUBTITLES, EXO_EXTERNAL_SUBTITLES) } + val filteredTranscodingProfiles: List + if (disallowedCodecs.isEmpty()){ + filteredTranscodingProfiles = transcodingProfiles + }else{ + filteredTranscodingProfiles = transcodingProfiles.map { tr -> + TranscodingProfile( + type = tr.type, + container = tr.container, + videoCodec = tr.videoCodec, //.split(",").filterNot { it in disallowedCodecs }.joinToString(","), + audioCodec = tr.audioCodec.split(",").filterNot { it in disallowedCodecs }.joinToString(","), + protocol = tr.protocol, + conditions = tr.conditions + ) + } + } + return DeviceProfile( name = Constants.APP_INFO_NAME, directPlayProfiles = directPlayProfiles, - transcodingProfiles = transcodingProfiles, + transcodingProfiles = filteredTranscodingProfiles, containerProfiles = containerProfiles, codecProfiles = codecProfiles, subtitleProfiles = subtitleProfiles, diff --git a/app/src/main/java/org/jellyfin/mobile/settings/SettingsFragment.kt b/app/src/main/java/org/jellyfin/mobile/settings/SettingsFragment.kt index 3df148885..c20330ccb 100644 --- a/app/src/main/java/org/jellyfin/mobile/settings/SettingsFragment.kt +++ b/app/src/main/java/org/jellyfin/mobile/settings/SettingsFragment.kt @@ -16,6 +16,7 @@ import de.Maxr1998.modernpreferences.helpers.checkBox import de.Maxr1998.modernpreferences.helpers.defaultOnCheckedChange import de.Maxr1998.modernpreferences.helpers.defaultOnClick import de.Maxr1998.modernpreferences.helpers.defaultOnSelectionChange +import de.Maxr1998.modernpreferences.helpers.editText import de.Maxr1998.modernpreferences.helpers.pref import de.Maxr1998.modernpreferences.helpers.screen import de.Maxr1998.modernpreferences.helpers.singleChoice @@ -43,6 +44,7 @@ class SettingsFragment : Fragment(), BackPressInterceptor { private lateinit var rememberBrightnessPreference: Preference private lateinit var backgroundAudioPreference: Preference private lateinit var directPlayAssPreference: Preference + private lateinit var disallowedCodecsPreference: Preference private lateinit var externalPlayerChoicePreference: Preference init { @@ -140,6 +142,13 @@ class SettingsFragment : Fragment(), BackPressInterceptor { enabled = appPreferences.videoPlayerType == VideoPlayerType.EXO_PLAYER } + disallowedCodecsPreference = editText(Constants.PREF_EXOPLAYER_DISALLOWED_CODECS) { + textInputHintRes = R.string.pref_exoplayer_disallowed_codecs_hint + titleRes = R.string.pref_exoplayer_disallowed_codecs + summaryRes = R.string.pref_exoplayer_disallowed_codecs_summary + enabled = appPreferences.videoPlayerType == VideoPlayerType.EXO_PLAYER + } + // Generate available external player options val packageManager = requireContext().packageManager val externalPlayerOptions = listOf( diff --git a/app/src/main/java/org/jellyfin/mobile/utils/Constants.kt b/app/src/main/java/org/jellyfin/mobile/utils/Constants.kt index 57158181c..7bf2765ea 100644 --- a/app/src/main/java/org/jellyfin/mobile/utils/Constants.kt +++ b/app/src/main/java/org/jellyfin/mobile/utils/Constants.kt @@ -38,6 +38,7 @@ object Constants { const val PREF_EXOPLAYER_REMEMBER_BRIGHTNESS = "pref_exoplayer_remember_brightness" const val PREF_EXOPLAYER_BRIGHTNESS = "pref_exoplayer_brightness" const val PREF_EXOPLAYER_ALLOW_BACKGROUND_AUDIO = "pref_exoplayer_allow_background_audio" + const val PREF_EXOPLAYER_DISALLOWED_CODECS = "pref_exoplayer_disallowed_codecs" const val PREF_EXOPLAYER_DIRECT_PLAY_ASS = "pref_exoplayer_direct_play_ass" const val PREF_EXTERNAL_PLAYER_APP = "pref_external_player_app" const val PREF_SUBTITLE_STYLE = "pref_subtitle_style" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 330a048d8..a85b08e35 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -99,6 +99,9 @@ Remember display brightness Background audio Allow playing videos in the background with audio-only + Disallowed Codecs + Try to prevent playing some codecs and request transcoding instead. + A comma-separated list of codecs to exclude from the exoplayer Allow SSA/ASS subtitles in direct play Prevent transcoding and show subtitles with basic styling only. Advanced subtitle styling will not be available if enabled.