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) \