From f41bc2c32bd513e764ec564f228c361d430ffaf4 Mon Sep 17 00:00:00 2001 From: Matthew Orlando Date: Wed, 26 Sep 2018 11:39:34 -0700 Subject: [PATCH 1/3] UI: Fix unencoded stream failure A stream will fail to start if the output_info does not have an encoded_audio_codecs string, even if the output is not flagged as encoded. This allows unencoded outputs to omit that string. --- UI/window-basic-main-outputs.cpp | 99 ++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 29f27a39c..70d807e71 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -685,28 +685,39 @@ bool SimpleOutput::StartStreaming(obs_service_t *service) obs_output_get_signal_handler(streamOutput), "stop", OBSStopStreaming, this); - const char *codec = - obs_output_get_supported_audio_codecs(streamOutput); - if (!codec) { - return false; - } + bool isEncoded = obs_output_get_flags(streamOutput) + & OBS_OUTPUT_ENCODED; - if (strcmp(codec, "aac") != 0) { - const char *id = FindAudioEncoderFromCodec(codec); - int audioBitrate = GetAudioBitrate(); - obs_data_t *settings = obs_data_create(); - obs_data_set_int(settings, "bitrate", audioBitrate); - - aacStreaming = obs_audio_encoder_create(id, - "alt_audio_enc", nullptr, 0, nullptr); - obs_encoder_release(aacStreaming); - if (!aacStreaming) + if (isEncoded) { + const char *codec = + obs_output_get_supported_audio_codecs( + streamOutput); + if (!codec) { + blog(LOG_WARNING, "Failed to load audio codec"); return false; + } - obs_encoder_update(aacStreaming, settings); - obs_encoder_set_audio(aacStreaming, obs_get_audio()); + if (strcmp(codec, "aac") != 0) { + const char *id = FindAudioEncoderFromCodec( + codec); + int audioBitrate = GetAudioBitrate(); + obs_data_t *settings = obs_data_create(); + obs_data_set_int(settings, "bitrate", + audioBitrate); - obs_data_release(settings); + aacStreaming = obs_audio_encoder_create(id, + "alt_audio_enc", nullptr, 0, + nullptr); + obs_encoder_release(aacStreaming); + if (!aacStreaming) + return false; + + obs_encoder_update(aacStreaming, settings); + obs_encoder_set_audio(aacStreaming, + obs_get_audio()); + + obs_data_release(settings); + } } outputType = type; @@ -1463,30 +1474,42 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service) obs_output_get_signal_handler(streamOutput), "stop", OBSStopStreaming, this); - const char *codec = - obs_output_get_supported_audio_codecs(streamOutput); - if (!codec) { - return false; - } + bool isEncoded = obs_output_get_flags(streamOutput) + & OBS_OUTPUT_ENCODED; - if (strcmp(codec, "aac") == 0) { - streamAudioEnc = aacTrack[trackIndex - 1]; - } else { - const char *id = FindAudioEncoderFromCodec(codec); - int audioBitrate = GetAudioBitrate(trackIndex - 1); - obs_data_t *settings = obs_data_create(); - obs_data_set_int(settings, "bitrate", audioBitrate); - - streamAudioEnc = obs_audio_encoder_create(id, - "alt_audio_enc", nullptr, - trackIndex - 1, nullptr); - if (!streamAudioEnc) + if (isEncoded) { + const char *codec = + obs_output_get_supported_audio_codecs( + streamOutput); + if (!codec) { + blog(LOG_WARNING, "Failed to load audio codec"); return false; + } - obs_encoder_update(streamAudioEnc, settings); - obs_encoder_set_audio(streamAudioEnc, obs_get_audio()); + if (strcmp(codec, "aac") == 0) { + streamAudioEnc = aacTrack[trackIndex - 1]; + } else { + obs_data_t *settings = obs_data_create(); + const char *id = + FindAudioEncoderFromCodec(codec); + int audioBitrate = + GetAudioBitrate(trackIndex - 1); + + obs_data_set_int(settings, "bitrate", + audioBitrate); + streamAudioEnc = obs_audio_encoder_create(id, + "alt_audio_enc", nullptr, + trackIndex - 1, nullptr); - obs_data_release(settings); + if (!streamAudioEnc) + return false; + + obs_encoder_update(streamAudioEnc, settings); + obs_encoder_set_audio(streamAudioEnc, + obs_get_audio()); + + obs_data_release(settings); + } } outputType = type; From 09d77878fd0bdfda215b757c55c98cf7b52377b2 Mon Sep 17 00:00:00 2001 From: Matthew Orlando Date: Wed, 10 Oct 2018 18:11:37 -0700 Subject: [PATCH 2/3] libobs: Initialize service before starting output This fixes the case where initialize is not called on a service if the output is not encoded. --- libobs/obs-output.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libobs/obs-output.c b/libobs/obs-output.c index e8cda627a..40aa12dcc 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -255,13 +255,17 @@ bool obs_output_actual_start(obs_output_t *output) bool obs_output_start(obs_output_t *output) { bool encoded; + bool has_service; if (!obs_output_valid(output, "obs_output_start")) return false; if (!output->context.data) return false; - encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0; + has_service = (output->info.flags & OBS_OUTPUT_SERVICE) != 0; + if (has_service && !obs_service_initialize(output->service, output)) + return false; + encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0; if (encoded && output->delay_sec) { return obs_output_delay_start(output); } else { @@ -1746,8 +1750,6 @@ bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags) if (!encoded) return false; - if (has_service && !obs_service_initialize(output->service, output)) - return false; if (has_video && !obs_encoder_initialize(output->video_encoder)) return false; if (has_audio && !initialize_audio_encoders(output, num_mixes)) From 54e7267ad91a470e5741fb0d8bdc49b8e7a0ef46 Mon Sep 17 00:00:00 2001 From: Matthew Orlando Date: Wed, 12 Dec 2018 15:20:48 -0800 Subject: [PATCH 3/3] UI: Show output's last error in failure dialog Logs the last output error if given. --- UI/window-basic-main-outputs.cpp | 26 ++++++++++++++++---------- UI/window-basic-main-outputs.hpp | 1 + UI/window-basic-main.cpp | 8 +++++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 70d807e71..3afda2025 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -771,12 +771,15 @@ bool SimpleOutput::StartStreaming(obs_service_t *service) } const char *error = obs_output_get_last_error(streamOutput); - bool has_last_error = error && *error; + bool hasLastError = error && *error; + if (hasLastError) + lastError = error; + else + lastError = string(); - blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", - type, - has_last_error ? " Last Error: " : "", - has_last_error ? error : ""); + blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type, + hasLastError ? " Last Error: " : "", + hasLastError ? error : ""); return false; } @@ -1561,12 +1564,15 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service) } const char *error = obs_output_get_last_error(streamOutput); - bool has_last_error = error && *error; + bool hasLastError = error && *error; + if (hasLastError) + lastError = error; + else + lastError = string(); - blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", - type, - has_last_error ? " Last Error: " : "", - has_last_error ? error : ""); + blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type, + hasLastError ? " Last Error: " : "", + hasLastError ? error : ""); return false; } diff --git a/UI/window-basic-main-outputs.hpp b/UI/window-basic-main-outputs.hpp index 4c4842d22..c053d0b08 100644 --- a/UI/window-basic-main-outputs.hpp +++ b/UI/window-basic-main-outputs.hpp @@ -15,6 +15,7 @@ struct BasicOutputHandler { OBSBasic *main; std::string outputType; + std::string lastError; OBSSignal startRecording; OBSSignal stopRecording; diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 2242e9d36..5b74857d0 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -4762,6 +4762,9 @@ void OBSBasic::StartStreaming() } if (!outputHandler->StartStreaming(service)) { + QString message = !outputHandler->lastError.empty() + ? QTStr(outputHandler->lastError.c_str()) + : QTStr("Output.StartFailedGeneric"); ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); ui->streamButton->setEnabled(true); ui->streamButton->setChecked(false); @@ -4771,9 +4774,8 @@ void OBSBasic::StartStreaming() sysTrayStream->setEnabled(true); } - QMessageBox::critical(this, - QTStr("Output.StartStreamFailed"), - QTStr("Output.StartFailedGeneric")); + QMessageBox::critical(this, QTStr("Output.StartStreamFailed"), + message); return; }