|
@@ -36,6 +36,7 @@
|
|
|
#include "window-namedialog.hpp"
|
|
|
#include "window-basic-source-select.hpp"
|
|
|
#include "window-basic-main.hpp"
|
|
|
+#include "window-basic-main-outputs.hpp"
|
|
|
#include "window-basic-properties.hpp"
|
|
|
#include "window-log-reply.hpp"
|
|
|
#include "window-remux.hpp"
|
|
@@ -294,36 +295,6 @@ static inline bool HasAudioDevices(const char *source_id)
|
|
|
return count != 0;
|
|
|
}
|
|
|
|
|
|
-static void OBSStartStreaming(void *data, calldata_t *params)
|
|
|
-{
|
|
|
- UNUSED_PARAMETER(params);
|
|
|
- QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
- "StreamingStart");
|
|
|
-}
|
|
|
-
|
|
|
-static void OBSStopStreaming(void *data, calldata_t *params)
|
|
|
-{
|
|
|
- int code = (int)calldata_int(params, "code");
|
|
|
- QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
- "StreamingStop", Q_ARG(int, code));
|
|
|
-}
|
|
|
-
|
|
|
-static void OBSStartRecording(void *data, calldata_t *params)
|
|
|
-{
|
|
|
- UNUSED_PARAMETER(params);
|
|
|
-
|
|
|
- QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
- "RecordingStart");
|
|
|
-}
|
|
|
-
|
|
|
-static void OBSStopRecording(void *data, calldata_t *params)
|
|
|
-{
|
|
|
- UNUSED_PARAMETER(params);
|
|
|
-
|
|
|
- QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
|
|
|
- "RecordingStop");
|
|
|
-}
|
|
|
-
|
|
|
#define SERVICE_PATH "obs-studio/basic/service.json"
|
|
|
|
|
|
void OBSBasic::SaveService()
|
|
@@ -380,49 +351,6 @@ bool OBSBasic::LoadService()
|
|
|
return !!service;
|
|
|
}
|
|
|
|
|
|
-bool OBSBasic::InitOutputs()
|
|
|
-{
|
|
|
- fileOutput = obs_output_create("flv_output", "default_file_output",
|
|
|
- nullptr);
|
|
|
- if (!fileOutput)
|
|
|
- return false;
|
|
|
-
|
|
|
- streamOutput = obs_output_create("rtmp_output", "default_stream",
|
|
|
- nullptr);
|
|
|
- if (!streamOutput)
|
|
|
- return false;
|
|
|
-
|
|
|
- signal_handler_connect(obs_output_get_signal_handler(streamOutput),
|
|
|
- "start", OBSStartStreaming, this);
|
|
|
- signal_handler_connect(obs_output_get_signal_handler(streamOutput),
|
|
|
- "stop", OBSStopStreaming, this);
|
|
|
-
|
|
|
- signal_handler_connect(obs_output_get_signal_handler(fileOutput),
|
|
|
- "start", OBSStartRecording, this);
|
|
|
- signal_handler_connect(obs_output_get_signal_handler(fileOutput),
|
|
|
- "stop", OBSStopRecording, this);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-bool OBSBasic::InitEncoders()
|
|
|
-{
|
|
|
- x264 = obs_video_encoder_create("obs_x264", "default_h264", nullptr);
|
|
|
- if (!x264)
|
|
|
- return false;
|
|
|
-
|
|
|
- aac = obs_audio_encoder_create("libfdk_aac", "default_aac", nullptr, 0);
|
|
|
-
|
|
|
- if (!aac)
|
|
|
- aac = obs_audio_encoder_create("ffmpeg_aac", "default_aac",
|
|
|
- nullptr, 0);
|
|
|
-
|
|
|
- if (!aac)
|
|
|
- return false;
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
bool OBSBasic::InitService()
|
|
|
{
|
|
|
if (LoadService())
|
|
@@ -458,6 +386,8 @@ bool OBSBasic::InitBasicConfigDefaults()
|
|
|
uint32_t cy = monitors[0].cy;
|
|
|
|
|
|
/* TODO: temporary */
|
|
|
+ config_set_default_string(basicConfig, "Output", "Type", "Simple");
|
|
|
+
|
|
|
config_set_default_string(basicConfig, "SimpleOutput", "FilePath",
|
|
|
GetDefaultVideoSavePath().c_str());
|
|
|
config_set_default_uint (basicConfig, "SimpleOutput", "VBitrate",
|
|
@@ -569,6 +499,16 @@ void OBSBasic::InitPrimitives()
|
|
|
obs_leave_graphics();
|
|
|
}
|
|
|
|
|
|
+void OBSBasic::ResetOutputs()
|
|
|
+{
|
|
|
+ if (!outputHandler || !outputHandler->Active()) {
|
|
|
+ outputHandler.reset();
|
|
|
+ outputHandler.reset(CreateSimpleOutputHandler(this));
|
|
|
+ } else {
|
|
|
+ outputHandler->Update();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void OBSBasic::OBSInit()
|
|
|
{
|
|
|
char savePath[512];
|
|
@@ -609,10 +549,8 @@ void OBSBasic::OBSInit()
|
|
|
AddExtraModulePaths();
|
|
|
obs_load_all_modules();
|
|
|
|
|
|
- if (!InitOutputs())
|
|
|
- throw "Failed to initialize outputs";
|
|
|
- if (!InitEncoders())
|
|
|
- throw "Failed to initialize encoders";
|
|
|
+ ResetOutputs();
|
|
|
+
|
|
|
if (!InitService())
|
|
|
throw "Failed to initialize service";
|
|
|
|
|
@@ -642,6 +580,8 @@ OBSBasic::~OBSBasic()
|
|
|
delete cpuUsageTimer;
|
|
|
os_cpu_usage_info_destroy(cpuUsageInfo);
|
|
|
|
|
|
+ outputHandler.reset();
|
|
|
+
|
|
|
if (interaction)
|
|
|
delete interaction;
|
|
|
|
|
@@ -2181,7 +2121,7 @@ void OBSBasic::StreamingStart()
|
|
|
{
|
|
|
ui->streamButton->setText(QTStr("Basic.Main.StopStreaming"));
|
|
|
ui->streamButton->setEnabled(true);
|
|
|
- ui->statusbar->StreamStarted(streamOutput);
|
|
|
+ ui->statusbar->StreamStarted(outputHandler->streamOutput);
|
|
|
}
|
|
|
|
|
|
void OBSBasic::StreamingStop(int code)
|
|
@@ -2212,7 +2152,6 @@ void OBSBasic::StreamingStop(int code)
|
|
|
errorMessage = Str("Output.ConnectFail.Disconnected");
|
|
|
}
|
|
|
|
|
|
- activeRefs--;
|
|
|
ui->statusbar->StreamStopped();
|
|
|
|
|
|
ui->streamButton->setText(QTStr("Basic.Main.StartStreaming"));
|
|
@@ -2226,89 +2165,25 @@ void OBSBasic::StreamingStop(int code)
|
|
|
|
|
|
void OBSBasic::RecordingStart()
|
|
|
{
|
|
|
- ui->statusbar->RecordingStarted(fileOutput);
|
|
|
+ ui->statusbar->RecordingStarted(outputHandler->fileOutput);
|
|
|
}
|
|
|
|
|
|
void OBSBasic::RecordingStop()
|
|
|
{
|
|
|
ui->statusbar->RecordingStopped();
|
|
|
- activeRefs--;
|
|
|
ui->recordButton->setText(QTStr("Basic.Main.StartRecording"));
|
|
|
}
|
|
|
|
|
|
-void OBSBasic::SetupEncoders()
|
|
|
-{
|
|
|
- if (activeRefs == 0) {
|
|
|
- obs_data_t *x264Settings = obs_data_create();
|
|
|
- obs_data_t *aacSettings = obs_data_create();
|
|
|
-
|
|
|
- int videoBitrate = config_get_uint(basicConfig, "SimpleOutput",
|
|
|
- "VBitrate");
|
|
|
- int audioBitrate = config_get_uint(basicConfig, "SimpleOutput",
|
|
|
- "ABitrate");
|
|
|
- bool advanced = config_get_bool(basicConfig, "SimpleOutput",
|
|
|
- "UseAdvanced");
|
|
|
- bool useCBR = config_get_bool(basicConfig, "SimpleOutput",
|
|
|
- "UseCBR");
|
|
|
- const char *preset = config_get_string(basicConfig,
|
|
|
- "SimpleOutput", "Preset");
|
|
|
- const char *custom = config_get_string(basicConfig,
|
|
|
- "SimpleOutput", "x264Settings");
|
|
|
-
|
|
|
- obs_data_set_int(x264Settings, "bitrate", videoBitrate);
|
|
|
- obs_data_set_int(x264Settings, "buffer_size", videoBitrate);
|
|
|
-
|
|
|
- if (advanced) {
|
|
|
- obs_data_set_string(x264Settings, "preset", preset);
|
|
|
- obs_data_set_string(x264Settings, "x264opts", custom);
|
|
|
- obs_data_set_bool(x264Settings, "cbr", useCBR);
|
|
|
- } else {
|
|
|
- obs_data_set_bool(x264Settings, "cbr", true);
|
|
|
- }
|
|
|
-
|
|
|
- obs_data_set_int(aacSettings, "bitrate", audioBitrate);
|
|
|
-
|
|
|
- obs_encoder_update(x264, x264Settings);
|
|
|
- obs_encoder_update(aac, aacSettings);
|
|
|
-
|
|
|
- obs_data_release(x264Settings);
|
|
|
- obs_data_release(aacSettings);
|
|
|
-
|
|
|
- obs_encoder_set_video(x264, obs_get_video());
|
|
|
- obs_encoder_set_audio(aac, obs_get_audio());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void OBSBasic::on_streamButton_clicked()
|
|
|
{
|
|
|
SaveProject();
|
|
|
|
|
|
- if (obs_output_active(streamOutput)) {
|
|
|
- obs_output_stop(streamOutput);
|
|
|
+ if (outputHandler->StreamingActive()) {
|
|
|
+ outputHandler->StopStreaming();
|
|
|
} else {
|
|
|
-
|
|
|
SaveService();
|
|
|
- SetupEncoders();
|
|
|
-
|
|
|
- obs_output_set_video_encoder(streamOutput, x264);
|
|
|
- obs_output_set_audio_encoder(streamOutput, aac, 0);
|
|
|
- obs_output_set_service(streamOutput, service);
|
|
|
-
|
|
|
- bool reconnect = config_get_bool(basicConfig, "SimpleOutput",
|
|
|
- "Reconnect");
|
|
|
- int retryDelay = config_get_uint(basicConfig, "SimpleOutput",
|
|
|
- "RetryDelay");
|
|
|
- int maxRetries = config_get_uint(basicConfig, "SimpleOutput",
|
|
|
- "MaxRetries");
|
|
|
- if (!reconnect)
|
|
|
- maxRetries = 0;
|
|
|
-
|
|
|
- obs_output_set_reconnect_settings(streamOutput, maxRetries,
|
|
|
- retryDelay);
|
|
|
-
|
|
|
- if (obs_output_start(streamOutput)) {
|
|
|
- activeRefs++;
|
|
|
|
|
|
+ if (outputHandler->StartStreaming(service)) {
|
|
|
ui->streamButton->setEnabled(false);
|
|
|
ui->streamButton->setText(
|
|
|
QTStr("Basic.Main.Connecting"));
|
|
@@ -2320,48 +2195,11 @@ void OBSBasic::on_recordButton_clicked()
|
|
|
{
|
|
|
SaveProject();
|
|
|
|
|
|
- if (obs_output_active(fileOutput)) {
|
|
|
- obs_output_stop(fileOutput);
|
|
|
+ if (outputHandler->RecordingActive()) {
|
|
|
+ outputHandler->StopRecording();
|
|
|
} else {
|
|
|
|
|
|
- const char *path = config_get_string(basicConfig,
|
|
|
- "SimpleOutput", "FilePath");
|
|
|
-
|
|
|
- os_dir_t *dir = path ? os_opendir(path) : nullptr;
|
|
|
-
|
|
|
- if (!dir) {
|
|
|
- QMessageBox::information(this,
|
|
|
- QTStr("Output.BadPath.Title"),
|
|
|
- QTStr("Output.BadPath.Text"));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- os_closedir(dir);
|
|
|
-
|
|
|
- string strPath;
|
|
|
- strPath += path;
|
|
|
-
|
|
|
- char lastChar = strPath.back();
|
|
|
- if (lastChar != '/' && lastChar != '\\')
|
|
|
- strPath += "/";
|
|
|
-
|
|
|
- strPath += GenerateTimeDateFilename("flv");
|
|
|
-
|
|
|
- SetupEncoders();
|
|
|
-
|
|
|
- obs_output_set_video_encoder(fileOutput, x264);
|
|
|
- obs_output_set_audio_encoder(fileOutput, aac, 0);
|
|
|
-
|
|
|
- obs_data_t *settings = obs_data_create();
|
|
|
- obs_data_set_string(settings, "path", strPath.c_str());
|
|
|
-
|
|
|
- obs_output_update(fileOutput, settings);
|
|
|
-
|
|
|
- obs_data_release(settings);
|
|
|
-
|
|
|
- if (obs_output_start(fileOutput)) {
|
|
|
- activeRefs++;
|
|
|
-
|
|
|
+ if (outputHandler->StartRecording()) {
|
|
|
ui->recordButton->setText(
|
|
|
QTStr("Basic.Main.StopRecording"));
|
|
|
}
|