@@ -565,6 +565,10 @@ void SimpleOutput::LoadStreamingPreset_Lossy(const char *encoderId)
565565 if (!videoStreaming)
566566 throw " Failed to create video streaming encoder (simple output)" ;
567567 obs_encoder_release (videoStreaming);
568+
569+ if (config_get_bool (main->Config (), " Stream1" , " UseSimulcast" )) {
570+ CreateSimulcastEncoders (encoderId);
571+ }
568572}
569573
570574/* mistakes have been made to lead us to this. */
@@ -867,9 +871,14 @@ void SimpleOutput::Update()
867871 default :
868872 obs_encoder_set_preferred_video_format (videoStreaming,
869873 VIDEO_FORMAT_NV12);
874+ for (auto enc : simulcastEncoders)
875+ obs_encoder_set_preferred_video_format (
876+ enc, VIDEO_FORMAT_NV12);
870877 }
871878
872879 obs_encoder_update (videoStreaming, videoSettings);
880+ SimulcastEncodersUpdate (videoSettings, videoBitrate);
881+
873882 obs_encoder_update (audioStreaming, audioSettings);
874883 obs_encoder_update (audioArchive, audioSettings);
875884}
@@ -1189,8 +1198,13 @@ FutureHolder<bool> SimpleOutput::SetupStreaming(obs_service_t *service)
11891198 outputType = type;
11901199 }
11911200
1192- obs_output_set_video_encoder (streamOutput,
1193- videoStreaming);
1201+ obs_output_set_video_encoder2 (
1202+ streamOutput, videoStreaming, 0 );
1203+ for (size_t i = 0 ; i < simulcastEncoders.size ();
1204+ i++)
1205+ obs_output_set_video_encoder2 (
1206+ streamOutput,
1207+ simulcastEncoders[i], i + 1 );
11941208 obs_output_set_audio_encoder (streamOutput,
11951209 audioStreaming, 0 );
11961210 obs_output_set_service (streamOutput, service);
@@ -1729,6 +1743,10 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
17291743 " (advanced output)" ;
17301744 obs_encoder_release (videoStreaming);
17311745
1746+ if (config_get_bool (main->Config (), " Stream1" , " UseSimulcast" )) {
1747+ CreateSimulcastEncoders (streamEncoder);
1748+ }
1749+
17321750 const char *rate_control = obs_data_get_string (
17331751 useStreamEncoder ? streamEncSettings : recordEncSettings,
17341752 " rate_control" );
@@ -1849,6 +1867,8 @@ void AdvancedOutput::UpdateStreamSettings()
18491867 }
18501868
18511869 obs_encoder_update (videoStreaming, settings);
1870+ SimulcastEncodersUpdate (settings,
1871+ obs_data_get_int (settings, " bitrate" ));
18521872}
18531873
18541874inline void AdvancedOutput::UpdateRecordingSettings ()
@@ -2338,8 +2358,13 @@ FutureHolder<bool> AdvancedOutput::SetupStreaming(obs_service_t *service)
23382358 outputType = type;
23392359 }
23402360
2341- obs_output_set_video_encoder (streamOutput,
2342- videoStreaming);
2361+ obs_output_set_video_encoder2 (
2362+ streamOutput, videoStreaming, 0 );
2363+ for (size_t i = 0 ; i < simulcastEncoders.size ();
2364+ i++)
2365+ obs_output_set_video_encoder2 (
2366+ streamOutput,
2367+ simulcastEncoders[i], i + 1 );
23432368 obs_output_set_audio_encoder (streamOutput,
23442369 streamAudioEnc, 0 );
23452370
@@ -2886,3 +2911,52 @@ BasicOutputHandler *CreateAdvancedOutputHandler(OBSBasic *main)
28862911{
28872912 return new AdvancedOutput (main);
28882913}
2914+
2915+ void BasicOutputHandler::CreateSimulcastEncoders (const char *encoderId)
2916+ {
2917+ int rescaleFilter =
2918+ config_get_int (main->Config (), " AdvOut" , " RescaleFilter" );
2919+ if (rescaleFilter == OBS_SCALE_DISABLE) {
2920+ rescaleFilter = OBS_SCALE_BICUBIC;
2921+ }
2922+
2923+ std::string encoder_name = " simulcast_0" ;
2924+ for (auto i = 0 ; i < 2 ; i++) {
2925+ uint32_t width = video_output_get_width (obs_get_video ()) /
2926+ (1.5 + (.5 * i));
2927+ width -= width % 2 ;
2928+
2929+ uint32_t height = video_output_get_height (obs_get_video ()) /
2930+ (1.5 + (.5 * i));
2931+ height -= height % 2 ;
2932+
2933+ encoder_name[encoder_name.size () - 1 ] = to_string (i).at (0 );
2934+ auto simulcast_encoder = obs_video_encoder_create (
2935+ encoderId, encoder_name.c_str (), nullptr , nullptr );
2936+
2937+ if (simulcast_encoder) {
2938+ obs_encoder_set_video (simulcast_encoder,
2939+ obs_get_video ());
2940+ obs_encoder_set_scaled_size (simulcast_encoder, width,
2941+ height);
2942+ obs_encoder_set_gpu_scale_type (
2943+ simulcast_encoder,
2944+ (obs_scale_type)rescaleFilter);
2945+ simulcastEncoders.push_back (simulcast_encoder);
2946+ obs_encoder_release (simulcast_encoder);
2947+ } else {
2948+ blog (LOG_WARNING,
2949+ " Failed to create video streaming simulcast encoders (BasicOutputHandler)" );
2950+ }
2951+ }
2952+ }
2953+
2954+ void BasicOutputHandler::SimulcastEncodersUpdate (obs_data_t *videoSettings,
2955+ int videoBitrate)
2956+ {
2957+ for (size_t i = 0 ; i < simulcastEncoders.size (); i++) {
2958+ obs_data_set_int (videoSettings, " bitrate" ,
2959+ videoBitrate / (2 * (i + 1 )));
2960+ obs_encoder_update (simulcastEncoders[i], videoSettings);
2961+ }
2962+ }
0 commit comments