diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerActivity.kt
index c816a60e4..2eb7b994c 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerActivity.kt
@@ -322,6 +322,8 @@ class PlayerActivity :
setMpvConf()
val logLevel = if (networkPreferences.verboseLogging().get()) "info" else "warn"
player.initialize(applicationContext.filesDir.path, logLevel)
+ val hwDec = playerPreferences.standardHwDec().get()
+ MPVLib.setOptionString("hwdec", hwDec)
MPVLib.setOptionString("keep-open", "always")
MPVLib.setOptionString("ytdl", "no")
MPVLib.addLogObserver(this)
@@ -1054,8 +1056,23 @@ class PlayerActivity :
@Suppress("UNUSED_PARAMETER")
fun switchDecoder(view: View) {
- player.cycleHwdec()
- playerPreferences.playerViewMode().get()
+ val standardHwDec = playerPreferences.standardHwDec().get()
+ val currentHwDec = player.hwdecActive
+
+ if (standardHwDec == currentHwDec) {
+ val hwDecEnabled = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ "mediacodec"
+ } else {
+ "mediacodec-copy"
+ }
+ val otherHwDec = when (standardHwDec) {
+ "no" -> hwDecEnabled
+ else -> "no"
+ }
+ MPVLib.setPropertyString("hwdec", otherHwDec)
+ } else {
+ MPVLib.setOptionString("hwdec", standardHwDec)
+ }
playerControls.updateDecoderButton()
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerControlsView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerControlsView.kt
index 6a21681f3..aeaf50b57 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerControlsView.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerControlsView.kt
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.player
import android.annotation.SuppressLint
import android.content.Context
import android.content.ContextWrapper
+import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.AttributeSet
@@ -148,6 +149,7 @@ class PlayerControlsView @JvmOverloads constructor(context: Context, attrs: Attr
// Long click controls
binding.cycleSpeedBtn.setOnLongClickListener { pickSpeed(); true }
+ binding.cycleDecoderBtn.setOnLongClickListener { pickDecoder(); true }
binding.playbackSeekbar.setOnSeekBarChangeListener(seekBarChangeListener)
@@ -362,6 +364,34 @@ class PlayerControlsView @JvmOverloads constructor(context: Context, attrs: Attr
}
}
+ private fun pickDecoder() {
+ val restore = pauseForDialog()
+
+ val items = mutableListOf(
+ Pair("HW (mediacodec-copy)", "mediacodec-copy"),
+ Pair("SW", "no"),
+ )
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ items.add(0, Pair("HW+ (mediacodec)", "mediacodec"))
+ }
+ var hwdecActive = playerPreferences.standardHwDec().get()
+ val selectedIndex = items.indexOfFirst { it.second == hwdecActive }
+ with(activity.HideBarsMaterialAlertDialogBuilder(activity)) {
+ setTitle(R.string.player_hwdec_dialog_title)
+ setSingleChoiceItems(items.map { it.first }.toTypedArray(), selectedIndex) { _, idx ->
+ hwdecActive = items[idx].second
+ }
+ setPositiveButton(R.string.dialog_ok) { _, _ ->
+ playerPreferences.standardHwDec().set(hwdecActive)
+ MPVLib.setPropertyString("hwdec", hwdecActive)
+ }
+ setNegativeButton(R.string.dialog_cancel) { dialog, _ -> dialog.cancel() }
+ setOnDismissListener { restore() }
+ create()
+ show()
+ }
+ }
+
private fun speedPickerDialog(
picker: PickerDialog,
@StringRes titleRes: Int,
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/player/setting/PlayerPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/player/setting/PlayerPreferences.kt
index c714c6ee4..05caa8d2b 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/player/setting/PlayerPreferences.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/player/setting/PlayerPreferences.kt
@@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.player.setting
+import android.os.Build
import eu.kanade.tachiyomi.core.preference.PreferenceStore
class PlayerPreferences(
@@ -64,4 +65,11 @@ class PlayerPreferences(
fun waitingTimeAniSkip() = preferenceStore.getInt("pref_waiting_time_aniskip", 5)
fun enableNetflixStyleAniSkip() = preferenceStore.getBoolean("pref_enable_netflixStyle_aniskip", false)
+
+ private val defaultHwDec = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ "mediacodec"
+ } else {
+ "mediacodec-copy"
+ }
+ fun standardHwDec() = preferenceStore.getString("pref_hwdec", defaultHwDec)
}
diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml
index bd4c16de1..929e4b68a 100644
--- a/i18n/src/main/res/values/strings.xml
+++ b/i18n/src/main/res/values/strings.xml
@@ -1134,6 +1134,7 @@
Don\'t skip
Skip in %d seconds
%s Skipped
+ Set default hardware decoding mode
See your recently updated library entries