|
@@ -1137,65 +1137,56 @@ FutureHolder<bool> SimpleOutput::SetupStreaming(obs_service_t *service)
|
|
|
auto vod_track_mixer = IsVodTrackEnabled(service) ? std::optional{1}
|
|
|
: std::nullopt;
|
|
|
|
|
|
+ auto handle_multitrack_video_result = [&](std::optional<bool>
|
|
|
+ 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<bool>
|
|
|
- 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<bool> AdvancedOutput::SetupStreaming(obs_service_t *service)
|
|
|
int streamTrackIndex =
|
|
|
config_get_int(main->Config(), "AdvOut", "TrackIndex") - 1;
|
|
|
|
|
|
- auto holder =
|
|
|
- SetupMultitrackVideo(service, audio_encoder_id,
|
|
|
- static_cast<size_t>(streamTrackIndex),
|
|
|
- VodTrackMixerIdx(service));
|
|
|
- auto future =
|
|
|
- PreventFutureDeadlock(holder.future)
|
|
|
- .then(main, [&](std::optional<bool>
|
|
|
- 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;
|
|
|
- }
|
|
|
+ auto handle_multitrack_video_result = [&](std::optional<bool>
|
|
|
+ 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;
|
|
|
- }
|
|
|
+ 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);
|
|
|
+ obs_output_set_video_encoder(streamOutput, videoStreaming);
|
|
|
+ obs_output_set_audio_encoder(streamOutput, streamAudioEnc, 0);
|
|
|
|
|
|
- if (!is_multitrack_output) {
|
|
|
+ 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, 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++;
|
|
|
- }
|
|
|
- }
|
|
|
+ streamOutput, streamTrack[i],
|
|
|
+ idx);
|
|
|
+ idx++;
|
|
|
}
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ };
|
|
|
|
|
|
- return true;
|
|
|
- });
|
|
|
+ auto holder =
|
|
|
+ SetupMultitrackVideo(service, audio_encoder_id,
|
|
|
+ static_cast<size_t>(streamTrackIndex),
|
|
|
+ VodTrackMixerIdx(service));
|
|
|
+ auto future = PreventFutureDeadlock(holder.future)
|
|
|
+ .then(main, handle_multitrack_video_result);
|
|
|
return {holder.cancelAll, future};
|
|
|
}
|
|
|
|
|
@@ -2773,6 +2751,44 @@ FutureHolder<std::optional<bool>> BasicOutputHandler::SetupMultitrackVideo(
|
|
|
|
|
|
auto stream_dump_config = GenerateMultitrackVideoStreamDumpConfig();
|
|
|
|
|
|
+ auto continue_on_main_thread =
|
|
|
+ [&, service = OBSService{service}](
|
|
|
+ std::optional<MultitrackVideoError> error)
|
|
|
+ -> std::optional<bool> {
|
|
|
+ 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<std::optional<bool>> BasicOutputHandler::SetupMultitrackVideo(
|
|
|
return std::nullopt;
|
|
|
});
|
|
|
|
|
|
- auto secondFuture = firstFuture.then(
|
|
|
- main,
|
|
|
- [&, service = OBSService{service}](
|
|
|
- std::optional<MultitrackVideoError> error)
|
|
|
- -> std::optional<bool> {
|
|
|
- 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)};
|