UI: Add audio codec selections

This commit is contained in:
tytan652
2022-12-17 18:26:59 +01:00
parent b15684aa17
commit 5fe417bce1
7 changed files with 633 additions and 225 deletions

View File

@@ -1267,7 +1267,7 @@ static bool return_first_id(void *data, const char *id)
return false;
}
bool OBSBasicSettings::ServiceAndCodecCompatible()
bool OBSBasicSettings::ServiceAndVCodecCompatible()
{
bool simple = (ui->outputMode->currentIndex() == 0);
bool ret;
@@ -1309,6 +1309,44 @@ bool OBSBasicSettings::ServiceAndCodecCompatible()
return ret;
}
bool OBSBasicSettings::ServiceAndACodecCompatible()
{
bool simple = (ui->outputMode->currentIndex() == 0);
bool ret;
QString codec;
if (simple) {
codec = ui->simpleOutStrAEncoder->currentData().toString();
} else {
QString encoder = ui->advOutAEncoder->currentData().toString();
codec = obs_get_encoder_codec(QT_TO_UTF8(encoder));
}
OBSService service = SpawnTempService();
const char **codecs = obs_service_get_supported_audio_codecs(service);
if (!codecs || IsCustomService()) {
const char *output;
char **output_codecs;
obs_enum_output_types_with_protocol(QT_TO_UTF8(protocol),
&output, return_first_id);
output_codecs = strlist_split(
obs_get_output_supported_audio_codecs(output), ';',
false);
ret = service_supports_codec((const char **)output_codecs,
QT_TO_UTF8(codec));
strlist_free(output_codecs);
} else {
ret = service_supports_codec(codecs, QT_TO_UTF8(codec));
}
return ret;
}
/* we really need a way to find fallbacks in a less hardcoded way. maybe. */
static QString get_adv_fallback(const QString &enc)
{
@@ -1321,6 +1359,22 @@ static QString get_adv_fallback(const QString &enc)
return "obs_x264";
}
static QString get_adv_audio_fallback(const QString &enc)
{
const char *codec = obs_get_encoder_codec(QT_TO_UTF8(enc));
if (strcmp(codec, "aac") == 0)
return "ffmpeg_opus";
QString aac_default = "ffmpeg_aac";
if (EncoderAvailable("CoreAudio_AAC"))
aac_default = "CoreAudio_AAC";
else if (EncoderAvailable("libfdk_aac"))
aac_default = "libfdk_aac";
return aac_default;
}
static QString get_simple_fallback(const QString &enc)
{
if (enc == SIMPLE_ENCODER_NVENC_HEVC)
@@ -1339,7 +1393,10 @@ bool OBSBasicSettings::ServiceSupportsCodecCheck()
if (loading)
return false;
if (ServiceAndCodecCompatible()) {
bool vcodec_compat = ServiceAndVCodecCompatible();
bool acodec_compat = ServiceAndACodecCompatible();
if (vcodec_compat && acodec_compat) {
if (lastServiceIdx != ui->service->currentIndex() ||
IsCustomService())
ResetEncoders(true);
@@ -1347,8 +1404,10 @@ bool OBSBasicSettings::ServiceSupportsCodecCheck()
}
QString service = ui->service->currentText();
QString cur_name;
QString fb_name;
QString cur_video_name;
QString fb_video_name;
QString cur_audio_name;
QString fb_audio_name;
bool simple = (ui->outputMode->currentIndex() == 0);
/* ------------------------------------------------- */
@@ -1362,20 +1421,45 @@ bool OBSBasicSettings::ServiceSupportsCodecCheck()
int cur_idx = ui->simpleOutStrEncoder->findData(cur_enc);
int fb_idx = ui->simpleOutStrEncoder->findData(fb_enc);
cur_name = ui->simpleOutStrEncoder->itemText(cur_idx);
fb_name = ui->simpleOutStrEncoder->itemText(fb_idx);
cur_video_name = ui->simpleOutStrEncoder->itemText(cur_idx);
fb_video_name = ui->simpleOutStrEncoder->itemText(fb_idx);
cur_enc = ui->simpleOutStrAEncoder->currentData().toString();
fb_enc = (cur_enc == "opus") ? "aac" : "opus";
cur_audio_name = ui->simpleOutStrAEncoder->itemText(
ui->simpleOutStrAEncoder->findData(cur_enc));
fb_audio_name = ui->simpleOutStrAEncoder->itemText(
ui->simpleOutStrAEncoder->findData(fb_enc));
} else {
QString cur_enc = ui->advOutEncoder->currentData().toString();
QString fb_enc = get_adv_fallback(cur_enc);
cur_name = obs_encoder_get_display_name(QT_TO_UTF8(cur_enc));
fb_name = obs_encoder_get_display_name(QT_TO_UTF8(fb_enc));
cur_video_name =
obs_encoder_get_display_name(QT_TO_UTF8(cur_enc));
fb_video_name =
obs_encoder_get_display_name(QT_TO_UTF8(fb_enc));
cur_enc = ui->advOutAEncoder->currentData().toString();
fb_enc = get_adv_audio_fallback(cur_enc);
cur_audio_name =
obs_encoder_get_display_name(QT_TO_UTF8(cur_enc));
fb_audio_name =
obs_encoder_get_display_name(QT_TO_UTF8(fb_enc));
}
#define WARNING_VAL(x) \
QTStr("Basic.Settings.Output.Warn.ServiceCodecCompatibility." x)
QString msg = WARNING_VAL("Msg").arg(service, cur_name, fb_name);
QString msg = WARNING_VAL("Msg").arg(
service, vcodec_compat ? cur_audio_name : cur_video_name,
vcodec_compat ? fb_audio_name : fb_video_name);
if (!vcodec_compat && !acodec_compat)
msg = WARNING_VAL("Msg2").arg(service, cur_video_name,
cur_audio_name, fb_video_name,
fb_audio_name);
auto button = OBSMessageBox::question(this, WARNING_VAL("Title"), msg);
#undef WARNING_VAL
@@ -1403,37 +1487,60 @@ bool OBSBasicSettings::ServiceSupportsCodecCheck()
void OBSBasicSettings::ResetEncoders(bool streamOnly)
{
QString lastAdvEnc = ui->advOutEncoder->currentData().toString();
QString lastEnc = ui->simpleOutStrEncoder->currentData().toString();
QString lastAdvVideoEnc = ui->advOutEncoder->currentData().toString();
QString lastVideoEnc =
ui->simpleOutStrEncoder->currentData().toString();
QString lastAdvAudioEnc = ui->advOutAEncoder->currentData().toString();
QString lastAudioEnc =
ui->simpleOutStrAEncoder->currentData().toString();
OBSService service = SpawnTempService();
const char **codecs = obs_service_get_supported_video_codecs(service);
const char **vcodecs = obs_service_get_supported_video_codecs(service);
const char **acodecs = obs_service_get_supported_audio_codecs(service);
const char *type;
BPtr<char *> output_codecs;
BPtr<char *> output_vcodecs;
BPtr<char *> output_acodecs;
size_t idx = 0;
if (!codecs || IsCustomService()) {
if (!vcodecs || IsCustomService()) {
const char *output;
obs_enum_output_types_with_protocol(QT_TO_UTF8(protocol),
&output, return_first_id);
output_codecs = strlist_split(
output_vcodecs = strlist_split(
obs_get_output_supported_video_codecs(output), ';',
false);
codecs = (const char **)output_codecs.Get();
vcodecs = (const char **)output_vcodecs.Get();
}
if (!acodecs || IsCustomService()) {
const char *output;
obs_enum_output_types_with_protocol(QT_TO_UTF8(protocol),
&output, return_first_id);
output_acodecs = strlist_split(
obs_get_output_supported_audio_codecs(output), ';',
false);
acodecs = (const char **)output_acodecs.Get();
}
QSignalBlocker s1(ui->simpleOutStrEncoder);
QSignalBlocker s2(ui->advOutEncoder);
QSignalBlocker s3(ui->simpleOutStrAEncoder);
QSignalBlocker s4(ui->advOutAEncoder);
/* ------------------------------------------------- */
/* clear encoder lists */
ui->simpleOutStrEncoder->clear();
ui->advOutEncoder->clear();
ui->simpleOutStrAEncoder->clear();
ui->advOutAEncoder->clear();
if (!streamOnly) {
ui->advOutRecEncoder->clear();
ui->advOutRecEncoder->addItem(TEXT_USE_STREAM_ENC, "none");
ui->advOutRecAEncoder->clear();
ui->advOutRecAEncoder->addItem(TEXT_USE_STREAM_ENC, "none");
}
/* ------------------------------------------------- */
@@ -1444,19 +1551,25 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
const char *codec = obs_get_encoder_codec(type);
uint32_t caps = obs_get_encoder_caps(type);
if (obs_get_encoder_type(type) != OBS_ENCODER_VIDEO)
continue;
if ((caps & ENCODER_HIDE_FLAGS) != 0)
continue;
QString qName = QT_UTF8(name);
QString qType = QT_UTF8(type);
if (service_supports_codec(codecs, codec))
ui->advOutEncoder->addItem(qName, qType);
if (!streamOnly)
ui->advOutRecEncoder->addItem(qName, qType);
if (obs_get_encoder_type(type) == OBS_ENCODER_VIDEO) {
if ((caps & ENCODER_HIDE_FLAGS) != 0)
continue;
if (service_supports_codec(vcodecs, codec))
ui->advOutEncoder->addItem(qName, qType);
if (!streamOnly)
ui->advOutRecEncoder->addItem(qName, qType);
}
if (obs_get_encoder_type(type) == OBS_ENCODER_AUDIO) {
if (service_supports_codec(acodecs, codec))
ui->advOutAEncoder->addItem(qName, qType);
if (!streamOnly)
ui->advOutRecAEncoder->addItem(qName, qType);
}
}
/* ------------------------------------------------- */
@@ -1466,40 +1579,40 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Software"),
QString(SIMPLE_ENCODER_X264));
if (service_supports_encoder(codecs, "obs_qsv11"))
if (service_supports_encoder(vcodecs, "obs_qsv11"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.QSV.H264"),
QString(SIMPLE_ENCODER_QSV));
if (service_supports_encoder(codecs, "obs_qsv11_av1"))
if (service_supports_encoder(vcodecs, "obs_qsv11_av1"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.QSV.AV1"),
QString(SIMPLE_ENCODER_QSV_AV1));
if (service_supports_encoder(codecs, "ffmpeg_nvenc"))
if (service_supports_encoder(vcodecs, "ffmpeg_nvenc"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.NVENC.H264"),
QString(SIMPLE_ENCODER_NVENC));
if (service_supports_encoder(codecs, "jim_av1_nvenc"))
if (service_supports_encoder(vcodecs, "jim_av1_nvenc"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.NVENC.AV1"),
QString(SIMPLE_ENCODER_NVENC_AV1));
#ifdef ENABLE_HEVC
if (service_supports_encoder(codecs, "h265_texture_amf"))
if (service_supports_encoder(vcodecs, "h265_texture_amf"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.AMD.HEVC"),
QString(SIMPLE_ENCODER_AMD_HEVC));
if (service_supports_encoder(codecs, "ffmpeg_hevc_nvenc"))
if (service_supports_encoder(vcodecs, "ffmpeg_hevc_nvenc"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.NVENC.HEVC"),
QString(SIMPLE_ENCODER_NVENC_HEVC));
#endif
if (service_supports_encoder(codecs, "h264_texture_amf"))
if (service_supports_encoder(vcodecs, "h264_texture_amf"))
ui->simpleOutStrEncoder->addItem(
ENCODER_STR("Hardware.AMD.H264"),
QString(SIMPLE_ENCODER_AMD));
/* Preprocessor guard required for the macOS version check */
#ifdef __APPLE__
if (service_supports_encoder(
codecs, "com.apple.videotoolbox.videoencoder.ave.avc")
vcodecs, "com.apple.videotoolbox.videoencoder.ave.avc")
#ifndef __aarch64__
&& os_get_emulation_status() == true
#endif
@@ -1512,7 +1625,7 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
}
#ifdef ENABLE_HEVC
if (service_supports_encoder(
codecs, "com.apple.videotoolbox.videoencoder.ave.hevc")
vcodecs, "com.apple.videotoolbox.videoencoder.ave.hevc")
#ifndef __aarch64__
&& os_get_emulation_status() == true
#endif
@@ -1525,36 +1638,72 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
}
#endif
#endif
if (service_supports_encoder(acodecs, "CoreAudio_AAC") ||
service_supports_encoder(acodecs, "libfdk_aac") ||
service_supports_encoder(acodecs, "ffmpeg_aac"))
ui->simpleOutStrAEncoder->addItem("AAC", "aac");
if (service_supports_encoder(acodecs, "ffmpeg_opus"))
ui->simpleOutStrAEncoder->addItem("Opus", "opus");
#undef ENCODER_STR
/* ------------------------------------------------- */
/* Find fallback encoders */
if (!lastAdvEnc.isEmpty()) {
int idx = ui->advOutEncoder->findData(lastAdvEnc);
if (!lastAdvVideoEnc.isEmpty()) {
int idx = ui->advOutEncoder->findData(lastAdvVideoEnc);
if (idx == -1) {
lastAdvEnc = get_adv_fallback(lastAdvEnc);
lastAdvVideoEnc = get_adv_fallback(lastAdvVideoEnc);
ui->advOutEncoder->setProperty("changed",
QVariant(true));
OutputsChanged();
}
idx = ui->advOutEncoder->findData(lastAdvEnc);
idx = ui->advOutEncoder->findData(lastAdvVideoEnc);
s2.unblock();
ui->advOutEncoder->setCurrentIndex(idx);
}
if (!lastEnc.isEmpty()) {
int idx = ui->simpleOutStrEncoder->findData(lastEnc);
if (!lastAdvAudioEnc.isEmpty()) {
int idx = ui->advOutAEncoder->findData(lastAdvAudioEnc);
if (idx == -1) {
lastEnc = get_simple_fallback(lastEnc);
lastAdvAudioEnc =
get_adv_audio_fallback(lastAdvAudioEnc);
ui->advOutAEncoder->setProperty("changed",
QVariant(true));
OutputsChanged();
}
idx = ui->advOutAEncoder->findData(lastAdvAudioEnc);
s4.unblock();
ui->advOutAEncoder->setCurrentIndex(idx);
}
if (!lastVideoEnc.isEmpty()) {
int idx = ui->simpleOutStrEncoder->findData(lastVideoEnc);
if (idx == -1) {
lastVideoEnc = get_simple_fallback(lastVideoEnc);
ui->simpleOutStrEncoder->setProperty("changed",
QVariant(true));
OutputsChanged();
}
idx = ui->simpleOutStrEncoder->findData(lastEnc);
idx = ui->simpleOutStrEncoder->findData(lastVideoEnc);
s1.unblock();
ui->simpleOutStrEncoder->setCurrentIndex(idx);
}
if (!lastAudioEnc.isEmpty()) {
int idx = ui->simpleOutStrAEncoder->findData(lastAudioEnc);
if (idx == -1) {
lastAudioEnc = (lastAudioEnc == "opus") ? "aac"
: "opus";
ui->simpleOutStrAEncoder->setProperty("changed",
QVariant(true));
OutputsChanged();
}
idx = ui->simpleOutStrAEncoder->findData(lastAudioEnc);
s3.unblock();
ui->simpleOutStrAEncoder->setCurrentIndex(idx);
}
}