Skip to content

Commit

Permalink
Shaders support additional mpv settings
Browse files Browse the repository at this point in the history
eg: {
      "name": "fsrcnnx-high",
      "shaders": [
        "FSRCNNX_x2_16-0-4-1.glsl",
        "SSimDownscaler.glsl",
        "KrigBilateral.glsl"
      ],
      "settings": [
        ["scale", "ewa_lanczos"],
        ["dscale", "mitchell"],
        ["linear_downscaling", "no"],
        ["cscale", "mitchell"]
      ]
    },
  • Loading branch information
xfangfang committed Oct 13, 2024
1 parent eda1134 commit 83a8347
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 60 deletions.
3 changes: 3 additions & 0 deletions wiliwili/include/activity/player_activity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ class BasePlayerActivity : public brls::Activity, public VideoDetail {
private:
bool activityShown = false;
std::chrono::system_clock::time_point videoDeadline{};

// 重新选择当前清晰度的播放链接播放
void updateVideoLink();
};

class PlayerActivity : public BasePlayerActivity {
Expand Down
31 changes: 31 additions & 0 deletions wiliwili/include/utils/event_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include <borealis/core/event.hpp>

typedef enum MpvEventEnum {
/**
* 视频播放的一系列状态
* 播放器组件会订阅这些事件处理不同的逻辑
*/
MPV_LOADED,
MPV_PAUSE,
MPV_RESUME,
Expand All @@ -20,12 +24,39 @@ typedef enum MpvEventEnum {
UPDATE_PROGRESS,
START_FILE,
END_OF_FILE,

/**
* 视频缓存速度更新时触发此事件
* 播放器组件会订阅此事件,用于在网络加载卡顿时显示缓冲速度
*/
CACHE_SPEED_CHANGE,

/**
* 视频播放速度调整时触发此事件
* 弹幕组件和播放器组件的相关功能会订阅此事件
*/
VIDEO_SPEED_CHANGE,

/**
* mpv内部音量调整时触发以下事件
* DLNA 播放页面会订阅相关事件,并将音量状态同步到手机投屏端
*/
VIDEO_VOLUME_CHANGE,
VIDEO_MUTE,
VIDEO_UNMUTE,

/**
* 每次播放视频前,触发此事件
* 重置视频进度、视频比例、视频时长等信息
* 弹幕组件、字幕组件和播放器组件的相关功能会订阅此事件
*/
RESET,

/**
* 需要重置到播放器初识参数时,触发此事件(比如清空着色器设置)
* 视频播放页会订阅此事件,用来在播放器重置后重新设置播放链接
*/
RESTART,
} MpvEventEnum;

typedef brls::Event<MpvEventEnum> MPVEvent;
Expand Down
33 changes: 30 additions & 3 deletions wiliwili/include/utils/shader_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@

#include <string>
#include <vector>
#include <pystring.h>
#include <nlohmann/json.hpp>
#include <borealis/core/singleton.hpp>

class ShaderProfile {
public:
std::string name;
std::vector<std::string> shaders;
std::vector<std::vector<std::string>> settings;

std::string getShaderString();
};

inline void to_json(nlohmann::json& nlohmann_json_j, const ShaderProfile& nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, name, shaders));
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, name, shaders, settings));
}

inline void from_json(const nlohmann::json& nlohmann_json_j, ShaderProfile& nlohmann_json_t) {
Expand All @@ -30,6 +32,24 @@ inline void from_json(const nlohmann::json& nlohmann_json_j, ShaderProfile& nloh
auto& shaders = nlohmann_json_j.at("shaders");
if (shaders.is_array()) shaders.get_to(nlohmann_json_t.shaders);
}
if (nlohmann_json_j.contains("settings")) {
auto& settings = nlohmann_json_j.at("settings");
if (settings.is_array()) settings.get_to(nlohmann_json_t.settings);
for (auto& setting : nlohmann_json_t.settings) {
if (setting.empty()) continue;
// 检查是否包含操作指令
const std::vector<std::string> mainOptions = {"set", "run", "change-list"};
bool hasMainOption = false;
for (auto& option : mainOptions) {
if (pystring::endswith(setting[0], option)) {
hasMainOption = true;
break;
}
}
// 如果没有指明操作方式,则默认为 set
if (!hasMainOption) setting.insert(setting.begin(), "set");
}
}
}

