From 3491487c71cb5e53365bd03ff7cb691e23268382 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Thu, 13 Jul 2017 03:57:42 -0700 Subject: [PATCH] UI: Allow services to use different outputs Allows a service to specify the output it needs in order to function as configured. NOTE: This functionality should be considered temporary as a seamless means of implementing support for different output types within the same service. Ideally, different services should be used for this functionality. --- UI/window-basic-auto-config-test.cpp | 21 ++-- UI/window-basic-main-outputs.cpp | 140 +++++++++++++++++---------- UI/window-basic-main-outputs.hpp | 4 + 3 files changed, 106 insertions(+), 59 deletions(-) diff --git a/UI/window-basic-auto-config-test.cpp b/UI/window-basic-auto-config-test.cpp index 04b44e1dc..00491aff1 100644 --- a/UI/window-basic-auto-config-test.cpp +++ b/UI/window-basic-auto-config-test.cpp @@ -157,6 +157,8 @@ static inline void string_depad_key(string &key) } } +const char *FindAudioEncoderFromCodec(const char *type); + void AutoConfigTestPage::TestBandwidthThread() { bool connected = false; @@ -189,9 +191,6 @@ void AutoConfigTestPage::TestBandwidthThread() "test_aac", nullptr, 0, nullptr); OBSService service = obs_service_create(serverType, "test_service", nullptr, nullptr); - OBSOutput output = obs_output_create("rtmp_output", - "test_stream", nullptr, nullptr); - obs_output_release(output); obs_encoder_release(vencoder); obs_encoder_release(aencoder); obs_service_release(service); @@ -251,19 +250,29 @@ void AutoConfigTestPage::TestBandwidthThread() servers.resize(1); /* -----------------------------------*/ - /* apply settings */ + /* apply service settings */ obs_service_update(service, service_settings); obs_service_apply_encoder_settings(service, vencoder_settings, aencoder_settings); - obs_encoder_update(vencoder, vencoder_settings); - obs_encoder_update(aencoder, aencoder_settings); + /* -----------------------------------*/ + /* create output */ + + const char *output_type = obs_service_get_output_type(service); + if (!output_type) + output_type = "rtmp_output"; + + OBSOutput output = obs_output_create(output_type, + "test_stream", nullptr, nullptr); + obs_output_release(output); obs_output_update(output, output_settings); /* -----------------------------------*/ /* connect encoders/services/outputs */ + obs_encoder_update(vencoder, vencoder_settings); + obs_encoder_update(aencoder, aencoder_settings); obs_encoder_set_video(vencoder, obs_get_video()); obs_encoder_set_audio(aencoder, obs_get_audio()); diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 1dcd87389..df9afb149 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -313,12 +313,6 @@ void SimpleOutput::LoadRecordingPreset() SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_) { - streamOutput = obs_output_create("rtmp_output", "simple_stream", - nullptr, nullptr); - if (!streamOutput) - throw "Failed to create stream output (simple output)"; - obs_output_release(streamOutput); - const char *encoder = config_get_string(main->Config(), "SimpleOutput", "StreamEncoder"); if (strcmp(encoder, SIMPLE_ENCODER_QSV) == 0) @@ -334,16 +328,6 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_) "simple_aac", 0)) throw "Failed to create aac streaming encoder (simple output)"; - 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); - LoadRecordingPreset(); if (!ffmpegOutput) { @@ -650,15 +634,63 @@ inline void SimpleOutput::SetupOutputs() } } +const char *FindAudioEncoderFromCodec(const char *type) +{ + const char *alt_enc_id = nullptr; + size_t i = 0; + + while (obs_enum_encoder_types(i++, &alt_enc_id)) { + const char *codec = obs_get_encoder_codec(alt_enc_id); + if (strcmp(type, codec) == 0) { + return alt_enc_id; + } + } + + return nullptr; +} + bool SimpleOutput::StartStreaming(obs_service_t *service) { if (!Active()) SetupOutputs(); + /* --------------------- */ + + const char *type = obs_service_get_output_type(service); + if (!type) + type = "rtmp_output"; + + /* XXX: this is messy and disgusting and should be refactored */ + if (outputType != type) { + streamOutput = obs_output_create(type, "simple_stream", + nullptr, nullptr); + if (!streamOutput) + return false; + obs_output_release(streamOutput); + + 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, h264Streaming); obs_output_set_audio_encoder(streamOutput, aacStreaming, 0); obs_output_set_service(streamOutput, service); + /* --------------------- */ + bool reconnect = config_get_bool(main->Config(), "Output", "Reconnect"); int retryDelay = config_get_uint(main->Config(), "Output", @@ -986,12 +1018,6 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_) OBSData streamEncSettings = GetDataFromJsonFile("streamEncoder.json"); OBSData recordEncSettings = GetDataFromJsonFile("recordEncoder.json"); - streamOutput = obs_output_create("rtmp_output", "adv_stream", - nullptr, nullptr); - if (!streamOutput) - throw "Failed to create stream output (advanced output)"; - obs_output_release(streamOutput); - if (ffmpegOutput) { fileOutput = obs_output_create("ffmpeg_output", "adv_ffmpeg_output", nullptr, nullptr); @@ -1035,16 +1061,6 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_) "(advanced output)"; } - 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); - startRecording.Connect(obs_output_get_signal_handler(fileOutput), "start", OBSStartRecording, this); stopRecording.Connect(obs_output_get_signal_handler(fileOutput), @@ -1094,12 +1110,6 @@ inline void AdvancedOutput::SetupStreaming() "Rescale"); const char *rescaleRes = config_get_string(main->Config(), "AdvOut", "RescaleRes"); - bool multitrack = config_get_bool(main->Config(), "AdvOut", - "Multitrack"); - int trackIndex = config_get_int(main->Config(), "AdvOut", - "TrackIndex"); - int trackCount = config_get_int(main->Config(), "AdvOut", - "TrackCount"); unsigned int cx = 0; unsigned int cy = 0; @@ -1112,21 +1122,6 @@ inline void AdvancedOutput::SetupStreaming() obs_encoder_set_scaled_size(h264Streaming, cx, cy); obs_encoder_set_video(h264Streaming, obs_get_video()); - - obs_output_set_video_encoder(streamOutput, h264Streaming); - - if (multitrack) { - int i = 0; - for (; i < trackCount; i++) - obs_output_set_audio_encoder(streamOutput, aacTrack[i], - i); - for (; i < MAX_AUDIO_MIXES; i++) - obs_output_set_audio_encoder(streamOutput, nullptr, i); - - } else { - obs_output_set_audio_encoder(streamOutput, - aacTrack[trackIndex - 1], 0); - } } inline void AdvancedOutput::SetupRecording() @@ -1320,6 +1315,45 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service) if (!Active()) SetupOutputs(); + /* --------------------- */ + + int trackIndex = config_get_int(main->Config(), "AdvOut", + "TrackIndex"); + + const char *type = obs_service_get_output_type(service); + if (!type) + type = "rtmp_output"; + + /* XXX: this is messy and disgusting and should be refactored */ + if (outputType != type) { + streamOutput = obs_output_create(type, "adv_stream", + nullptr, nullptr); + if (!streamOutput) + return false; + obs_output_release(streamOutput); + + 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, h264Streaming); + obs_output_set_audio_encoder(streamOutput, aacTrack[trackIndex - 1], 0); + + /* --------------------- */ + obs_output_set_service(streamOutput, service); bool reconnect = config_get_bool(main->Config(), "Output", "Reconnect"); diff --git a/UI/window-basic-main-outputs.hpp b/UI/window-basic-main-outputs.hpp index ec814a782..4c4842d22 100644 --- a/UI/window-basic-main-outputs.hpp +++ b/UI/window-basic-main-outputs.hpp @@ -1,5 +1,7 @@ #pragma once +#include + class OBSBasic; struct BasicOutputHandler { @@ -12,6 +14,8 @@ struct BasicOutputHandler { bool replayBufferActive = false; OBSBasic *main; + std::string outputType; + OBSSignal startRecording; OBSSignal stopRecording; OBSSignal startReplayBuffer;