Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to disallow some codecs for exoplayer #1403

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/java/org/jellyfin/mobile/app/AppPreferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, DeviceCodec.Video> = HashMap()
val audioCodecs: MutableMap<String, DeviceCodec.Audio> = HashMap()
Expand All @@ -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)) {
Expand Down Expand Up @@ -99,26 +101,36 @@ class DeviceProfileBuilder(
val directPlayProfiles = ArrayList<DirectPlayProfile>()
val codecProfiles = ArrayList<CodecProfile>()

val disallowedCodecs: List<String> = 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<String> = supportedVideoCodecs[i].filterNot { it in disallowedCodecs }
val filteredAudioList: List<String> = 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<String> = 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(","),
),
)
}
Expand All @@ -131,10 +143,26 @@ class DeviceProfileBuilder(
else -> getSubtitleProfiles(EXO_EMBEDDED_SUBTITLES, EXO_EXTERNAL_SUBTITLES)
}

val filteredTranscodingProfiles: List<TranscodingProfile>
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/org/jellyfin/mobile/utils/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@
<string name="pref_exoplayer_remember_brightness">Remember display brightness</string>
<string name="pref_exoplayer_allow_background_audio">Background audio</string>
<string name="pref_exoplayer_allow_background_audio_summary">Allow playing videos in the background with audio-only</string>
<string name="pref_exoplayer_disallowed_codecs">Disallowed Codecs</string>
<string name="pref_exoplayer_disallowed_codecs_summary">Try to prevent playing some codecs and request transcoding instead.</string>
<string name="pref_exoplayer_disallowed_codecs_hint">A comma-separated list of codecs to exclude from the exoplayer</string>
<string name="pref_exoplayer_direct_play_ass">Allow SSA/ASS subtitles in direct play</string>
<string name="pref_exoplayer_direct_play_ass_summary">Prevent transcoding and show subtitles with basic styling only. Advanced subtitle styling will not be available if enabled.</string>

Expand Down