typedef std::vector<ShaderProfile> ShaderProfileList;
Expand Down Expand Up @@ -133,11 +153,18 @@ class ShaderHelper : public brls::Singleton<ShaderHelper> {
std::string getProfileNameByIndex(size_t index);

/**
* 通过配置索引获取 profile 字符串
* 通过配置索引获取 profile shader
* @param index
* @return
*/
std::string getProfileShaderByIndex(size_t index);

/**
* 通过配置索引获取 profile settings
* @param index
* @return
*/
std::string getProfileByIndex(size_t index);
std::vector<std::vector<std::string>> getByProfileSettingByIndex(size_t index);

/**
* 通过剧集 id 获取配置索引
Expand Down
27 changes: 16 additions & 11 deletions wiliwili/include/view/mpv_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ class MPVCore : public brls::Singleton<MPVCore> {
*/
void setAspect(const std::string &value);

void setMirror(bool value);

/**
* 设置视频亮度
* @param value [-100, 100]
Expand Down Expand Up @@ -288,7 +290,15 @@ class MPVCore : public brls::Singleton<MPVCore> {

void reset();

void setShader(const std::string &profile, const std::string &shaders, bool showHint = true);
/**
* 设置着色器配置
* @param profile 配置名
* @param shaders 着色器文件
* @param settings mpv 配置
* @param reset 在设置前是否需要重置
*/
void setShader(const std::string &profile, const std::string &shaders,
const std::vector<std::vector<std::string>> &settings, bool reset = true);

void clearShader(bool showHint = true);

Expand All @@ -300,17 +310,11 @@ class MPVCore : public brls::Singleton<MPVCore> {
return;
}
std::vector<std::string> commands = {fmt::format("{}", std::forward<Args>(args))...};

std::vector<const char *> res;
res.reserve(commands.size() + 1);
for (auto &i : commands) {
res.emplace_back(i.c_str());
}
res.emplace_back(nullptr);

mpvCommandAsync(mpv, 0, res.data());
_command_async(commands);
}

void _command_async(const std::vector<std::string>& commands);

// core states
int64_t duration = 0; // second
int64_t cache_speed = 0; // Bps
Expand All @@ -330,6 +334,7 @@ class MPVCore : public brls::Singleton<MPVCore> {
std::string filepath;
std::string currentShaderProfile; // 当前着色器脚本名
std::string currentShader; // 当前着色器脚本
std::vector<std::vector<std::string>> currentSetting; // 当前着色器脚本附加的mpv配置

double video_brightness = 0;
double video_contrast = 0;
Expand All @@ -347,7 +352,7 @@ class MPVCore : public brls::Singleton<MPVCore> {
inline static bool TERMINAL = false;

// 硬件解码
inline static bool HARDWARE_DEC = false;
inline static bool HARDWARE_DEC = false;

// 硬解方式
#ifdef __SWITCH__
Expand Down
53 changes: 31 additions & 22 deletions wiliwili/source/activity/player_base_activity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,13 @@ void BasePlayerActivity::setCommonData() {
});

// 暂停
this->registerAction("toggle", brls::ControllerButton::BUTTON_SPACE, [this](...) -> bool {
this->video->togglePlay();
return true;
}, true);
this->registerAction(
"toggle", brls::ControllerButton::BUTTON_SPACE,
[this](...) -> bool {
this->video->togglePlay();
return true;
},
true);

this->btnQR->getParent()->addGestureRecognizer(new brls::TapGestureRecognizer(this->btnQR->getParent()));

Expand Down Expand Up @@ -345,6 +348,9 @@ void BasePlayerActivity::setCommonData() {
}
}
break;
case MpvEventEnum::RESTART:
this->updateVideoLink();
break;
default:
break;
}
Expand Down Expand Up @@ -405,6 +411,26 @@ void BasePlayerActivity::showCoinDialog(uint64_t aid) {
dialog->open();
}

void BasePlayerActivity::updateVideoLink() {
// 设置视频加载后跳转的时间
setProgress(MPVCore::instance().video_progress);

// dash
if (!this->videoUrlResult.dash.video.empty()) {
// dash格式的视频无需重复请求视频链接,这里简单的设置清晰度即可
videoUrlResult.quality = BasePlayerActivity::defaultQuality;
this->onVideoPlayUrl(videoUrlResult);
return;
}

// flv
if (dynamic_cast<PlayerSeasonActivity*>(this)) {
this->requestSeasonVideoUrl(episodeResult.bvid, episodeResult.cid);
} else {
this->requestVideoUrl(videoDetailResult.bvid, videoDetailPage.cid);
}
}

