@@ -588,6 +588,10 @@ void SimpleOutput::LoadStreamingPreset_Lossy(const char *encoderId)
588588 if (!videoStreaming)
589589 throw " Failed to create video streaming encoder (simple output)" ;
590590 obs_encoder_release (videoStreaming);
591+
592+ if (config_get_bool (main->Config (), " Stream1" , " UseSimulcast" )) {
593+ CreateSimulcastEncoders (encoderId);
594+ }
591595}
592596
593597/* mistakes have been made to lead us to this. */
@@ -890,9 +894,14 @@ void SimpleOutput::Update()
890894 default :
891895 obs_encoder_set_preferred_video_format (videoStreaming,
892896 VIDEO_FORMAT_NV12);
897+ for (auto enc : simulcastEncoders)
898+ obs_encoder_set_preferred_video_format (
899+ enc, VIDEO_FORMAT_NV12);
893900 }
894901
895902 obs_encoder_update (videoStreaming, videoSettings);
903+ SimulcastEncodersUpdate (videoSettings, videoBitrate);
904+
896905 obs_encoder_update (audioStreaming, audioSettings);
897906 obs_encoder_update (audioArchive, audioSettings);
898907}
@@ -1204,6 +1213,9 @@ SimpleOutput::SetupStreaming(obs_service_t *service,
12041213 }
12051214
12061215 obs_output_set_video_encoder (streamOutput, videoStreaming);
1216+ for (size_t i = 0 ; i < simulcastEncoders.size (); i++)
1217+ obs_output_set_video_encoder2 (
1218+ streamOutput, simulcastEncoders[i], i + 1 );
12071219 obs_output_set_audio_encoder (streamOutput, audioStreaming, 0 );
12081220 obs_output_set_service (streamOutput, service);
12091221 return true ;
@@ -1747,6 +1759,10 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
17471759 " (advanced output)" ;
17481760 obs_encoder_release (videoStreaming);
17491761
1762+ if (config_get_bool (main->Config (), " Stream1" , " UseSimulcast" )) {
1763+ CreateSimulcastEncoders (streamEncoder);
1764+ }
1765+
17501766 const char *rate_control = obs_data_get_string (
17511767 useStreamEncoder ? streamEncSettings : recordEncSettings,
17521768 " rate_control" );
@@ -1867,6 +1883,8 @@ void AdvancedOutput::UpdateStreamSettings()
18671883 }
18681884
18691885 obs_encoder_update (videoStreaming, settings);
1886+ SimulcastEncodersUpdate (settings,
1887+ obs_data_get_int (settings, " bitrate" ));
18701888}
18711889
18721890inline void AdvancedOutput::UpdateRecordingSettings ()
@@ -2351,6 +2369,9 @@ AdvancedOutput::SetupStreaming(obs_service_t *service,
23512369 }
23522370
23532371 obs_output_set_video_encoder (streamOutput, videoStreaming);
2372+ for (size_t i = 0 ; i < simulcastEncoders.size (); i++)
2373+ obs_output_set_video_encoder2 (
2374+ streamOutput, simulcastEncoders[i], i + 1 );
23542375 obs_output_set_audio_encoder (streamOutput, streamAudioEnc, 0 );
23552376
23562377 if (!is_multitrack_output) {
@@ -2900,3 +2921,52 @@ BasicOutputHandler *CreateAdvancedOutputHandler(OBSBasic *main)
29002921{
29012922 return new AdvancedOutput (main);
29022923}
2924+
2925+ void BasicOutputHandler::CreateSimulcastEncoders (const char *encoderId)
2926+ {
2927+ int rescaleFilter =
2928+ config_get_int (main->Config (), " AdvOut" , " RescaleFilter" );
2929+ if (rescaleFilter == OBS_SCALE_DISABLE) {
2930+ rescaleFilter = OBS_SCALE_BICUBIC;
2931+ }
2932+
2933+ std::string encoder_name = " simulcast_0" ;
2934+ for (auto i = 0 ; i < 2 ; i++) {
2935+ uint32_t width = video_output_get_width (obs_get_video ()) /
2936+ (1.5 + (.5 * i));
2937+ width -= width % 2 ;
2938+
2939+ uint32_t height = video_output_get_height (obs_get_video ()) /
2940+ (1.5 + (.5 * i));
2941+ height -= height % 2 ;
2942+
2943+ encoder_name[encoder_name.size () - 1 ] = to_string (i).at (0 );
2944+ auto simulcast_encoder = obs_video_encoder_create (
2945+ encoderId, encoder_name.c_str (), nullptr , nullptr );
2946+
2947+ if (simulcast_encoder) {
2948+ obs_encoder_set_video (simulcast_encoder,
2949+ obs_get_video ());
2950+ obs_encoder_set_scaled_size (simulcast_encoder, width,
2951+ height);
2952+ obs_encoder_set_gpu_scale_type (
2953+ simulcast_encoder,
2954+ (obs_scale_type)rescaleFilter);
2955+ simulcastEncoders.push_back (simulcast_encoder);
2956+ obs_encoder_release (simulcast_encoder);
2957+ } else {
2958+ blog (LOG_WARNING,
2959+ " Failed to create video streaming simulcast encoders (BasicOutputHandler)" );
2960+ }
2961+ }
2962+ }
2963+
2964+ void BasicOutputHandler::SimulcastEncodersUpdate (obs_data_t *videoSettings,
2965+ int videoBitrate)
2966+ {
2967+ for (size_t i = 0 ; i < simulcastEncoders.size (); i++) {
2968+ obs_data_set_int (videoSettings, " bitrate" ,
2969+ videoBitrate / (2 * (i + 1 )));
2970+ obs_encoder_update (simulcastEncoders[i], videoSettings);
2971+ }
2972+ }
0 commit comments