Added Video framerate limiter

Will fix cinematics and videos when readed over their framerate
This commit is contained in:
HolographicWings 2023-05-15 11:45:29 +02:00
parent e9069dfe76
commit acf0df69b8
7 changed files with 76 additions and 0 deletions

View file

@ -54,6 +54,7 @@ void LogSettings() {
log_setting("Renderer_AntiAliasing", values.anti_aliasing.GetValue());
log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue());
log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue());
log_setting("Renderer_VideoFramerate", values.video_framerate.GetValue());
log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue());
log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
log_setting("Renderer_UseAsynchronousGpuEmulation",
@ -218,6 +219,8 @@ void RestoreGlobalState(bool is_powered_on) {
values.max_anisotropy.SetGlobal(true);
values.use_speed_limit.SetGlobal(true);
values.speed_limit.SetGlobal(true);
values.use_video_framerate.SetGlobal(true);
values.video_framerate.SetGlobal(true);
values.use_disk_shader_cache.SetGlobal(true);
values.gpu_accuracy.SetGlobal(true);
values.use_asynchronous_gpu_emulation.SetGlobal(true);

View file

@ -456,6 +456,8 @@ struct Values {
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"};
SwitchableSetting<u16, true> video_framerate{30, 1, 240, "video_framerate"};
SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
GPUAccuracy::Extreme, "gpu_accuracy"};

View file

@ -278,14 +278,32 @@ void Codec::Decode() {
}
}
std::chrono::steady_clock::time_point last_frame_time = std::chrono::steady_clock::now();
std::chrono::microseconds min_call_interval = std::chrono::microseconds(1000/Settings::values.video_framerate.GetValue()*1000);
AVFramePtr Codec::GetCurrentFrame() {
// Sometimes VIC will request more frames than have been decoded.
// in this case, return a nullptr and don't overwrite previous frame data
if (av_frames.empty()) {
return AVFramePtr{nullptr, AVFrameDeleter};
}
AVFramePtr frame = std::move(av_frames.front());
av_frames.pop();
if (Settings::values.use_video_framerate.GetValue()) {
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
std::chrono::microseconds elapsed =
std::chrono::duration_cast<std::chrono::microseconds>(now - last_frame_time);
if (elapsed < min_call_interval) {
std::this_thread::sleep_for(min_call_interval - elapsed);
now = std::chrono::steady_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - last_frame_time);
}
last_frame_time = now;
}
return frame;
}

View file

@ -705,6 +705,8 @@ void Config::ReadRendererValues() {
ReadGlobalSetting(Settings::values.anti_aliasing);
ReadGlobalSetting(Settings::values.max_anisotropy);
ReadGlobalSetting(Settings::values.speed_limit);
ReadGlobalSetting(Settings::values.use_video_framerate);
ReadGlobalSetting(Settings::values.video_framerate);
ReadGlobalSetting(Settings::values.use_disk_shader_cache);
ReadGlobalSetting(Settings::values.gpu_accuracy);
ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
@ -1346,6 +1348,8 @@ void Config::SaveRendererValues() {
Settings::values.anti_aliasing.UsingGlobal());
WriteGlobalSetting(Settings::values.max_anisotropy);
WriteGlobalSetting(Settings::values.speed_limit);
WriteGlobalSetting(Settings::values.use_video_framerate);
WriteGlobalSetting(Settings::values.video_framerate);
WriteGlobalSetting(Settings::values.use_disk_shader_cache);
WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()),
static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)),

View file

@ -20,6 +20,9 @@ ConfigureGeneral::ConfigureGeneral(const Core::System& system_, QWidget* parent)
SetConfiguration();
if (Settings::IsConfiguringGlobal()) {
connect(ui->toggle_video_framerate, &QCheckBox::clicked, ui->video_framerate, [this]() {
ui->video_framerate->setEnabled(ui->toggle_video_framerate->isChecked());
});
connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit,
[this]() { ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked()); });
}
@ -41,14 +44,19 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue());
ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue());
ui->toggle_video_framerate->setChecked(Settings::values.use_video_framerate.GetValue());
ui->video_framerate->setValue(Settings::values.video_framerate.GetValue());
ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
ui->speed_limit->setValue(Settings::values.speed_limit.GetValue());
ui->button_reset_defaults->setEnabled(runtime_lock);
if (Settings::IsConfiguringGlobal()) {
ui->video_framerate->setEnabled(Settings::values.use_video_framerate.GetValue());
ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue());
} else {
ui->video_framerate->setEnabled(Settings::values.use_video_framerate.GetValue() && use_video_framerate != ConfigurationShared::CheckState::Global);
ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() &&
use_speed_limit != ConfigurationShared::CheckState::Global);
}
@ -83,6 +91,12 @@ void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
if (Settings::values.use_video_framerate.UsingGlobal()) {
Settings::values.use_video_framerate.SetValue(
ui->toggle_video_framerate->checkState() ==
Qt::Checked);
Settings::values.video_framerate.SetValue(ui->video_framerate->value());
}
// Guard if during game and set to game-specific value
if (Settings::values.use_speed_limit.UsingGlobal()) {
Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() ==
@ -118,6 +132,8 @@ void ConfigureGeneral::SetupPerGameUI() {
// Disables each setting if:
// - A game is running (thus settings in use), and
// - A non-global setting is applied.
ui->toggle_video_framerate->setEnabled(Settings::values.use_video_framerate.UsingGlobal());
ui->video_framerate->setEnabled(Settings::values.video_framerate.UsingGlobal());
ui->toggle_speed_limit->setEnabled(Settings::values.use_speed_limit.UsingGlobal());
ui->speed_limit->setEnabled(Settings::values.speed_limit.UsingGlobal());
@ -131,11 +147,16 @@ void ConfigureGeneral::SetupPerGameUI() {
ui->button_reset_defaults->setVisible(false);
ConfigurationShared::SetColoredTristate(ui->toggle_video_framerate, Settings::values.use_video_framerate, use_video_framerate);
ConfigurationShared::SetColoredTristate(ui->toggle_speed_limit,
Settings::values.use_speed_limit, use_speed_limit);
ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core,
use_multi_core);
connect(ui->toggle_video_framerate, &QCheckBox::clicked, ui->video_framerate, [this]() {
ui->video_framerate->setEnabled(ui->toggle_video_framerate->isChecked() &&
(use_video_framerate != ConfigurationShared::CheckState::Global));
});
connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() {
ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() &&
(use_speed_limit != ConfigurationShared::CheckState::Global));

View file

@ -46,6 +46,7 @@ private:
std::unique_ptr<Ui::ConfigureGeneral> ui;
ConfigurationShared::CheckState use_speed_limit;
ConfigurationShared::CheckState use_video_framerate;
ConfigurationShared::CheckState use_multi_core;
const Core::System& system;

View file

@ -89,6 +89,33 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="toggle_video_framerate">
<property name="text">
<string>Limit Videos Framerate</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="video_framerate">
<property name="suffix">
<string>fps</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>240</number>
</property>
<property name="value">
<number>30</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>