提交 b218957f 编写于 作者: K kc5nra 提交者: John Bradley

UI: Add Format, Audio and Video ComboBoxes

Adds ComboBoxes for selecting format and audio/video
codecs. The ComboBoxes also show only valid codec
combinations for a particular container format.
上级 f04be519
......@@ -189,6 +189,7 @@ endif()
target_link_libraries(obs
libobs
libff
Qt5::Widgets
Qt5::Network
${obs_PLATFORM_LIBRARIES})
......
......@@ -276,9 +276,17 @@ Basic.Settings.Output.Adv.Recording.UseStreamEncoder="(Use stream encoder)"
Basic.Settings.Output.Adv.FFmpeg.SaveFilter.Common="Common recording formats"
Basic.Settings.Output.Adv.FFmpeg.SaveFilter.All="All Files"
Basic.Settings.Output.Adv.FFmpeg.SavePathURL="File path or URL"
Basic.Settings.Output.Adv.FFmpeg.VEncoder="Video Encoder (blank=default)"
Basic.Settings.Output.Adv.FFmpeg.Format="Container Format"
Basic.Settings.Output.Adv.FFmpeg.FormatAudio="Audio"
Basic.Settings.Output.Adv.FFmpeg.FormatVideo="Video"
Basic.Settings.Output.Adv.FFmpeg.FormatDefault="Default Format"
Basic.Settings.Output.Adv.FFmpeg.FormatDesc="Container Format Description"
Basic.Settings.Output.Adv.FFmpeg.FormatDescDef="Audio/Video Codec guessed from File path or URL"
Basic.Settings.Output.Adv.FFmpeg.AVEncoderDefault="Default Encoder"
Basic.Settings.Output.Adv.FFmpeg.AVEncoderDisable="Disable Encoder"
Basic.Settings.Output.Adv.FFmpeg.VEncoder="Video Encoder"
Basic.Settings.Output.Adv.FFmpeg.VEncoderSettings="Video Encoder Settings (if any)"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Audio Encoder (blank=default)"
Basic.Settings.Output.Adv.FFmpeg.AEncoder="Audio Encoder"
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings="Audio Encoder Settings (if any)"
# basic mode 'video' settings
......
......@@ -1241,13 +1241,20 @@
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.Format</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_40">
<property name="text">
<string>Basic.Settings.Output.VideoBitrate</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="3" column="1">
<widget class="QSpinBox" name="advOutFFVBitrate">
<property name="minimum">
<number>0</number>
......@@ -1260,34 +1267,60 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="4" column="0">
<widget class="QCheckBox" name="advOutFFUseRescale">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Basic.Settings.Output.Adv.Rescale</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="advOutFFRescale">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_37">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.VEncoder</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="advOutFFVEncoder"/>
<item row="5" column="1">
<widget class="QComboBox" name="advOutFFVEncoder"/>
</item>
<item row="4" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_38">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.VEncoderSettings</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="6" column="1">
<widget class="QLineEdit" name="advOutFFVCfg"/>
</item>
<item row="5" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_41">
<property name="text">
<string>Basic.Settings.Output.AudioBitrate</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="7" column="1">
<widget class="QSpinBox" name="advOutFFABitrate">
<property name="minimum">
<number>32</number>
......@@ -1303,60 +1336,14 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label_47">
<property name="text">
<string>Basic.Settings.Output.Adv.AudioTrack</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.AEncoder</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="advOutFFAEncoder"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_46">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="advOutFFACfg"/>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="advOutFFUseRescale">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Basic.Settings.Output.Adv.Rescale</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="advOutFFRescale">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QWidget" name="widget_10" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
......@@ -1411,6 +1398,43 @@
</layout>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.AEncoder</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_46">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="advOutFFACfg"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="advOutFFFormat"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="advOutFFFormatDesc">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_44">
<property name="text">
<string>Basic.Settings.Output.Adv.FFmpeg.FormatDesc</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QComboBox" name="advOutFFAEncoder"/>
</item>
</layout>
</widget>
</widget>
......
......@@ -495,8 +495,14 @@ inline void AdvancedOutput::SetupFFmpeg()
"FFRescale");
const char *rescaleRes = config_get_string(main->Config(), "AdvOut",
"FFRescaleRes");
const char *formatName = config_get_string(main->Config(), "AdvOut",
"FFFormat");
const char *mimeType = config_get_string(main->Config(), "AdvOut",
"FFFormatMimeType");
const char *vEncoder = config_get_string(main->Config(), "AdvOut",
"FFVEncoder");
int vEncoderId = config_get_int(main->Config(), "AdvOut",
"FFVEncoderId");
const char *vEncCustom = config_get_string(main->Config(), "AdvOut",
"FFVCustom");
int aBitrate = config_get_int(main->Config(), "AdvOut",
......@@ -505,16 +511,22 @@ inline void AdvancedOutput::SetupFFmpeg()
"FFAudioTrack");
const char *aEncoder = config_get_string(main->Config(), "AdvOut",
"FFAEncoder");
int aEncoderId = config_get_int(main->Config(), "AdvOut",
"FFAEncoderId");
const char *aEncCustom = config_get_string(main->Config(), "AdvOut",
"FFACustom");
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "url", url);
obs_data_set_string(settings, "format_name", formatName);
obs_data_set_string(settings, "format_mime_type", mimeType);
obs_data_set_int(settings, "video_bitrate", vBitrate);
obs_data_set_string(settings, "video_encoder", vEncoder);
obs_data_set_int(settings, "video_encoder_id", vEncoderId);
obs_data_set_string(settings, "video_settings", vEncCustom);
obs_data_set_int(settings, "audio_bitrate", aBitrate);
obs_data_set_string(settings, "audio_encoder", aEncoder);
obs_data_set_int(settings, "audio_encoder_id", aEncoderId);
obs_data_set_string(settings, "audio_settings", aEncCustom);
if (rescale && rescaleRes && *rescaleRes) {
......
......@@ -25,6 +25,9 @@
#include <QCloseEvent>
#include <QFileDialog>
#include <QDirIterator>
#include <QVariant>
#include <QTreeView>
#include <QStandardItemModel>
#include "obs-app.hpp"
#include "platform.hpp"
......@@ -37,6 +40,51 @@
using namespace std;
// Used for QVariant in codec comboboxes
namespace {
struct FormatDesc {
const char *name = nullptr;
const char *mimeType = nullptr;
const ff_format_desc *desc = nullptr;
inline FormatDesc() = default;
inline FormatDesc(const char *name, const char *mimeType,
const ff_format_desc *desc = nullptr)
: name(name), mimeType(mimeType), desc(desc) {}
bool operator==(const FormatDesc &f) const
{
if ((name == nullptr) ^ (f.name == nullptr))
return false;
if (name != nullptr && strcmp(name, f.name) != 0)
return false;
if ((mimeType == nullptr) ^ (f.mimeType == nullptr))
return false;
if (mimeType != nullptr && strcmp(mimeType, f.mimeType) != 0)
return false;
return true;
}
};
struct CodecDesc {
const char *name = nullptr;
int id = 0;
inline CodecDesc() = default;
inline CodecDesc(const char *name, int id) : name(name), id(id) {}
bool operator==(const CodecDesc &codecDesc) const
{
if ((name == nullptr) ^ (codecDesc.name == nullptr))
return false;
if (id != codecDesc.id)
return false;
return name == nullptr || strcmp(name, codecDesc.name) == 0;
}
};
}
Q_DECLARE_METATYPE(FormatDesc)
Q_DECLARE_METATYPE(CodecDesc)
/* parses "[width]x[height]", string, i.e. 1024x768 */
static bool ConvertResText(const char *res, uint32_t &cx, uint32_t &cy)
{
......@@ -102,6 +150,40 @@ static inline QString GetComboData(QComboBox *combo)
return combo->itemData(idx).toString();
}
static int FindEncoder(QComboBox *combo, const char *name, int id)
{
CodecDesc codecDesc(name, id);
for(int i = 0; i < combo->count(); i++) {
QVariant v = combo->itemData(i);
if (!v.isNull()) {
if (codecDesc == v.value<CodecDesc>()) {
return i;
break;
}
}
}
return -1;
}
static CodecDesc GetDefaultCodecDesc(const ff_format_desc *formatDesc,
ff_codec_type codecType)
{
int id = 0;
switch (codecType) {
case FF_CODEC_AUDIO:
id = ff_format_desc_audio(formatDesc);
break;
case FF_CODEC_VIDEO:
id = ff_format_desc_video(formatDesc);
break;
default:
return CodecDesc();
}
return CodecDesc(ff_format_desc_get_default_name(formatDesc, codecType),
id);
}
void OBSBasicSettings::HookWidget(QWidget *widget, const char *signal,
const char *slot)
{
......@@ -173,17 +255,18 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->advOutRecTrack3, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutRecTrack4, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFURL, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFFormat, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVBitrate, SCROLL_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFUseRescale, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFRescale, CBEDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVEncoder, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVCfg, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFABitrate, SCROLL_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack1, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack2, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack3, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFTrack4, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFAEncoder, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFAEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFACfg, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutTrack1Bitrate, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutTrack1Name, EDIT_CHANGED, OUTPUTS_CHANGED);
......@@ -219,9 +302,13 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
//Apply button disabled until change.
EnableApplyButton(false);
// Initialize libff library
ff_init();
LoadServiceTypes();
LoadEncoderTypes();
LoadColorRanges();
LoadFormats();
LoadSettings(false);
}
......@@ -320,6 +407,122 @@ void OBSBasicSettings::LoadColorRanges()
ui->colorRange->addItem(CS_FULL_STR, "Full");
}
#define AV_FORMAT_DEFAULT_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.FormatDefault")
#define AUDIO_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.FormatAudio")
#define VIDEO_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.FormatVideo")
void OBSBasicSettings::LoadFormats()
{
formats.reset(ff_format_supported());
const ff_format_desc *format = formats.get();
while(format != nullptr) {
bool audio = ff_format_desc_has_audio(format);
bool video = ff_format_desc_has_video(format);
FormatDesc formatDesc(ff_format_desc_name(format),
ff_format_desc_mime_type(format),
format);
if (audio || video) {
QString itemText(ff_format_desc_name(format));
if (audio ^ video)
itemText += QString(" (%1)").arg(
audio ? AUDIO_STR : VIDEO_STR);
ui->advOutFFFormat->addItem(itemText,
qVariantFromValue(formatDesc));
}
format = ff_format_desc_next(format);
}
ui->advOutFFFormat->model()->sort(0);
ui->advOutFFFormat->insertItem(0, AV_FORMAT_DEFAULT_STR);
}
static void AddCodec(QComboBox *combo, const ff_codec_desc *codec_desc)
{
QString itemText(ff_codec_desc_name(codec_desc));
if (ff_codec_desc_is_alias(codec_desc))
itemText += QString(" (%1)").arg(
ff_codec_desc_base_name(codec_desc));
CodecDesc cd(ff_codec_desc_name(codec_desc),
ff_codec_desc_id(codec_desc));
combo->addItem(itemText, qVariantFromValue(cd));
}
#define AV_ENCODER_DEFAULT_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.AVEncoderDefault")
static void AddDefaultCodec(QComboBox *combo, const ff_format_desc *formatDesc,
ff_codec_type codecType)
{
CodecDesc cd = GetDefaultCodecDesc(formatDesc, codecType);
int existingIdx = FindEncoder(combo, cd.name, cd.id);
if (existingIdx >= 0)
combo->removeItem(existingIdx);
combo->addItem(QString("%1 (%2)").arg(cd.name, AV_ENCODER_DEFAULT_STR),
qVariantFromValue(cd));
}
#define AV_ENCODER_DISABLE_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.AVEncoderDisable")
void OBSBasicSettings::ReloadCodecs(const ff_format_desc *formatDesc)
{
ui->advOutFFAEncoder->blockSignals(true);
ui->advOutFFVEncoder->blockSignals(true);
ui->advOutFFAEncoder->clear();
ui->advOutFFVEncoder->clear();
if (formatDesc == nullptr)
return;
OBSFFCodecDesc codecDescs(ff_codec_supported(formatDesc));
const ff_codec_desc *codec = codecDescs.get();
while(codec != nullptr) {
switch (ff_codec_desc_type(codec)) {
case FF_CODEC_AUDIO:
AddCodec(ui->advOutFFAEncoder, codec);
break;
case FF_CODEC_VIDEO:
AddCodec(ui->advOutFFVEncoder, codec);
break;
default:
break;
}
codec = ff_codec_desc_next(codec);
}
if (ff_format_desc_has_audio(formatDesc))
AddDefaultCodec(ui->advOutFFAEncoder, formatDesc,
FF_CODEC_AUDIO);
if (ff_format_desc_has_video(formatDesc))
AddDefaultCodec(ui->advOutFFVEncoder, formatDesc,
FF_CODEC_VIDEO);
ui->advOutFFAEncoder->model()->sort(0);
ui->advOutFFVEncoder->model()->sort(0);
QVariant disable = qVariantFromValue(CodecDesc());
ui->advOutFFAEncoder->insertItem(0, AV_ENCODER_DISABLE_STR, disable);
ui->advOutFFVEncoder->insertItem(0, AV_ENCODER_DISABLE_STR, disable);
ui->advOutFFAEncoder->blockSignals(false);
ui->advOutFFVEncoder->blockSignals(false);
}
void OBSBasicSettings::LoadLanguageList()
{
const char *currentLang = App()->GetLocale();
......@@ -783,9 +986,38 @@ void OBSBasicSettings::LoadAdvOutputRecordingEncoderProperties()
SetComboByValue(ui->advOutRecEncoder, encoder);
}
static void SelectFormat(QComboBox *combo, const char *name,
const char *mimeType)
{
FormatDesc formatDesc(name, mimeType);
for(int i = 0; i < combo->count(); i++) {
QVariant v = combo->itemData(i);
if (!v.isNull()) {
if (formatDesc == v.value<FormatDesc>()) {
combo->setCurrentIndex(i);
return;
}
}
}
combo->setCurrentIndex(0);
}
static void SelectEncoder(QComboBox *combo, const char *name, int id)
{
int idx = FindEncoder(combo, name, id);
if (idx >= 0)
combo->setCurrentIndex(idx);
}
void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
{
const char *url = config_get_string(main->Config(), "AdvOut", "FFURL");
const char *format = config_get_string(main->Config(), "AdvOut",
"FFFormat");
const char *mimeType = config_get_string(main->Config(), "AdvOut",
"FFFormatMimeType");
int videoBitrate = config_get_int(main->Config(), "AdvOut",
"FFVBitrate");
bool rescale = config_get_bool(main->Config(), "AdvOut",
......@@ -794,6 +1026,8 @@ void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
"FFRescaleRes");
const char *vEncoder = config_get_string(main->Config(), "AdvOut",
"FFVEncoder");
int vEncoderId = config_get_int(main->Config(), "AdvOut",
"FFVEncoderId");
const char *vEncCustom = config_get_string(main->Config(), "AdvOut",
"FFVCustom");
int audioBitrate = config_get_int(main->Config(), "AdvOut",
......@@ -802,18 +1036,21 @@ void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
"FFAudioTrack");
const char *aEncoder = config_get_string(main->Config(), "AdvOut",
"FFAEncoder");
int aEncoderId = config_get_int(main->Config(), "AdvOut",
"FFAEncoderId");
const char *aEncCustom = config_get_string(main->Config(), "AdvOut",
"FFACustom");
ui->advOutFFURL->setText(url);
SelectFormat(ui->advOutFFFormat, format, mimeType);
ui->advOutFFVBitrate->setValue(videoBitrate);
ui->advOutFFUseRescale->setChecked(rescale);
ui->advOutFFRescale->setEnabled(rescale);
ui->advOutFFRescale->setCurrentText(rescaleRes);
ui->advOutFFVEncoder->setText(vEncoder);
SelectEncoder(ui->advOutFFVEncoder, vEncoder, vEncoderId);
ui->advOutFFVCfg->setText(vEncCustom);
ui->advOutFFABitrate->setValue(audioBitrate);
ui->advOutFFAEncoder->setText(aEncoder);
SelectEncoder(ui->advOutFFAEncoder, aEncoder, aEncoderId);
ui->advOutFFACfg->setText(aEncCustom);
switch (audioTrack) {
......@@ -887,6 +1124,34 @@ void OBSBasicSettings::LoadOutputSettings()
loading = false;
}
void OBSBasicSettings::SetAdvOutputFFmpegEnablement(
ff_codec_type encoderType, bool enabled,
bool enableEncoder)
{
bool rescale = config_get_bool(main->Config(), "AdvOut",
"FFRescale");
switch (encoderType) {
case FF_CODEC_VIDEO:
ui->advOutFFVBitrate->setEnabled(enabled);
ui->advOutFFUseRescale->setEnabled(enabled);
ui->advOutFFRescale->setEnabled(enabled && rescale);
ui->advOutFFVEncoder->setEnabled(enabled || enableEncoder);
ui->advOutFFVCfg->setEnabled(enabled);
break;
case FF_CODEC_AUDIO:
ui->advOutFFABitrate->setEnabled(enabled);
ui->advOutFFAEncoder->setEnabled(enabled || enableEncoder);
ui->advOutFFACfg->setEnabled(enabled);
ui->advOutFFTrack1->setEnabled(enabled);
ui->advOutFFTrack2->setEnabled(enabled);
ui->advOutFFTrack3->setEnabled(enabled);
ui->advOutFFTrack4->setEnabled(enabled);
default:
break;
}
}
static inline void LoadListValue(QComboBox *widget, const char *text,
const char *val)
{
......@@ -1147,6 +1412,38 @@ static void SaveTrackIndex(config_t *config, const char *section,
else if (check4->isChecked()) config_set_int(config, section, name, 4);
}
void OBSBasicSettings::SaveFormat(QComboBox *combo)
{
QVariant v = combo->currentData();
if (!v.isNull()) {
FormatDesc desc = v.value<FormatDesc>();
config_set_string(main->Config(), "AdvOut", "FFFormat",
desc.name);
config_set_string(main->Config(), "AdvOut", "FFFormatMimeType",
desc.mimeType);
} else {
config_set_string(main->Config(), "AdvOut", "FFFormat",
nullptr);
config_set_string(main->Config(), "AdvOut", "FFFormatMimeType",
nullptr);
}
}
void OBSBasicSettings::SaveEncoder(QComboBox *combo, const char *section,
const char *value)
{
QVariant v = combo->currentData();
CodecDesc cd;
if (!v.isNull())
cd = v.value<CodecDesc>();
config_set_int(main->Config(), section,
QT_TO_UTF8(QString("%1Id").arg(value)), cd.id);
if (cd.id != 0)
config_set_string(main->Config(), section, value, cd.name);
else
config_set_string(main->Config(), section, value, nullptr);
}
void OBSBasicSettings::SaveOutputSettings()
{
config_set_string(main->Config(), "Output", "Mode",
......@@ -1190,13 +1487,14 @@ void OBSBasicSettings::SaveOutputSettings()
ui->advOutRecTrack3, ui->advOutRecTrack4);
SaveEdit(ui->advOutFFURL, "AdvOut", "FFURL");
SaveFormat(ui->advOutFFFormat);
SaveSpinBox(ui->advOutFFVBitrate, "AdvOut", "FFVBitrate");
SaveCheckBox(ui->advOutFFUseRescale, "AdvOut", "FFRescale");
SaveCombo(ui->advOutFFRescale, "AdvOut", "FFRescaleRes");
SaveEdit(ui->advOutFFVEncoder, "AdvOut", "FFVEncoder");
SaveEncoder(ui->advOutFFVEncoder, "AdvOut", "FFVEncoder");
SaveEdit(ui->advOutFFVCfg, "AdvOut", "FFVCustom");
SaveSpinBox(ui->advOutFFABitrate, "AdvOut", "FFABitrate");
SaveEdit(ui->advOutFFAEncoder, "AdvOut", "FFAEncoder");
SaveEncoder(ui->advOutFFAEncoder, "AdvOut", "FFAEncoder");
SaveEdit(ui->advOutFFACfg, "AdvOut", "FFACustom");
SaveTrackIndex(main->Config(), "AdvOut", "FFAudioTrack",
ui->advOutFFTrack1, ui->advOutFFTrack2,
......@@ -1442,6 +1740,59 @@ void OBSBasicSettings::on_advOutRecEncoder_currentIndexChanged(int idx)
}
}
#define DEFAULT_CONTAINER_STR \
QTStr("Basic.Settings.Output.Adv.FFmpeg.FormatDescDef")
void OBSBasicSettings::on_advOutFFFormat_currentIndexChanged(int idx)
{
const QVariant itemDataVariant = ui->advOutFFFormat->itemData(idx);
if (!itemDataVariant.isNull()) {
FormatDesc desc = itemDataVariant.value<FormatDesc>();
SetAdvOutputFFmpegEnablement(FF_CODEC_AUDIO,
ff_format_desc_has_audio(desc.desc),
false);
SetAdvOutputFFmpegEnablement(FF_CODEC_VIDEO,
ff_format_desc_has_video(desc.desc),
false);
ReloadCodecs(desc.desc);
ui->advOutFFFormatDesc->setText(ff_format_desc_long_name(
desc.desc));
CodecDesc defaultAudioCodecDesc =
GetDefaultCodecDesc(desc.desc, FF_CODEC_AUDIO);
CodecDesc defaultVideoCodecDesc =
GetDefaultCodecDesc(desc.desc, FF_CODEC_VIDEO);
SelectEncoder(ui->advOutFFAEncoder, defaultAudioCodecDesc.name,
defaultAudioCodecDesc.id);
SelectEncoder(ui->advOutFFVEncoder, defaultVideoCodecDesc.name,
defaultVideoCodecDesc.id);
} else {
ReloadCodecs(nullptr);
ui->advOutFFFormatDesc->setText(DEFAULT_CONTAINER_STR);
}
}
void OBSBasicSettings::on_advOutFFAEncoder_currentIndexChanged(int idx)
{
const QVariant itemDataVariant = ui->advOutFFAEncoder->itemData(idx);
if (!itemDataVariant.isNull()) {
CodecDesc desc = itemDataVariant.value<CodecDesc>();
SetAdvOutputFFmpegEnablement(FF_CODEC_AUDIO,
desc.id != 0 || desc.name != nullptr, true);
}
}
void OBSBasicSettings::on_advOutFFVEncoder_currentIndexChanged(int idx)
{
const QVariant itemDataVariant = ui->advOutFFVEncoder->itemData(idx);
if (!itemDataVariant.isNull()) {
CodecDesc desc = itemDataVariant.value<CodecDesc>();
SetAdvOutputFFmpegEnablement(FF_CODEC_VIDEO,
desc.id != 0 || desc.name != nullptr, true);
}
}
#define INVALID_RES_STR "Basic.Settings.Video.InvalidResolution"
static bool ValidResolutions(Ui::OBSBasicSettings *ui)
......
......@@ -23,6 +23,8 @@
#include <memory>
#include <string>
#include <libff/ff-util.h>
#include <obs.h>
class OBSBasic;
......@@ -32,6 +34,23 @@ class OBSPropertiesView;
#include "ui_OBSBasicSettings.h"
class OBSFFDeleter
{
public:
void operator()(const ff_format_desc *format)
{
ff_format_desc_free(format);
}
void operator()(const ff_codec_desc *codec)
{
ff_codec_desc_free(codec);
}
};
using OBSFFCodecDesc = std::unique_ptr<const ff_codec_desc,
OBSFFDeleter>;
using OBSFFFormatDesc = std::unique_ptr<const ff_format_desc,
OBSFFDeleter>;
class OBSBasicSettings : public QDialog {
Q_OBJECT
......@@ -49,6 +68,8 @@ private:
bool loading = true;
std::string savedTheme;
OBSFFFormatDesc formats;
OBSPropertiesView *streamProperties = nullptr;
OBSPropertiesView *streamEncoderProps = nullptr;
OBSPropertiesView *recordEncoderProps = nullptr;
......@@ -63,6 +84,9 @@ private:
const char *value);
void SaveSpinBox(QSpinBox *widget, const char *section,
const char *value);
void SaveFormat(QComboBox *combo);
void SaveEncoder(QComboBox *combo, const char *section,
const char *value);
inline bool Changed() const
{
......@@ -93,6 +117,8 @@ private:
void LoadServiceTypes();
void LoadEncoderTypes();
void LoadColorRanges();
void LoadFormats();
void ReloadCodecs(const ff_format_desc *formatDesc);
void LoadGeneralSettings();
void LoadStream1Settings();
......@@ -117,6 +143,9 @@ private:
void LoadAdvOutputRecordingEncoderProperties();
void LoadAdvOutputFFmpegSettings();
void LoadAdvOutputAudioSettings();
void SetAdvOutputFFmpegEnablement(
ff_codec_type encoderType, bool enabled,
bool enableEncode = false);
/* audio */
void LoadListValues(QComboBox *widget, obs_property_t *prop,
......@@ -154,6 +183,9 @@ private slots:
void on_advOutFFPathBrowse_clicked();
void on_advOutEncoder_currentIndexChanged(int idx);
void on_advOutRecEncoder_currentIndexChanged(int idx);
void on_advOutFFFormat_currentIndexChanged(int idx);
void on_advOutFFAEncoder_currentIndexChanged(int idx);
void on_advOutFFVEncoder_currentIndexChanged(int idx);
void on_baseResolution_editTextChanged(const QString &text);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册