From a50eebb442ce280946a1b1d4b764168172f3a941 Mon Sep 17 00:00:00 2001 From: SkyD666 Date: Sun, 19 May 2024 22:07:35 +0800 Subject: [PATCH] [feature] Support configure hardware decoding --- app/build.gradle.kts | 2 +- .../java/com/skyd/anivu/ext/PreferenceExt.kt | 2 ++ .../skyd/anivu/model/preference/Settings.kt | 4 +++ .../player/HardwareDecodePreference.kt | 26 +++++++++++++++++++ .../advanced/PlayerConfigAdvancedFragment.kt | 21 +++++++++++++++ .../com/skyd/anivu/ui/local/LocalValue.kt | 4 ++- .../java/com/skyd/anivu/ui/mpv/MPVView.kt | 13 +++++----- app/src/main/res/values-zh-rCN/strings.xml | 3 +++ app/src/main/res/values/strings.xml | 2 ++ 9 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/skyd/anivu/model/preference/player/HardwareDecodePreference.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 45c50590..1fedf653 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -21,7 +21,7 @@ android { minSdk = 24 targetSdk = 34 versionCode = 16 - versionName = "1.1-beta29" + versionName = "1.1-beta30" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt b/app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt index cb273c77..c0cb6fb8 100644 --- a/app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt +++ b/app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt @@ -13,6 +13,7 @@ import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPr import com.skyd.anivu.model.preference.behavior.article.ArticleTapActionPreference import com.skyd.anivu.model.preference.behavior.article.DeduplicateTitleInDescPreference import com.skyd.anivu.model.preference.behavior.feed.HideEmptyDefaultPreference +import com.skyd.anivu.model.preference.player.HardwareDecodePreference import com.skyd.anivu.model.preference.player.PlayerDoubleTapPreference import com.skyd.anivu.model.preference.player.PlayerShow85sButtonPreference import com.skyd.anivu.model.preference.player.PlayerShowScreenshotButtonPreference @@ -40,5 +41,6 @@ fun Preferences.toSettings(): Settings { playerDoubleTap = PlayerDoubleTapPreference.fromPreferences(this), playerShow85sButton = PlayerShow85sButtonPreference.fromPreferences(this), playerShowScreenshotButton = PlayerShowScreenshotButtonPreference.fromPreferences(this), + hardwareDecode = HardwareDecodePreference.fromPreferences(this), ) } diff --git a/app/src/main/java/com/skyd/anivu/model/preference/Settings.kt b/app/src/main/java/com/skyd/anivu/model/preference/Settings.kt index 47af13e5..b37cc4e3 100644 --- a/app/src/main/java/com/skyd/anivu/model/preference/Settings.kt +++ b/app/src/main/java/com/skyd/anivu/model/preference/Settings.kt @@ -18,6 +18,7 @@ import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPr import com.skyd.anivu.model.preference.behavior.article.ArticleTapActionPreference import com.skyd.anivu.model.preference.behavior.article.DeduplicateTitleInDescPreference import com.skyd.anivu.model.preference.behavior.feed.HideEmptyDefaultPreference +import com.skyd.anivu.model.preference.player.HardwareDecodePreference import com.skyd.anivu.model.preference.player.PlayerDoubleTapPreference import com.skyd.anivu.model.preference.player.PlayerShow85sButtonPreference import com.skyd.anivu.model.preference.player.PlayerShowScreenshotButtonPreference @@ -27,6 +28,7 @@ import com.skyd.anivu.ui.local.LocalDarkMode import com.skyd.anivu.ui.local.LocalDateStyle import com.skyd.anivu.ui.local.LocalDeduplicateTitleInDesc import com.skyd.anivu.ui.local.LocalFeedGroupExpand +import com.skyd.anivu.ui.local.LocalHardwareDecode import com.skyd.anivu.ui.local.LocalHideEmptyDefault import com.skyd.anivu.ui.local.LocalIgnoreUpdateVersion import com.skyd.anivu.ui.local.LocalNavigationBarLabel @@ -57,6 +59,7 @@ data class Settings( val playerDoubleTap: String = PlayerDoubleTapPreference.default, val playerShow85sButton: Boolean = PlayerShow85sButtonPreference.default, val playerShowScreenshotButton: Boolean = PlayerShowScreenshotButtonPreference.default, + val hardwareDecode: Boolean = HardwareDecodePreference.default, ) @Composable @@ -86,6 +89,7 @@ fun SettingsProvider( LocalPlayerDoubleTap provides settings.playerDoubleTap, LocalPlayerShow85sButton provides settings.playerShow85sButton, LocalPlayerShowScreenshotButton provides settings.playerShowScreenshotButton, + LocalHardwareDecode provides settings.hardwareDecode, ) { content() } diff --git a/app/src/main/java/com/skyd/anivu/model/preference/player/HardwareDecodePreference.kt b/app/src/main/java/com/skyd/anivu/model/preference/player/HardwareDecodePreference.kt new file mode 100644 index 00000000..e954b02b --- /dev/null +++ b/app/src/main/java/com/skyd/anivu/model/preference/player/HardwareDecodePreference.kt @@ -0,0 +1,26 @@ +package com.skyd.anivu.model.preference.player + +import android.content.Context +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.booleanPreferencesKey +import com.skyd.anivu.base.BasePreference +import com.skyd.anivu.ext.dataStore +import com.skyd.anivu.ext.put +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +object HardwareDecodePreference : BasePreference { + private const val HARDWARE_DECODE = "hardwareDecode" + override val default = true + + val key = booleanPreferencesKey(HARDWARE_DECODE) + + fun put(context: Context, scope: CoroutineScope, value: Boolean) { + scope.launch(Dispatchers.IO) { + context.dataStore.put(key, value) + } + } + + override fun fromPreferences(preferences: Preferences): Boolean = preferences[key] ?: default +} \ No newline at end of file diff --git a/app/src/main/java/com/skyd/anivu/ui/fragment/settings/playerconfig/advanced/PlayerConfigAdvancedFragment.kt b/app/src/main/java/com/skyd/anivu/ui/fragment/settings/playerconfig/advanced/PlayerConfigAdvancedFragment.kt index fc5b6bfb..fb8ac818 100644 --- a/app/src/main/java/com/skyd/anivu/ui/fragment/settings/playerconfig/advanced/PlayerConfigAdvancedFragment.kt +++ b/app/src/main/java/com/skyd/anivu/ui/fragment/settings/playerconfig/advanced/PlayerConfigAdvancedFragment.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.PlayCircle +import androidx.compose.material.icons.rounded.DeveloperBoard import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults @@ -20,14 +21,18 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import com.skyd.anivu.R import com.skyd.anivu.base.BaseComposeFragment +import com.skyd.anivu.model.preference.player.HardwareDecodePreference import com.skyd.anivu.model.preference.player.MpvConfigPreference import com.skyd.anivu.ui.component.AniVuTopBar import com.skyd.anivu.ui.component.AniVuTopBarStyle import com.skyd.anivu.ui.component.BaseSettingsItem +import com.skyd.anivu.ui.component.SwitchSettingsItem import com.skyd.anivu.ui.component.dialog.TextFieldDialog +import com.skyd.anivu.ui.local.LocalHardwareDecode import dagger.hilt.android.AndroidEntryPoint @@ -43,6 +48,7 @@ class PlayerConfigAdvancedFragment : BaseComposeFragment() { @Composable fun PlayerConfigAdvancedScreen() { val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() + val context = LocalContext.current val scope = rememberCoroutineScope() var mpvConfEditDialogValue by rememberSaveable { mutableStateOf("") } var openMpvConfEditDialog by rememberSaveable { mutableStateOf(false) } @@ -62,6 +68,21 @@ fun PlayerConfigAdvancedScreen() { .nestedScroll(scrollBehavior.nestedScrollConnection), contentPadding = paddingValues, ) { + item { + SwitchSettingsItem( + imageVector = Icons.Rounded.DeveloperBoard, + text = stringResource(id = R.string.player_config_advanced_screen_hardware_decode), + description = stringResource(id = R.string.player_config_advanced_screen_hardware_decode_description), + checked = LocalHardwareDecode.current, + onCheckedChange = { + HardwareDecodePreference.put( + context = context, + scope = scope, + value = it, + ) + } + ) + } item { BaseSettingsItem( icon = rememberVectorPainter(Icons.Outlined.PlayCircle), diff --git a/app/src/main/java/com/skyd/anivu/ui/local/LocalValue.kt b/app/src/main/java/com/skyd/anivu/ui/local/LocalValue.kt index 1a9c2559..2d4279a7 100644 --- a/app/src/main/java/com/skyd/anivu/ui/local/LocalValue.kt +++ b/app/src/main/java/com/skyd/anivu/ui/local/LocalValue.kt @@ -14,6 +14,7 @@ import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPr import com.skyd.anivu.model.preference.behavior.article.ArticleTapActionPreference import com.skyd.anivu.model.preference.behavior.article.DeduplicateTitleInDescPreference import com.skyd.anivu.model.preference.behavior.feed.HideEmptyDefaultPreference +import com.skyd.anivu.model.preference.player.HardwareDecodePreference import com.skyd.anivu.model.preference.player.PlayerDoubleTapPreference import com.skyd.anivu.model.preference.player.PlayerShow85sButtonPreference import com.skyd.anivu.model.preference.player.PlayerShowScreenshotButtonPreference @@ -46,4 +47,5 @@ val LocalHideEmptyDefault = compositionLocalOf { HideEmptyDefaultPreference.defa // Player val LocalPlayerDoubleTap = compositionLocalOf { PlayerDoubleTapPreference.default } val LocalPlayerShow85sButton = compositionLocalOf { PlayerShow85sButtonPreference.default } -val LocalPlayerShowScreenshotButton = compositionLocalOf { PlayerShowScreenshotButtonPreference.default } \ No newline at end of file +val LocalPlayerShowScreenshotButton = compositionLocalOf { PlayerShowScreenshotButtonPreference.default } +val LocalHardwareDecode = compositionLocalOf { HardwareDecodePreference.default } \ No newline at end of file diff --git a/app/src/main/java/com/skyd/anivu/ui/mpv/MPVView.kt b/app/src/main/java/com/skyd/anivu/ui/mpv/MPVView.kt index c20404b7..fc4501ac 100644 --- a/app/src/main/java/com/skyd/anivu/ui/mpv/MPVView.kt +++ b/app/src/main/java/com/skyd/anivu/ui/mpv/MPVView.kt @@ -8,6 +8,9 @@ import android.view.SurfaceHolder import android.view.SurfaceView import android.view.WindowManager import com.skyd.anivu.config.Const +import com.skyd.anivu.ext.dataStore +import com.skyd.anivu.ext.getOrDefault +import com.skyd.anivu.model.preference.player.HardwareDecodePreference import `is`.xyz.mpv.MPVLib import `is`.xyz.mpv.MPVLib.mpvFormat.MPV_FORMAT_DOUBLE import `is`.xyz.mpv.MPVLib.mpvFormat.MPV_FORMAT_FLAG @@ -69,9 +72,6 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att // vo voInUse = vo - // hwdec - val hwdec = "auto"//"no" - // vo: set display fps as reported by android val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager val disp = wm.defaultDisplay @@ -84,8 +84,10 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att MPVLib.setOptionString("vo", vo) MPVLib.setOptionString("gpu-context", "android") MPVLib.setOptionString("opengl-es", "yes") - MPVLib.setOptionString("hwdec", hwdec) -// MPVLib.setOptionString("hwdec-codecs", "h264,hevc,mpeg4,mpeg2video,vp8,vp9,av1") + MPVLib.setOptionString( + "hwdec", + if (context.dataStore.getOrDefault(HardwareDecodePreference)) "auto" else "no" + ) MPVLib.setOptionString("ao", "audiotrack,opensles") MPVLib.setOptionString("input-default-bindings", "yes") // Limit demuxer cache since the defaults are too high for mobile devices @@ -121,7 +123,6 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att Property("eof-reached", MPV_FORMAT_FLAG), Property("paused-for-cache", MPV_FORMAT_FLAG), Property("track-list"), - Property("sub-add"), // observing double properties is not hooked up in the JNI code, but doing this // will restrict updates to when it actually changes Property("video-zoom", MPV_FORMAT_DOUBLE), diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index eac831d4..c8eefc66 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -208,6 +208,9 @@ 截图 无权限。无法保存截图。 截图按钮 + 添加字幕文件 + 硬件解码 + 优先使用硬件解码,失败时改用软件解码。 每 %d 分钟 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d1cb3ba5..96d71b71 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -217,6 +217,8 @@ No permission. Can\'t save screenshot. Screenshot button Add subtitle file + Hardware decoding + Try hardware decoding first; fallback to software if it fails Every %d minute Every %d minutes