diff --git a/.github/workflows/pink.yml b/.github/workflows/pink.yml index 6828dc8272..fa9fdaa29c 100644 --- a/.github/workflows/pink.yml +++ b/.github/workflows/pink.yml @@ -23,15 +23,15 @@ jobs: - name: Rename package run: | export LC_ALL=C - sed -i 's/androidInfo\.supportedAbis\.first/"pink"/g' lib/utils/update.dart - sed -i 's/com\.gucooing\.piliplus/tv\.danmaku\.bili/g' \ + sed -i 's/androidInfo\.supportedAbis\.first/"hdr"/g' lib/utils/update.dart + sed -i 's/com\.gucooing\.piliplus/com\.gucooing\.piliplusxs/g' \ android/app/build.gradle.kts \ android/app/src/profile/AndroidManifest.xml \ android/app/src/main/AndroidManifest.xml \ android/app/src/main/kotlin/com/example/piliplus/MainActivity.kt \ lib/services/audio_handler.dart - grep -n '"pink"' lib/utils/update.dart || echo "update.dart 替换失败" - grep -n 'tv\.danmaku\.bili' android/app/build.gradle.kts | head -2 || echo "build.gradle.kts 替换失败" + grep -n '"hdr"' lib/utils/update.dart || echo "update.dart 替换失败" + grep -n 'com\.gucooing\.piliplusxs' android/app/build.gradle.kts | head -2 || echo "build.gradle.kts 替换失败" shell: bash - name: 构建Java环境 diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3b020913e8..4aeeb164a2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -44,9 +44,6 @@ android:allowBackup="false" android:fullBackupContent="false" tools:replace="android:allowBackup"> - + diff --git a/lib/models/common/video/video_quality.dart b/lib/models/common/video/video_quality.dart index bd91f362e5..f8b9bd7192 100644 --- a/lib/models/common/video/video_quality.dart +++ b/lib/models/common/video/video_quality.dart @@ -23,4 +23,6 @@ enum VideoQuality { static final _codeMap = {for (final i in values) i.code: i}; static VideoQuality fromCode(int code) => _codeMap[code]!; + + bool get isHDR => [hdr, hdrVivid, dolbyVision].contains(this); } diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index d33aeac20a..e34c7363ed 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -213,6 +213,7 @@ class LiveRoomController extends GetxController { isLive: true, autoplay: autoplay, isVertical: isPortrait.value, + canHDR: false, ); } diff --git a/lib/pages/setting/models/play_settings.dart b/lib/pages/setting/models/play_settings.dart index 24206c5195..719b666984 100644 --- a/lib/pages/setting/models/play_settings.dart +++ b/lib/pages/setting/models/play_settings.dart @@ -291,6 +291,29 @@ List get playSettings => [ setKey: SettingBoxKey.tempPlayerConf, defaultVal: false, ), + if (Platform.isAndroid) ...[ + const SwitchModel( + title: '启用 HDR 视频', + subtitle: '在 HDR 视频中覆盖设置,启用平台视图渲染,调用合适的解码与输出参数', + leading: Icon(Icons.settings_brightness_outlined), + setKey: SettingBoxKey.enableHDR, + defaultVal: true, + ), + const SwitchModel( + title: '使用平台视图', + subtitle: '使用平台视图渲染播放器,支持 HDR 视频', + leading: Icon(Icons.draw_outlined), + setKey: SettingBoxKey.platformView, + defaultVal: false, + ), + const SwitchModel( + title: '平台视图使用 HCPP 渲染', + subtitle: '使用性能与效果更优的 HCPP 渲染平台视图,要求设备 Android 14 (SDK 34) 及以上且支持 Vulkan,如不匹配会导致崩溃', + leading: Icon(Icons.extension_outlined), + setKey: SettingBoxKey.platformViewHCPP, + defaultVal: true, + ), + ], ]; Future _showSubtitleDialog( diff --git a/lib/pages/setting/models/video_settings.dart b/lib/pages/setting/models/video_settings.dart index 138dadcd1e..8ea16b8d1e 100644 --- a/lib/pages/setting/models/video_settings.dart +++ b/lib/pages/setting/models/video_settings.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/pages/setting/widgets/ordered_multi_select_dialog.dart' import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart'; import 'package:PiliPlus/plugin/pl_player/models/audio_output_type.dart'; import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart'; +import 'package:PiliPlus/plugin/pl_player/models/video_output.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -169,6 +170,12 @@ List get videoSettings => [ getSubtitle: () => '当前:${Pref.hardwareDecoding}(此项即mpv的--hwdec)', onTap: _showHwDecDialog, ), + NormalModel( + title: '视频输出', + leading: const Icon(Icons.video_settings_outlined), + getSubtitle: () => '当前:${Pref.videoOutput}(此项即mpv的--vo)', + onTap: _showVideoOutputDialog, + ), ]; Future _showCDNDialog(BuildContext context, VoidCallback setState) async { @@ -455,6 +462,31 @@ Future _showHwDecDialog( } } +Future _showVideoOutputDialog( + BuildContext context, + VoidCallback setState, + ) async { + final result = await showDialog>( + context: context, + builder: (context) { + return OrderedMultiSelectDialog( + title: '视频输出', + initValues: Pref.videoOutput.split(','), + values: { + for (var e in VoType.values) e.vo: '${e.vo}\n${e.desc}', + }, + ); + }, + ); + if (result != null && result.isNotEmpty) { + await GStorage.setting.put( + SettingBoxKey.videoOutput, + result.join(','), + ); + setState(); + } +} + void _showAutoSyncDialog(BuildContext context, VoidCallback setState) { String autosync = Pref.autosync.toString(); showDialog( diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index d9809f3f56..7576d32a7b 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -110,6 +110,7 @@ class VideoDetailController extends GetxController /// 播放器配置 画质 音质 解码格式 final Rxn currentVideoQa = Rxn(); + VideoQuality? curHighestVideoQa; AudioQuality? currentAudioQa; late VideoDecodeFormatType currentDecodeFormats; @@ -723,6 +724,7 @@ class VideoDetailController extends GetxController dirPath: isFileSource ? args['dirPath'] : null, typeTag: isFileSource ? entry.typeTag : null, mediaType: isFileSource ? entry.mediaType : null, + canHDR: currentVideoQa.value?.isHDR, ); if (isClosed) return; @@ -857,11 +859,11 @@ class VideoDetailController extends GetxController final List videoList = data.dash!.video!; // if (kDebugMode) debugPrint("allVideosList:${allVideosList}"); // 当前可播放的最高质量视频 - final curHighestVideoQa = videoList.first.quality.code; + curHighestVideoQa = videoList.first.quality; // 预设的画质为null,则当前可用的最高质量 - int targetVideoQa = curHighestVideoQa; + int targetVideoQa = curHighestVideoQa!.code; if (data.acceptQuality?.isNotEmpty == true && - plPlayerController.cacheVideoQa! <= curHighestVideoQa) { + plPlayerController.cacheVideoQa! <= curHighestVideoQa!.code) { // 如果预设的画质低于当前最高 targetVideoQa = data.acceptQuality!.findClosestTarget( (e) => e <= plPlayerController.cacheVideoQa!, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 800f390c19..25337af4ac 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -392,7 +392,15 @@ class PlPlayerController with BlockConfigMixin { bool enableHeart = true; late final bool enableHA = Pref.enableHA; - late final String hwdec = Pref.hardwareDecoding; + late final bool enableHDR = Platform.isAndroid && Pref.enableHDR; + + bool? _canHDR; + String get hwdec => + enableHDR && _canHDR == true ? 'mediacodec,auto' : Pref.hardwareDecoding; + String get vo => + enableHDR && _canHDR == true ? 'mediacodec_embed,gpu' : Pref.videoOutput; + bool get platformView => Pref.platformView || (enableHDR && _canHDR == true); + late final bool platformViewHCPP = Pref.platformViewHCPP; late final progressType = Pref.btmProgressBehavior; late final enableQuickDouble = Pref.enableQuickDouble; @@ -600,6 +608,7 @@ class PlPlayerController with BlockConfigMixin { String? dirPath, String? typeTag, int? mediaType, + bool? canHDR, }) async { try { this.dirPath = dirPath; @@ -626,6 +635,7 @@ class PlPlayerController with BlockConfigMixin { _epid = epid; _seasonId = seasonId; _pgcType = pgcType; + _canHDR = canHDR; if (showSeekPreview) { _clearPreview(); @@ -830,7 +840,10 @@ class PlPlayerController with BlockConfigMixin { configuration: VideoControllerConfiguration( enableHardwareAcceleration: enableHA, androidAttachSurfaceAfterVideoParameters: false, + vo: vo.isEmpty ? null : vo, hwdec: enableHA ? hwdec : null, + usePlatformView: platformView, + useHCPP: platformViewHCPP, ), ); diff --git a/lib/plugin/pl_player/models/video_output.dart b/lib/plugin/pl_player/models/video_output.dart new file mode 100644 index 0000000000..da228b620e --- /dev/null +++ b/lib/plugin/pl_player/models/video_output.dart @@ -0,0 +1,20 @@ +// mpv --vo=help +enum VoType { + gpu('gpu', 'GPU 视频输出'), + gpuNext('gpu-next', 'GPU 视频输出 (实验性)'), + xv('xv', 'XVideo (X11) (过时)'), + x11('x11', 'X11 共享内存 (X11) (仅回退)'), + vdpau('vdpau', 'VDPAU (X11)'), + direct3d('direct3d', 'Direct3D (Windows)'), + sdl('sdl', 'SDL 2.0+ (兼容性)'), + dmabufWayland('dmabuf-wayland', 'Wayland 输出 (实验性)'), + vaapi('vaapi', 'VAAPI (Linux)'), + drm('drm', 'DRM (Linux)'), + mediacodecEmbed('mediacodec_embed', 'MediaCodec 嵌入 (Android)'), + wlshm('wlshm', 'Wayland 共享内存 (Wayland)') + ; + + final String vo; + final String desc; + const VoType(this.vo, this.desc); +} diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 57ccfb6b5c..7b016b41d9 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -18,6 +18,7 @@ abstract final class SettingBoxKey { hardwareDecoding = 'hardwareDecoding', videoSync = 'videoSync', autosync = 'autosync', + videoOutput = 'videoOutput', p1080 = 'p1080', enableAutoEnter = 'enableAutoEnter', enableAutoExit = 'enableAutoExit', @@ -243,6 +244,9 @@ abstract final class SettingBoxKey { msgUnReadTypeV2 = 'msgUnReadTypeV2', navBarSort = 'navBarSort', tempPlayerConf = 'tempPlayerConf', + enableHDR = 'enableHDR', + platformView = 'platformView', + platformViewHCPP = 'platformViewHCPP', reduceLuxColor = 'reduceLuxColor', liveCdnUrl = 'liveCdnUrl'; } diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 8d06272199..1d42e2f648 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -29,6 +29,7 @@ import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart'; import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart'; import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart'; +import 'package:PiliPlus/plugin/pl_player/models/video_output.dart'; import 'package:PiliPlus/utils/extension/context_ext.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/global_data.dart'; @@ -264,6 +265,11 @@ abstract final class Pref { defaultValue: Platform.isAndroid ? '30' : '0', ); + static String get videoOutput => _setting.get( + SettingBoxKey.videoOutput, + defaultValue: VoType.gpu.vo, + ); + static CDNService get defaultCDNService { if (_setting.get(SettingBoxKey.CDNService) case final String cdnName) { return CDNService.values.byName(cdnName); @@ -893,6 +899,15 @@ abstract final class Pref { static bool get tempPlayerConf => _setting.get(SettingBoxKey.tempPlayerConf, defaultValue: false); + static bool get enableHDR => + _setting.get(SettingBoxKey.enableHDR, defaultValue: true); + + static bool get platformView => + _setting.get(SettingBoxKey.platformView, defaultValue: false); + + static bool get platformViewHCPP => + _setting.get(SettingBoxKey.platformViewHCPP, defaultValue: true); + static Color? get reduceLuxColor { final int? color = _setting.get(SettingBoxKey.reduceLuxColor); if (color != null && color != 0xFFFFFFFF) { diff --git a/pubspec.lock b/pubspec.lock index 34ee107ebe..b3023d22fc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1130,18 +1130,18 @@ packages: dependency: "direct main" description: path: media_kit - ref: "version_1.2.5" - resolved-ref: ac35bc96c5560a7c9a55bc421bd4115d1e47bc70 - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + ref: "PiliPlus-1.2.5" + resolved-ref: e126e9b0ec6687830c058e1b6b00663c36dc5fbd + url: "https://github.com/chenx-dust/media-kit.git" source: git version: "1.1.11" media_kit_libs_android_video: dependency: "direct overridden" description: path: "libs/android/media_kit_libs_android_video" - ref: "version_1.2.5" - resolved-ref: ac35bc96c5560a7c9a55bc421bd4115d1e47bc70 - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + ref: "PiliPlus-1.2.5" + resolved-ref: e126e9b0ec6687830c058e1b6b00663c36dc5fbd + url: "https://github.com/chenx-dust/media-kit.git" source: git version: "1.3.7" media_kit_libs_ios_video: @@ -1172,36 +1172,36 @@ packages: dependency: "direct main" description: path: "libs/universal/media_kit_libs_video" - ref: "version_1.2.5" - resolved-ref: ac35bc96c5560a7c9a55bc421bd4115d1e47bc70 - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + ref: "PiliPlus-1.2.5" + resolved-ref: e126e9b0ec6687830c058e1b6b00663c36dc5fbd + url: "https://github.com/chenx-dust/media-kit.git" source: git version: "1.0.5" media_kit_libs_windows_video: dependency: "direct overridden" description: path: "libs/windows/media_kit_libs_windows_video" - ref: "version_1.2.5" - resolved-ref: ac35bc96c5560a7c9a55bc421bd4115d1e47bc70 - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + ref: "PiliPlus-1.2.5" + resolved-ref: e126e9b0ec6687830c058e1b6b00663c36dc5fbd + url: "https://github.com/chenx-dust/media-kit.git" source: git version: "1.0.10" media_kit_native_event_loop: dependency: "direct overridden" description: path: media_kit_native_event_loop - ref: "version_1.2.5" - resolved-ref: ac35bc96c5560a7c9a55bc421bd4115d1e47bc70 - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + ref: "PiliPlus-1.2.5" + resolved-ref: e126e9b0ec6687830c058e1b6b00663c36dc5fbd + url: "https://github.com/chenx-dust/media-kit.git" source: git version: "1.0.9" media_kit_video: dependency: "direct main" description: path: media_kit_video - ref: "version_1.2.5" - resolved-ref: ac35bc96c5560a7c9a55bc421bd4115d1e47bc70 - url: "https://github.com/bggRGjQaUbCoE/media-kit.git" + ref: "PiliPlus-1.2.5" + resolved-ref: e126e9b0ec6687830c058e1b6b00663c36dc5fbd + url: "https://github.com/chenx-dust/media-kit.git" source: git version: "1.2.5" menu_base: diff --git a/pubspec.yaml b/pubspec.yaml index aeb002b2e3..8623ea686c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -111,9 +111,9 @@ dependencies: # media_kit_video: ^1.2.5 # For video rendering. media_kit_video: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: media_kit_video - ref: version_1.2.5 + ref: PiliPlus-1.2.5 media_kit_libs_video: 1.0.5 # 媒体通知 @@ -250,34 +250,34 @@ dependency_overrides: rxdart: ^0.28.0 media_kit: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: media_kit - ref: version_1.2.5 + ref: PiliPlus-1.2.5 media_kit_video: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: media_kit_video - ref: version_1.2.5 + ref: PiliPlus-1.2.5 media_kit_libs_video: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: libs/universal/media_kit_libs_video - ref: version_1.2.5 + ref: PiliPlus-1.2.5 media_kit_native_event_loop: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: media_kit_native_event_loop - ref: version_1.2.5 + ref: PiliPlus-1.2.5 media_kit_libs_android_video: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: libs/android/media_kit_libs_android_video - ref: version_1.2.5 + ref: PiliPlus-1.2.5 media_kit_libs_windows_video: git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git + url: https://github.com/chenx-dust/media-kit.git path: libs/windows/media_kit_libs_windows_video - ref: version_1.2.5 + ref: PiliPlus-1.2.5 font_awesome_flutter: 10.9.0 dev_dependencies: