Skip to content

Commit

Permalink
obs-webrtc: Add WebRTC Simulcast Support
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean-Der committed Jul 12, 2023
1 parent 8f830dd commit 5f24f56
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 18 deletions.
2 changes: 2 additions & 0 deletions UI/data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,7 @@ Basic.Settings.Output.RetryDelay="Retry Delay"
Basic.Settings.Output.MaxRetries="Maximum Retries"
Basic.Settings.Output.Advanced="Enable Custom Encoder Settings (Advanced)"
Basic.Settings.Output.EncoderPreset="Encoder Preset"
Basic.Settings.Output.Simulcast="Enable Simulcast"
Basic.Settings.Output.EncoderPreset.ultrafast="%1 (low CPU usage, lowest quality)"
Basic.Settings.Output.EncoderPreset.veryfast="%1 (default) (medium CPU usage, standard quality)"
Basic.Settings.Output.EncoderPreset.fast="%1 (high CPU usage, high quality)"
Expand All @@ -1019,6 +1020,7 @@ Basic.Settings.Output.CustomMuxerSettings="Custom Muxer Settings"
Basic.Settings.Output.NoSpaceFileName="Generate File Name without Space"

# basic mode 'output' settings - advanced section
Basic.Settings.Output.Adv.Simulcast="Enable Simulcast"
Basic.Settings.Output.Adv.Rescale="Rescale Output"
Basic.Settings.Output.Adv.AudioTrack="Audio Track"
Basic.Settings.Output.Adv.Streaming="Streaming"
Expand Down
32 changes: 26 additions & 6 deletions UI/forms/OBSBasicSettings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@
<bool>true</bool>
</property>
</widget>
</item>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
Expand All @@ -1776,11 +1776,21 @@
<cstring>simpleOutCustom</cstring>
</property>
</widget>
</item>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="simpleOutCustom"/>
</item>
<item row="6" column="0">
<item row="6" column="1">
<widget class="QCheckBox" name="simpleOutSimulcast">
<property name="text">
<string>Basic.Settings.Output.Simulcast</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="simpleOutStrAEncoderLabel">
<property name="text">
<string>Basic.Settings.Output.Encoder.Audio</string>
Expand All @@ -1790,7 +1800,7 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QComboBox" name="simpleOutStrAEncoder"/>
</item>
</layout>
Expand Down Expand Up @@ -2524,7 +2534,17 @@
<item row="3" column="1">
<widget class="QComboBox" name="advOutEncoder"/>
</item>
<item row="4" column="0">
<item row="4" column="1">
<widget class="QCheckBox" name="advOutUseSimulcast">
<property name="text">
<string>Basic.Settings.Output.Adv.Simulcast</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="advOutUseRescale">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
Expand All @@ -2540,7 +2560,7 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QComboBox" name="advOutRescale">
<property name="enabled">
<bool>false</bool>
Expand Down
68 changes: 67 additions & 1 deletion UI/window-basic-main-outputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,10 @@ void SimpleOutput::LoadStreamingPreset_Lossy(const char *encoderId)
if (!videoStreaming)
throw "Failed to create video streaming encoder (simple output)";
obs_encoder_release(videoStreaming);

if (config_get_bool(main->Config(), "SimpleOutput", "UseSimulcast")) {
CreateSimulcastEncoders(encoderId);
}
}

/* mistakes have been made to lead us to this. */
Expand Down Expand Up @@ -838,9 +842,14 @@ void SimpleOutput::Update()
default:
obs_encoder_set_preferred_video_format(videoStreaming,
VIDEO_FORMAT_NV12);
for (auto enc : simulcastEncoders)
obs_encoder_set_preferred_video_format(
enc, VIDEO_FORMAT_NV12);
}

obs_encoder_update(videoStreaming, videoSettings);
ConfigureSimulcastEncoders(videoSettings, videoBitrate);

obs_encoder_update(audioStreaming, audioSettings);
obs_encoder_update(audioArchive, audioSettings);
}
Expand Down Expand Up @@ -1039,6 +1048,9 @@ inline void SimpleOutput::SetupOutputs()
{
SimpleOutput::Update();
obs_encoder_set_video(videoStreaming, obs_get_video());
for (auto enc : simulcastEncoders)
obs_encoder_set_video(enc, obs_get_video());

obs_encoder_set_audio(audioStreaming, obs_get_audio());
obs_encoder_set_audio(audioArchive, obs_get_audio());
int tracks =
Expand Down Expand Up @@ -1135,7 +1147,11 @@ bool SimpleOutput::SetupStreaming(obs_service_t *service)
outputType = type;
}

obs_output_set_video_encoder(streamOutput, videoStreaming);
obs_output_set_video_encoder2(streamOutput, videoStreaming, 0);
for (size_t i = 0; i < simulcastEncoders.size(); i++)
obs_output_set_video_encoder2(streamOutput,
simulcastEncoders[i], i + 1);

obs_output_set_audio_encoder(streamOutput, audioStreaming, 0);
obs_output_set_service(streamOutput, service);
return true;
Expand Down Expand Up @@ -2433,6 +2449,56 @@ std::string BasicOutputHandler::GetRecordingFilename(
return dst;
}

void BasicOutputHandler::CreateSimulcastEncoders(const char *encoderId)
{
std::string encoder_name = "simulcast_0";
for (auto i = 0; i < 2; i++) {
encoder_name[encoder_name.size() - 1] = to_string(i).at(0);
auto simulcast_encoder = obs_video_encoder_create(
encoderId, encoder_name.c_str(), nullptr, nullptr);

if (simulcast_encoder) {
simulcastEncoders.push_back(simulcast_encoder);
obs_encoder_release(simulcast_encoder);
} else {
blog(LOG_WARNING,
"Failed to create video streaming simulcast encoders (simple output)");
}
}
}

void BasicOutputHandler::ConfigureSimulcastEncoders(obs_data_t *videoSettings,
int videoBitrate)
{
video_t *video = obs_get_video();

if (simulcastEncoders.size() > 0) {
uint32_t width = video_output_get_width(video) / 1.5;
width -= width % 2;

uint32_t height = video_output_get_height(video) / 1.5;
height -= height % 2;

obs_data_set_int(videoSettings, "bitrate", videoBitrate / 2);
obs_encoder_update(simulcastEncoders[0], videoSettings);
obs_encoder_set_scaled_size(simulcastEncoders[0], width,
height);
}

if (simulcastEncoders.size() > 1) {
uint32_t width = video_output_get_width(video) / 2;
width -= width % 2;

uint32_t height = video_output_get_height(video) / 2;
height -= height % 2;

obs_data_set_int(videoSettings, "bitrate", videoBitrate / 4);
obs_encoder_update(simulcastEncoders[1], videoSettings);
obs_encoder_set_scaled_size(simulcastEncoders[1], width,
height);
}
}

BasicOutputHandler *CreateSimpleOutputHandler(OBSBasic *main)
{
return new SimpleOutput(main);
Expand Down
6 changes: 6 additions & 0 deletions UI/window-basic-main-outputs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct BasicOutputHandler {
obs_scene_t *vCamSourceScene = nullptr;
obs_sceneitem_t *vCamSourceSceneItem = nullptr;

std::vector<OBSEncoder> simulcastEncoders;

std::string outputType;
std::string lastError;

Expand Down Expand Up @@ -79,6 +81,10 @@ struct BasicOutputHandler {
const char *container, bool noSpace,
bool overwrite, const char *format,
bool ffmpeg);

void CreateSimulcastEncoders(const char *encoderId);
void ConfigureSimulcastEncoders(obs_data_t *videoSettings,
int videoBitrate);
};

BasicOutputHandler *CreateSimpleOutputHandler(OBSBasic *main);
Expand Down
8 changes: 8 additions & 0 deletions UI/window-basic-settings-stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,14 @@ void OBSBasicSettings::on_service_currentIndexChanged(int idx)
if (idx == 0)
lastCustomServer = ui->customServer->text();
}

if (IsWHIP()) {
ui->simpleOutSimulcast->show();
ui->advOutUseSimulcast->show();
} else {
ui->simpleOutSimulcast->hide();
ui->advOutUseSimulcast->hide();
}
}

