diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 8109863cc..0296cbc4c 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -897,6 +897,7 @@ Basic.Settings.Output.Simple.Encoder.Hardware.QSV.H264="Hardware (QSV, H.264)" Basic.Settings.Output.Simple.Encoder.Hardware.AMD.H264="Hardware (AMD, H.264)" Basic.Settings.Output.Simple.Encoder.Hardware.NVENC.H264="Hardware (NVENC, H.264)" Basic.Settings.Output.Simple.Encoder.Hardware.NVENC.HEVC="Hardware (NVENC, HEVC)" +Basic.Settings.Output.Simple.Encoder.Hardware.Apple.H264="Hardware (Apple, H.264)" Basic.Settings.Output.Simple.Encoder.SoftwareLowCPU="Software (x264 low CPU usage preset, increases file size)" Basic.Settings.Output.Simple.TwitchVodTrack="Twitch VOD Track (Uses Track 2)" Basic.Settings.Output.Warn.EnforceResolutionFPS.Title="Incompatible Resolution/Framerate" diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui index d4b516bc3..5f17c0af6 100644 --- a/UI/forms/OBSBasicSettings.ui +++ b/UI/forms/OBSBasicSettings.ui @@ -1610,7 +1610,7 @@ - + true diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 0035e7ca9..82ad80c20 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -289,6 +289,7 @@ struct SimpleOutput : BasicOutputHandler { void UpdateRecordingSettings_nvenc_hevc(int cqp); #endif void UpdateRecordingSettings_amd_cqp(int cqp); + void UpdateRecordingSettings_apple(int quality); void UpdateRecordingSettings(); void UpdateRecordingAudioSettings(); virtual void Update() override; @@ -402,6 +403,9 @@ void SimpleOutput::LoadRecordingPreset() : "ffmpeg_hevc_nvenc"; LoadRecordingPreset_Lossy(id); #endif + } else if (strcmp(encoder, SIMPLE_ENCODER_APPLE_H264) == 0) { + LoadRecordingPreset_Lossy( + "com.apple.videotoolbox.videoencoder.ave.avc"); } usingRecordingPreset = true; @@ -438,6 +442,10 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_) LoadStreamingPreset_Lossy(id); #endif + } else if (strcmp(encoder, SIMPLE_ENCODER_APPLE_H264) == 0) { + LoadStreamingPreset_Lossy( + "com.apple.videotoolbox.videoencoder.ave.avc"); + } else { LoadStreamingPreset_Lossy("obs_x264"); } @@ -690,6 +698,16 @@ void SimpleOutput::UpdateRecordingSettings_nvenc_hevc(int cqp) } #endif +void SimpleOutput::UpdateRecordingSettings_apple(int quality) +{ + OBSDataAutoRelease settings = obs_data_create(); + obs_data_set_string(settings, "rate_control", "CRF"); + obs_data_set_string(settings, "profile", "high"); + obs_data_set_int(settings, "quality", quality); + + obs_encoder_update(videoRecording, settings); +} + void SimpleOutput::UpdateStreamingSettings_amd(obs_data_t *settings, int bitrate) { @@ -754,6 +772,9 @@ void SimpleOutput::UpdateRecordingSettings() } else if (videoEncoder == SIMPLE_ENCODER_NVENC_HEVC) { UpdateRecordingSettings_nvenc_hevc(crf); #endif + } else if (videoEncoder == SIMPLE_ENCODER_APPLE_H264) { + /* These are magic numbers. 0 - 100, more is better. */ + UpdateRecordingSettings_apple(ultra_hq ? 70 : 50); } UpdateRecordingAudioSettings(); } diff --git a/UI/window-basic-main-profiles.cpp b/UI/window-basic-main-profiles.cpp index 04780a142..5c6ed768a 100644 --- a/UI/window-basic-main-profiles.cpp +++ b/UI/window-basic-main-profiles.cpp @@ -821,6 +821,7 @@ void OBSBasic::CheckForSimpleModeX264Fallback() #ifdef ENABLE_HEVC bool nve_hevc_supported = false; #endif + bool apple_supported = false; bool changed = false; size_t idx = 0; const char *id; @@ -836,6 +837,10 @@ void OBSBasic::CheckForSimpleModeX264Fallback() else if (strcmp(id, "ffmpeg_hevc_nvenc") == 0) nve_hevc_supported = true; #endif + else if (strcmp(id, + "com.apple.videotoolbox.videoencoder.ave.avc") == + 0) + apple_supported = true; } auto CheckEncoder = [&](const char *&name) { @@ -865,6 +870,12 @@ void OBSBasic::CheckForSimpleModeX264Fallback() name = SIMPLE_ENCODER_X264; return false; } + } else if (strcmp(name, SIMPLE_ENCODER_APPLE_H264) == 0) { + if (!apple_supported) { + changed = true; + name = SIMPLE_ENCODER_X264; + return false; + } } return true; diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 4ab99049f..4a91ceb31 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -70,6 +70,7 @@ class OBSBasicStats; #define SIMPLE_ENCODER_NVENC_HEVC "nvenc_hevc" #endif #define SIMPLE_ENCODER_AMD "amd" +#define SIMPLE_ENCODER_APPLE_H264 "apple_h264" #define PREVIEW_EDGE_SIZE 10 diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index e99707fca..3853cf116 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -3542,6 +3542,11 @@ void OBSBasicSettings::SaveOutputSettings() #endif else if (encoder == SIMPLE_ENCODER_AMD) presetType = "AMDPreset"; + else if (encoder == SIMPLE_ENCODER_APPLE_H264) + /* The Apple encoders don't have presets like the other encoders + do. This only exists to make sure that the x264 preset doesn't + get overwritten with empty data. */ + presetType = "ApplePreset"; else presetType = "Preset"; @@ -4768,6 +4773,14 @@ void OBSBasicSettings::FillSimpleRecordingValues() ui->simpleOutRecEncoder->addItem( ENCODER_STR("Hardware.AMD.H264"), QString(SIMPLE_ENCODER_AMD)); + if (EncoderAvailable("com.apple.videotoolbox.videoencoder.ave.avc") +#ifndef __aarch64__ + && os_get_emulation_status() == true +#endif + ) + ui->simpleOutRecEncoder->addItem( + ENCODER_STR("Hardware.Apple.H264"), + QString(SIMPLE_ENCODER_APPLE_H264)); #undef ADD_QUALITY } @@ -4793,6 +4806,18 @@ void OBSBasicSettings::FillSimpleStreamingValues() ui->simpleOutStrEncoder->addItem( ENCODER_STR("Hardware.AMD.H264"), QString(SIMPLE_ENCODER_AMD)); +/* Preprocessor guard required for the macOS version check */ +#ifdef __APPLE__ + if (EncoderAvailable("com.apple.videotoolbox.videoencoder.ave.avc") +#ifndef __aarch64__ + && os_get_emulation_status() == true +#endif + ) + if (__builtin_available(macOS 13.0, *)) + ui->simpleOutStrEncoder->addItem( + ENCODER_STR("Hardware.Apple.H264"), + QString(SIMPLE_ENCODER_APPLE_H264)); +#endif #undef ENCODER_STR } @@ -4835,6 +4860,9 @@ void OBSBasicSettings::SimpleStreamingEncoderChanged() QString preset; const char *defaultPreset = nullptr; + ui->simpleOutAdvanced->setVisible(true); + ui->simpleOutPresetLabel->setVisible(true); + ui->simpleOutPreset->setVisible(true); ui->simpleOutPreset->clear(); if (encoder == SIMPLE_ENCODER_QSV) { @@ -4906,6 +4934,11 @@ void OBSBasicSettings::SimpleStreamingEncoderChanged() defaultPreset = "balanced"; preset = curAMDPreset; + } else if (encoder == SIMPLE_ENCODER_APPLE_H264) { + ui->simpleOutAdvanced->setChecked(false); + ui->simpleOutAdvanced->setVisible(false); + ui->simpleOutPreset->setVisible(false); + ui->simpleOutPresetLabel->setVisible(false); } else { #define PRESET_STR(val) \