void BasePlayerActivity::setVideoQuality() {
if (this->videoUrlResult.accept_description.empty()) return;

Expand All @@ -421,24 +447,7 @@ void BasePlayerActivity::setVideoQuality() {
return;
}

// 设置视频加载后跳转的时间
setProgress(MPVCore::instance().video_progress);

// dash
if (!this->videoUrlResult.dash.video.empty()) {
// dash格式的视频无需重复请求视频链接,这里简单的设置清晰度即可
videoUrlResult.quality = BasePlayerActivity::defaultQuality;
this->onVideoPlayUrl(videoUrlResult);
return;
}

// flv
auto self = dynamic_cast<PlayerSeasonActivity*>(this);
if (self) {
this->requestSeasonVideoUrl(episodeResult.bvid, episodeResult.cid);
} else {
this->requestVideoUrl(videoDetailResult.bvid, videoDetailPage.cid);
}
this->updateVideoLink();
},
getQualityIndex());
auto* recycler = dropdown->getRecyclingList();
Expand Down
3 changes: 1 addition & 2 deletions wiliwili/source/fragment/player_setting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,7 @@ void PlayerSetting::setupCommonSetting() {

/// Player mirror
btnMirror->init("wiliwili/player/setting/common/mirror"_i18n, MPVCore::VIDEO_MIRROR, [](bool value) {
MPVCore::VIDEO_MIRROR = !MPVCore::VIDEO_MIRROR;
MPVCore::instance().command_async("set", "vf", MPVCore::VIDEO_MIRROR ? "hflip" : "");
MPVCore::instance().setMirror(!MPVCore::VIDEO_MIRROR);
GA("player_setting", {{"mirror", value ? "true" : "false"}});

// 如果正在使用硬解,那么将硬解更新为 auto-copy,避免直接硬解因为不经过 cpu 处理导致镜像翻转无效
Expand Down
20 changes: 15 additions & 5 deletions wiliwili/source/utils/shader_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <unistd.h>
#include <nlohmann/json.hpp>
#include <borealis/core/singleton.hpp>
#include <borealis/core/application.hpp>
#include <borealis/core/util.hpp>
#include <utility>
#include <pystring.h>
Expand All @@ -20,6 +21,7 @@ std::string ShaderProfile::getShaderString() {
std::string separator = ":";
#endif
std::vector<std::string> res;
res.reserve(shaders.size());
for (auto& s : shaders) {
res.emplace_back("~~/shaders/" + s);
}
Expand All @@ -33,14 +35,15 @@ void ShaderHelper::setShaderPack(const ShaderPack& data) { this->pack = data; }
ShaderPack ShaderHelper::getShaderPack() { return this->pack; }

void ShaderHelper::setShader(size_t index, bool showHint) {
MPVCore::instance().setShader(getProfileNameByIndex(index), getProfileByIndex(index), showHint);
MPVCore::instance().setShader(getProfileNameByIndex(index), getProfileShaderByIndex(index),
getByProfileSettingByIndex(index), showHint);
}

void ShaderHelper::clearShader(bool showHint) { MPVCore::instance().clearShader(showHint); }

void ShaderHelper::setProfile(size_t sid, size_t profileIndex) {
if (!isAvailable()) return;
if (profileIndex < 0 || profileIndex >= pack.profiles.size()) return;
if (profileIndex >= pack.profiles.size()) return;
for (auto& anime : pack.animeList) {
if (anime.anime == sid) {
// 修改已有配置
Expand Down Expand Up @@ -92,16 +95,22 @@ std::string ShaderHelper::getProfileByName(const std::string& name) {

std::string ShaderHelper::getProfileNameByIndex(size_t index) {
if (!isAvailable()) return "";
if (index < 0 || index >= pack.profiles.size()) return "";
if (index >= pack.profiles.size()) return "";
return pack.profiles[index].name;
}

std::string ShaderHelper::getProfileByIndex(size_t index) {
std::string ShaderHelper::getProfileShaderByIndex(size_t index) {
if (!isAvailable()) return "";
if (index < 0 || index >= pack.profiles.size()) return "";
if (index >= pack.profiles.size()) return "";
return pack.profiles[index].getShaderString();
}

std::vector<std::vector<std::string>> ShaderHelper::getByProfileSettingByIndex(size_t index) {
if (!isAvailable()) return {};
if (index >= pack.profiles.size()) return {};
return pack.profiles[index].settings;
}

size_t ShaderHelper::getProfileIndexBySeason(size_t sid) {
if (!isAvailable()) return -1;
for (auto& anime : pack.animeList) {
Expand Down Expand Up @@ -146,6 +155,7 @@ void ShaderHelper::load() {
this->setShaderPack(content.get<ShaderPack>());
} catch (const std::exception& e) {
brls::Logger::error("ShaderHelper::load: {}", e.what());
brls::Application::notify("Load custom shader pack failed\n" + std::string(e.what()));
}
brls::Logger::info("Load custom shader pack from: {}", path);
} else {
Expand Down
Loading

0 comments on commit 83a8347

Please sign in to comment.