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.
This commit is contained in:
parent
f04be51947
commit
b218957f38
@ -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,77 +1267,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" 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>
|
||||
<item row="4" 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">
|
||||
<widget class="QLineEdit" name="advOutFFVCfg"/>
|
||||
</item>
|
||||
<item row="5" 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">
|
||||
<widget class="QSpinBox" name="advOutFFABitrate">
|
||||
<property name="minimum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>4096</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" 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">
|
||||
@ -1346,7 +1283,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="advOutFFRescale">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@ -1356,7 +1293,57 @@
|
||||
</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="5" column="1">
|
||||
<widget class="QComboBox" name="advOutFFVEncoder"/>
|
||||
</item>
|
||||
<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="6" column="1">
|
||||
<widget class="QLineEdit" name="advOutFFVCfg"/>
|
||||
</item>
|
||||
<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="7" column="1">
|
||||
<widget class="QSpinBox" name="advOutFFABitrate">
|
||||
<property name="minimum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>4096</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<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="8" 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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user