void OBSBasicSettings::on_customServer_textChanged(const QString &)
Expand Down
18 changes: 18 additions & 0 deletions UI/window-basic-settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->simpleOutAdvanced, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutPreset, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutCustom, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutSimulcast, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutRecQuality, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutRecEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutRecAEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
Expand All @@ -506,6 +507,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->simpleRBMegsMax, SCROLL_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutAEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutUseSimulcast, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutUseRescale, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutRescale, CBEDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutTrack1, CHECK_CHANGED, OUTPUTS_CHANGED);
Expand Down Expand Up @@ -1927,6 +1929,8 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
config_get_uint(main->Config(), "SimpleOutput", "ABitrate");
bool advanced =
config_get_bool(main->Config(), "SimpleOutput", "UseAdvanced");
bool simulcast =
config_get_bool(main->Config(), "SimpleOutput", "UseSimulcast");
const char *preset =
config_get_string(main->Config(), "SimpleOutput", "Preset");
const char *qsvPreset =
Expand Down Expand Up @@ -1996,6 +2000,15 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
ui->simpleOutAdvanced->setChecked(advanced);
ui->simpleOutCustom->setText(custom);

OBSService service = GetStream1Service();
if (strcmp(obs_service_get_id(service), "whip_custom") == 0) {
ui->simpleOutSimulcast->show();
} else {
ui->simpleOutSimulcast->hide();
}

ui->simpleOutSimulcast->setChecked(simulcast);

idx = ui->simpleOutRecQuality->findData(QString(recQual));
if (idx == -1)
idx = 0;
Expand Down Expand Up @@ -2075,11 +2088,13 @@ static inline QString makeFormatToolTip()

void OBSBasicSettings::LoadAdvOutputStreamingSettings()
{
bool simulcast = config_get_bool(main->Config(), "AdvOut", "Simulcast");
bool rescale = config_get_bool(main->Config(), "AdvOut", "Rescale");
const char *rescaleRes =
config_get_string(main->Config(), "AdvOut", "RescaleRes");
int trackIndex = config_get_int(main->Config(), "AdvOut", "TrackIndex");

ui->advOutUseSimulcast->setChecked(simulcast);
ui->advOutUseRescale->setChecked(rescale);
ui->advOutRescale->setEnabled(rescale);
ui->advOutRescale->setCurrentText(rescaleRes);
Expand Down Expand Up @@ -3845,6 +3860,7 @@ void OBSBasicSettings::SaveOutputSettings()
SaveCheckBox(ui->simpleOutAdvanced, "SimpleOutput", "UseAdvanced");
SaveComboData(ui->simpleOutPreset, "SimpleOutput", presetType);
SaveEdit(ui->simpleOutCustom, "SimpleOutput", "x264Settings");
SaveCheckBox(ui->simpleOutSimulcast, "SimpleOutput", "UseSimulcast");
SaveComboData(ui->simpleOutRecQuality, "SimpleOutput", "RecQuality");
SaveComboData(ui->simpleOutRecEncoder, "SimpleOutput", "RecEncoder");
SaveComboData(ui->simpleOutRecAEncoder, "SimpleOutput",
Expand All @@ -3860,6 +3876,7 @@ void OBSBasicSettings::SaveOutputSettings()

SaveComboData(ui->advOutEncoder, "AdvOut", "Encoder");
SaveComboData(ui->advOutAEncoder, "AdvOut", "AudioEncoder");
SaveCheckBox(ui->advOutUseSimulcast, "AdvOut", "Simulcast");
SaveCheckBox(ui->advOutUseRescale, "AdvOut", "Rescale");
SaveCombo(ui->advOutRescale, "AdvOut", "RescaleRes");
SaveTrackIndex(main->Config(), "AdvOut", "TrackIndex", ui->advOutTrack1,
Expand Down Expand Up @@ -4373,6 +4390,7 @@ void OBSBasicSettings::on_advOutEncoder_currentIndexChanged()
ui->advOutEncoderLayout->addWidget(streamEncoderProps);
}

ui->advOutUseSimulcast->setVisible(true);
ui->advOutUseRescale->setVisible(true);
ui->advOutRescale->setVisible(true);
}
Expand Down
Loading

0 comments on commit 5f24f56

Please sign in to comment.