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: