UI: Add Apple H.264 hardware encoder to simple mode

Adds the Apple Silicon hardware encoder as a simple mode option. For
recordings this only requires being on Apple Silicon (since we use the
Constant Quality setting), while for streaming it requires the user to
be on macOS 13 or newer (since we're using CBR).
master
gxalpha 2022-06-23 02:46:03 +02:00 committed by Sebastian Beckmann
parent 566ce79b0f
commit 29ae00e4af
6 changed files with 68 additions and 1 deletions

View File

@ -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"

View File

@ -1610,7 +1610,7 @@
<widget class="QComboBox" name="simpleOutStrEncoder"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_24">
<widget class="QLabel" name="simpleOutPresetLabel">
<property name="enabled">
<bool>true</bool>
</property>

View File

@ -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();
}

View File

@ -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;

View File

@ -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

View File

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