mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-03-06 07:36:12 -05:00
UI: Add audio codec selections
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user