Skip to content

Commit b1bf25b

Browse files
Add option to not advertise software codecs as supported
Sometimes, software-codecs can cause performance-related issues like seen in #4838. The added option allows disabling software codecs, forcing a transcode to a non-software/hardware-accelerated codec.
1 parent bb239f5 commit b1bf25b

File tree

7 files changed

+41
-0
lines changed

7 files changed

+41
-0
lines changed

app/src/main/java/org/jellyfin/androidtv/preference/UserPreferences.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
236236
* Enable PGS subtitle direct-play.
237237
*/
238238
var pgsDirectPlay = booleanPreference("pgs_enabled", true)
239+
240+
/**
241+
* Enable the use of software-based codecs.
242+
*/
243+
var useSoftwareCodecs = booleanPreference("use_software_codecs", true)
239244
}
240245

241246
init {

app/src/main/java/org/jellyfin/androidtv/ui/settings/screen/playback/SettingsPlaybackAdvancedScreen.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,16 @@ fun SettingsPlaybackAdvancedScreen() {
185185
)
186186
}
187187

188+
item {
189+
var useSoftwareCodecs by rememberPreference(userPreferences, UserPreferences.useSoftwareCodecs)
190+
191+
ListButton(
192+
headingContent = { Text(stringResource(R.string.pref_use_software_codecs)) },
193+
trailingContent = { Checkbox(checked = useSoftwareCodecs) },
194+
onClick = { useSoftwareCodecs = !useSoftwareCodecs }
195+
)
196+
}
197+
188198
item { ListSection(headingContent = { Text(stringResource(R.string.pref_live_tv_cat)) }) }
189199

190200
item {

app/src/main/java/org/jellyfin/androidtv/util/profile/MediaCodecCapabilitiesTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jellyfin.androidtv.util.profile
22

33
import android.content.Context
4+
import android.media.MediaCodecInfo
45
import android.media.MediaCodecInfo.CodecProfileLevel
56
import android.media.MediaCodecList
67
import android.media.MediaFormat
@@ -15,6 +16,7 @@ class MediaCodecCapabilitiesTest(
1516
) {
1617
private val display by lazy { ContextCompat.getDisplayOrDefault(context) }
1718
private val mediaCodecList by lazy { MediaCodecList(MediaCodecList.REGULAR_CODECS) }
19+
var useSoftwareCodecs = true
1820

1921
// Map common Dolby Vision Profiles to their corresponding CodecProfileLevel constant
2022
private object DolbyVisionProfiles {
@@ -207,6 +209,7 @@ class MediaCodecCapabilitiesTest(
207209

208210
for (info in mediaCodecList.codecInfos) {
209211
if (info.isEncoder) continue
212+
if (!useSoftwareCodecs && info.isSoftwareCodec()) continue
210213

211214
try {
212215
val capabilities = info.getCapabilitiesForType(mime)
@@ -226,6 +229,7 @@ class MediaCodecCapabilitiesTest(
226229
private fun hasDecoder(mime: String, profile: Int, level: Int): Boolean {
227230
for (info in mediaCodecList.codecInfos) {
228231
if (info.isEncoder) continue
232+
if (!useSoftwareCodecs && info.isSoftwareCodec()) continue
229233

230234
try {
231235
val capabilities = info.getCapabilitiesForType(mime)
@@ -253,6 +257,7 @@ class MediaCodecCapabilitiesTest(
253257
private fun hasCodecForMime(mime: String): Boolean {
254258
for (info in mediaCodecList.codecInfos) {
255259
if (info.isEncoder) continue
260+
if (!useSoftwareCodecs && info.isSoftwareCodec()) continue
256261

257262
if (info.supportedTypes.any { it.equals(mime, ignoreCase = true) }) {
258263
Timber.i("found codec %s for mime %s", info.name, mime)
@@ -268,6 +273,7 @@ class MediaCodecCapabilitiesTest(
268273

269274
for (info in mediaCodecList.codecInfos) {
270275
if (info.isEncoder) continue
276+
if (!useSoftwareCodecs && info.isSoftwareCodec()) continue
271277

272278
try {
273279
val types = info.getSupportedTypes()
@@ -289,6 +295,7 @@ class MediaCodecCapabilitiesTest(
289295

290296
for (info in mediaCodecList.codecInfos) {
291297
if (info.isEncoder) continue
298+
if (!useSoftwareCodecs && info.isSoftwareCodec()) continue
292299

293300
try {
294301
val capabilities = info.getCapabilitiesForType(mime)
@@ -308,4 +315,16 @@ class MediaCodecCapabilitiesTest(
308315

309316
return Size(maxWidth, maxHeight)
310317
}
318+
319+
private fun MediaCodecInfo.isSoftwareCodec(): Boolean {
320+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
321+
this.isSoftwareOnly
322+
} else {
323+
val name = this.name
324+
325+
// detect software-based codecs by name; approach taken from here:
326+
// https://android.googlesource.com/platform/frameworks/av/+/d5dbc2b31c492be23fc4d4a96619330b63499b06/media/libstagefright/MediaCodecList.cpp#364
327+
name.startsWith("OMX.google.", ignoreCase = true) || name.startsWith("c2.android.", ignoreCase = true)
328+
}
329+
}
311330
}

app/src/main/java/org/jellyfin/androidtv/util/profile/deviceProfile.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ fun createDeviceProfile(
8585
downMixAudio = userPreferences[UserPreferences.audioBehaviour] == AudioBehavior.DOWNMIX_TO_STEREO,
8686
assDirectPlay = false,
8787
pgsDirectPlay = userPreferences[UserPreferences.pgsDirectPlay],
88+
useSoftwareCodecs = userPreferences[UserPreferences.useSoftwareCodecs],
8889
)
8990

9091
fun createDeviceProfile(
@@ -94,7 +95,10 @@ fun createDeviceProfile(
9495
downMixAudio: Boolean,
9596
assDirectPlay: Boolean,
9697
pgsDirectPlay: Boolean,
98+
useSoftwareCodecs: Boolean,
9799
) = buildDeviceProfile {
100+
mediaTest.useSoftwareCodecs = useSoftwareCodecs
101+
98102
val allowedAudioCodecs = when {
99103
downMixAudio -> downmixSupportedAudioCodecs
100104
!isAC3Enabled -> supportedAudioCodecs.filterNot { it == Codec.Audio.EAC3 || it == Codec.Audio.AC3 }.toTypedArray()

app/src/main/res/values-de/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,4 +621,5 @@
621621
<string name="video_player_internal">Eingebauter Videoplayer</string>
622622
<string name="video_player_external">Externe App</string>
623623
<string name="filters">Filter</string>
624+
<string name="pref_use_software_codecs">Software-Codecs verwenden</string>
624625
</resources>

app/src/main/res/values-en-rGB/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,4 +621,5 @@
621621
<string name="video_player_external">External app</string>
622622
<string name="playback_video_player_external_empty">You don\'t have any video player apps installed on your device that can open Jellyfin videos.</string>
623623
<string name="filters">Filters</string>
624+
<string name="pref_use_software_codecs">Use software codecs</string>
624625
</resources>

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,4 +621,5 @@
621621
<item quantity="one">%1$s album</item>
622622
<item quantity="other">%1$s albums</item>
623623
</plurals>
624+
<string name="pref_use_software_codecs">Use software codecs</string>
624625
</resources>

0 commit comments

Comments
 (0)