diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 3473ac2fd..4ba3b9963 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -1137,65 +1137,56 @@ FutureHolder SimpleOutput::SetupStreaming(obs_service_t *service) auto vod_track_mixer = IsVodTrackEnabled(service) ? std::optional{1} : std::nullopt; + auto handle_multitrack_video_result = [&](std::optional + multitrackVideoResult) { + if (multitrackVideoResult.has_value()) + return multitrackVideoResult.value(); + + /* XXX: this is messy and disgusting and should be refactored */ + if (outputType != type) { + streamDelayStarting.Disconnect(); + streamStopping.Disconnect(); + startStreaming.Disconnect(); + stopStreaming.Disconnect(); + + streamOutput = obs_output_create(type, "simple_stream", + nullptr, nullptr); + if (!streamOutput) { + blog(LOG_WARNING, + "Creation of stream output type '%s' " + "failed!", + type); + return false; + } + + streamDelayStarting.Connect( + obs_output_get_signal_handler(streamOutput), + "starting", OBSStreamStarting, this); + streamStopping.Connect( + obs_output_get_signal_handler(streamOutput), + "stopping", OBSStreamStopping, this); + + startStreaming.Connect( + obs_output_get_signal_handler(streamOutput), + "start", OBSStartStreaming, this); + stopStreaming.Connect( + obs_output_get_signal_handler(streamOutput), + "stop", OBSStopStreaming, this); + + outputType = type; + } + + obs_output_set_video_encoder(streamOutput, videoStreaming); + obs_output_set_audio_encoder(streamOutput, audioStreaming, 0); + obs_output_set_service(streamOutput, service); + return true; + }; + auto holder = SetupMultitrackVideo( service, GetSimpleAACEncoderForBitrate(audio_bitrate), 0, vod_track_mixer); - auto future = - PreventFutureDeadlock(holder.future) - .then(main, [&](std::optional - multitrackVideoResult) { - if (multitrackVideoResult.has_value()) - return multitrackVideoResult.value(); - - /* XXX: this is messy and disgusting and should be refactored */ - if (outputType != type) { - streamDelayStarting.Disconnect(); - streamStopping.Disconnect(); - startStreaming.Disconnect(); - stopStreaming.Disconnect(); - - streamOutput = obs_output_create( - type, "simple_stream", nullptr, - nullptr); - if (!streamOutput) { - blog(LOG_WARNING, - "Creation of stream output type '%s' " - "failed!", - type); - return false; - } - - streamDelayStarting.Connect( - obs_output_get_signal_handler( - streamOutput), - "starting", OBSStreamStarting, - this); - streamStopping.Connect( - obs_output_get_signal_handler( - streamOutput), - "stopping", OBSStreamStopping, - this); - - startStreaming.Connect( - obs_output_get_signal_handler( - streamOutput), - "start", OBSStartStreaming, - this); - stopStreaming.Connect( - obs_output_get_signal_handler( - streamOutput), - "stop", OBSStopStreaming, this); - - outputType = type; - } - - obs_output_set_video_encoder(streamOutput, - videoStreaming); - obs_output_set_audio_encoder(streamOutput, - audioStreaming, 0); - obs_output_set_service(streamOutput, service); - return true; - }); + auto future = PreventFutureDeadlock(holder.future) + .then(main, handle_multitrack_video_result); return {holder.cancelAll, future}; } @@ -2289,84 +2280,71 @@ FutureHolder AdvancedOutput::SetupStreaming(obs_service_t *service) int streamTrackIndex = config_get_int(main->Config(), "AdvOut", "TrackIndex") - 1; + auto handle_multitrack_video_result = [&](std::optional + multitrackVideoResult) { + if (multitrackVideoResult.has_value()) + return multitrackVideoResult.value(); + + /* XXX: this is messy and disgusting and should be refactored */ + if (outputType != type) { + streamDelayStarting.Disconnect(); + streamStopping.Disconnect(); + startStreaming.Disconnect(); + stopStreaming.Disconnect(); + + streamOutput = obs_output_create(type, "adv_stream", + nullptr, nullptr); + if (!streamOutput) { + blog(LOG_WARNING, + "Creation of stream output type '%s' " + "failed!", + type); + return false; + } + + streamDelayStarting.Connect( + obs_output_get_signal_handler(streamOutput), + "starting", OBSStreamStarting, this); + streamStopping.Connect( + obs_output_get_signal_handler(streamOutput), + "stopping", OBSStreamStopping, this); + + startStreaming.Connect( + obs_output_get_signal_handler(streamOutput), + "start", OBSStartStreaming, this); + stopStreaming.Connect( + obs_output_get_signal_handler(streamOutput), + "stop", OBSStopStreaming, this); + + outputType = type; + } + + obs_output_set_video_encoder(streamOutput, videoStreaming); + obs_output_set_audio_encoder(streamOutput, streamAudioEnc, 0); + + if (!is_multitrack_output) { + obs_output_set_audio_encoder(streamOutput, + streamAudioEnc, 0); + } else { + for (int i = 0; i < MAX_AUDIO_MIXES; i++) { + if ((multiTrackAudioMixes & (1 << i)) != 0) { + obs_output_set_audio_encoder( + streamOutput, streamTrack[i], + idx); + idx++; + } + } + } + + return true; + }; + auto holder = SetupMultitrackVideo(service, audio_encoder_id, static_cast(streamTrackIndex), VodTrackMixerIdx(service)); - auto future = - PreventFutureDeadlock(holder.future) - .then(main, [&](std::optional - multitrackVideoResult) { - if (multitrackVideoResult.has_value()) - return multitrackVideoResult.value(); - - /* XXX: this is messy and disgusting and should be refactored */ - if (outputType != type) { - streamDelayStarting.Disconnect(); - streamStopping.Disconnect(); - startStreaming.Disconnect(); - stopStreaming.Disconnect(); - - streamOutput = obs_output_create( - type, "adv_stream", nullptr, - nullptr); - if (!streamOutput) { - blog(LOG_WARNING, - "Creation of stream output type '%s' " - "failed!", - type); - return false; - } - - streamDelayStarting.Connect( - obs_output_get_signal_handler( - streamOutput), - "starting", OBSStreamStarting, - this); - streamStopping.Connect( - obs_output_get_signal_handler( - streamOutput), - "stopping", OBSStreamStopping, - this); - - startStreaming.Connect( - obs_output_get_signal_handler( - streamOutput), - "start", OBSStartStreaming, - this); - stopStreaming.Connect( - obs_output_get_signal_handler( - streamOutput), - "stop", OBSStopStreaming, this); - - outputType = type; - } - - obs_output_set_video_encoder(streamOutput, - videoStreaming); - obs_output_set_audio_encoder(streamOutput, - streamAudioEnc, 0); - - if (!is_multitrack_output) { - obs_output_set_audio_encoder( - streamOutput, streamAudioEnc, - 0); - } else { - for (int i = 0; i < MAX_AUDIO_MIXES; - i++) { - if ((multiTrackAudioMixes & - (1 << i)) != 0) { - obs_output_set_audio_encoder( - streamOutput, - streamTrack[i], - idx); - idx++; - } - } - } - - return true; - }); + auto future = PreventFutureDeadlock(holder.future) + .then(main, handle_multitrack_video_result); return {holder.cancelAll, future}; } @@ -2773,6 +2751,44 @@ FutureHolder> BasicOutputHandler::SetupMultitrackVideo( auto stream_dump_config = GenerateMultitrackVideoStreamDumpConfig(); + auto continue_on_main_thread = + [&, service = OBSService{service}]( + std::optional error) + -> std::optional { + if (error) { + OBSDataAutoRelease service_settings = + obs_service_get_settings(service); + auto multitrack_video_name = QTStr( + "Basic.Settings.Stream.MultitrackVideoLabel"); + if (obs_data_has_user_value(service_settings, + "multitrack_video_name")) { + multitrack_video_name = obs_data_get_string( + service_settings, + "multitrack_video_name"); + } + + multitrackVideoActive = false; + if (!error->ShowDialog(main, multitrack_video_name)) + return false; + return std::nullopt; + } + + multitrackVideoActive = true; + + auto signal_handler = multitrackVideo->StreamingSignalHandler(); + + streamDelayStarting.Connect(signal_handler, "starting", + OBSStreamStarting, this); + streamStopping.Connect(signal_handler, "stopping", + OBSStreamStopping, this); + + startStreaming.Connect(signal_handler, "start", + OBSStartStreaming, this); + stopStreaming.Connect(signal_handler, "stop", OBSStopStreaming, + this); + return true; + }; + auto firstFuture = CreateFuture().then( QThreadPool::globalInstance(), [=, multitrackVideo = multitrackVideo.get(), @@ -2795,48 +2811,7 @@ FutureHolder> BasicOutputHandler::SetupMultitrackVideo( return std::nullopt; }); - auto secondFuture = firstFuture.then( - main, - [&, service = OBSService{service}]( - std::optional error) - -> std::optional { - if (error) { - OBSDataAutoRelease service_settings = - obs_service_get_settings(service); - auto multitrack_video_name = QTStr( - "Basic.Settings.Stream.MultitrackVideoLabel"); - if (obs_data_has_user_value( - service_settings, - "multitrack_video_name")) { - multitrack_video_name = - obs_data_get_string( - service_settings, - "multitrack_video_name"); - } - - multitrackVideoActive = false; - if (!error->ShowDialog(main, - multitrack_video_name)) - return false; - return std::nullopt; - } - - multitrackVideoActive = true; - - auto signal_handler = - multitrackVideo->StreamingSignalHandler(); - - streamDelayStarting.Connect(signal_handler, "starting", - OBSStreamStarting, this); - streamStopping.Connect(signal_handler, "stopping", - OBSStreamStopping, this); - - startStreaming.Connect(signal_handler, "start", - OBSStartStreaming, this); - stopStreaming.Connect(signal_handler, "stop", - OBSStopStreaming, this); - return true; - }); + auto secondFuture = firstFuture.then(main, continue_on_main_thread); return {[=]() mutable { firstFuture.cancel(); }, PreventFutureDeadlock(secondFuture)}; diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 8f5fc43c1..36015b613 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -7109,8 +7109,7 @@ void OBSBasic::StartStreaming() sysTrayStream->setText("Basic.Main.PreparingStream"); } - auto holder = outputHandler->SetupStreaming(service); - auto future = holder.future.then(this, [&](bool setupStreamingResult) { + auto finish_stream_setup = [&](bool setupStreamingResult) { if (!setupStreamingResult) { DisplayStreamStartError(); return; @@ -7152,7 +7151,10 @@ void OBSBasic::StartStreaming() if (!autoStartBroadcast) OBSBasic::ShowYouTubeAutoStartWarning(); #endif - }); + }; + + auto holder = outputHandler->SetupStreaming(service); + auto future = holder.future.then(this, finish_stream_setup); startStreamingFuture = {holder.cancelAll, future}; }