diff --git a/js/module.d.ts b/js/module.d.ts
index 2bb3aee9f..9066315bf 100644
--- a/js/module.d.ts
+++ b/js/module.d.ts
@@ -307,6 +307,8 @@ export declare const VideoEncoderFactory: IVideoEncoderFactory;
export declare const ServiceFactory: IServiceFactory;
export declare const SimpleStreamingFactory: ISimpleStreamingFactory;
export declare const AdvancedStreamingFactory: IAdvancedStreamingFactory;
+export declare const EnhancedBroadcastingAdvancedStreamingFactory: IEnhancedBroadcastingAdvancedStreamingFactory;
+export declare const EnhancedBroadcastingSimpleStreamingFactory: IEnhancedBroadcastingSimpleStreamingFactory;
export declare const DelayFactory: IDelayFactory;
export declare const ReconnectFactory: IReconnectFactory;
export declare const NetworkFactory: INetworkFactory;
@@ -794,7 +796,8 @@ export interface IVideoEncoderFactory {
create(id: string, name: string, settings?: ISettings): IVideoEncoder;
}
export interface IStreaming {
- videoEncoder: IVideoEncoder;
+ // Video encoder value is only ignored in the Enhanced Broadcasting mode, otherwise it should be set
+ videoEncoder?: IVideoEncoder;
service: IService;
enforceServiceBitrate: boolean;
enableTwitchVOD: boolean;
@@ -803,7 +806,7 @@ export interface IStreaming {
network: INetwork;
video: IVideo;
signalHandler: (signal: EOutputSignal) => void;
- start(): void;
+ start(): void; // throws
stop(force?: boolean): void;
droppedFrames: number;
totalFrames: number;
@@ -838,6 +841,26 @@ export interface IAdvancedStreamingFactory {
destroy(stream: IAdvancedStreaming): void;
legacySettings: IAdvancedStreaming;
}
+export interface IEnhancedBroadcastingAdvancedStreaming extends IAdvancedStreaming {
+ // If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
+ // This value should be initialized before the stream start.
+ additionalVideo?: IVideo,
+}
+export interface IEnhancedBroadcastingAdvancedStreamingFactory {
+ create(): IEnhancedBroadcastingAdvancedStreaming;
+ destroy(stream: IEnhancedBroadcastingAdvancedStreaming): void;
+ legacySettings: IEnhancedBroadcastingAdvancedStreaming;
+}
+export interface IEnhancedBroadcastingSimpleStreaming extends ISimpleStreaming {
+ // If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
+ // This value should be initialized before the stream start.
+ additionalVideo?: IVideo,
+}
+export interface IEnhancedBroadcastingSimpleStreamingFactory {
+ create(): IEnhancedBroadcastingSimpleStreaming;
+ destroy(stream: IEnhancedBroadcastingSimpleStreaming): void;
+ legacySettings: IEnhancedBroadcastingSimpleStreaming;
+}
export interface IFileOutput {
path: string;
format: ERecordingFormat;
diff --git a/js/module.js b/js/module.js
index 48ea85376..61471a348 100644
--- a/js/module.js
+++ b/js/module.js
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-exports.NodeObs = exports.getSourcesSize = exports.createSources = exports.addItems = exports.AdvancedReplayBufferFactory = exports.SimpleReplayBufferFactory = exports.AudioEncoderFactory = exports.AdvancedRecordingFactory = exports.SimpleRecordingFactory = exports.AudioTrackFactory = exports.NetworkFactory = exports.ReconnectFactory = exports.DelayFactory = exports.AdvancedStreamingFactory = exports.SimpleStreamingFactory = exports.ServiceFactory = exports.VideoEncoderFactory = exports.IPC = exports.ModuleFactory = exports.AudioFactory = exports.Audio = exports.FaderFactory = exports.VolmeterFactory = exports.DisplayFactory = exports.TransitionFactory = exports.FilterFactory = exports.SceneFactory = exports.InputFactory = exports.VideoFactory = exports.Video = exports.Global = exports.DefaultPluginPathMac = exports.DefaultPluginDataPath = exports.DefaultPluginPath = exports.DefaultDataPath = exports.DefaultBinPath = exports.DefaultDrawPluginPath = exports.DefaultOpenGLPath = exports.DefaultD3D11Path = void 0;
+exports.NodeObs = exports.getSourcesSize = exports.createSources = exports.addItems = exports.AdvancedReplayBufferFactory = exports.SimpleReplayBufferFactory = exports.AudioEncoderFactory = exports.AdvancedRecordingFactory = exports.SimpleRecordingFactory = exports.AudioTrackFactory = exports.NetworkFactory = exports.ReconnectFactory = exports.DelayFactory = exports.AdvancedStreamingFactory = exports.EnhancedBroadcastingSimpleStreamingFactory = exports.EnhancedBroadcastingAdvancedStreamingFactory = exports.SimpleStreamingFactory = exports.ServiceFactory = exports.VideoEncoderFactory = exports.IPC = exports.ModuleFactory = exports.AudioFactory = exports.Audio = exports.FaderFactory = exports.VolmeterFactory = exports.DisplayFactory = exports.TransitionFactory = exports.FilterFactory = exports.SceneFactory = exports.InputFactory = exports.VideoFactory = exports.Video = exports.Global = exports.DefaultPluginPathMac = exports.DefaultPluginDataPath = exports.DefaultPluginPath = exports.DefaultDataPath = exports.DefaultBinPath = exports.DefaultDrawPluginPath = exports.DefaultOpenGLPath = exports.DefaultD3D11Path = void 0;
const path = require("path");
const fs = require("fs");
// Mac- search for optional OSN.app bundle (Chromium requires an app bundle to find obs64 helper apps)
@@ -34,6 +34,8 @@ exports.VideoEncoderFactory = obs.VideoEncoder;
exports.ServiceFactory = obs.Service;
exports.SimpleStreamingFactory = obs.SimpleStreaming;
exports.AdvancedStreamingFactory = obs.AdvancedStreaming;
+exports.EnhancedBroadcastingAdvancedStreamingFactory = obs.EnhancedBroadcastingAdvancedStreaming;
+exports.EnhancedBroadcastingSimpleStreamingFactory = obs.EnhancedBroadcastingSimpleStreaming;
exports.DelayFactory = obs.Delay;
exports.ReconnectFactory = obs.Reconnect;
exports.NetworkFactory = obs.Network;
@@ -70,7 +72,7 @@ function createSources(sources) {
console.error(`[OSN] Failed to create input for source "${source.name}":`, error instanceof Error ? error.message : error);
return; // Skip the rest of this iteration if input creation fails
}
-
+
if (newSource) {
if (newSource.audioMixers) {
newSource.muted = source.muted ?? false;
@@ -80,7 +82,7 @@ function createSources(sources) {
newSource.deinterlaceMode = source.deinterlaceMode;
newSource.deinterlaceFieldOrder = source.deinterlaceFieldOrder;
items.push(newSource);
-
+
const filters = source.filters;
if (Array.isArray(filters)) {
filters.forEach(function (filter) {
@@ -90,7 +92,7 @@ function createSources(sources) {
} catch (filterError) {
console.error(`[OSN] Failed to create filter "${filter.name}" for source "${source.name}":`, filterError instanceof Error ? filterError.message : filterError);
}
-
+
if (ObsFilter) {
ObsFilter.enabled = filter.enabled ?? true;
newSource.addFilter(ObsFilter);
diff --git a/js/module.ts b/js/module.ts
index 6ef9a70ea..8063934e3 100644
--- a/js/module.ts
+++ b/js/module.ts
@@ -392,6 +392,8 @@ export const VideoEncoderFactory: IVideoEncoderFactory = obs.VideoEncoder;
export const ServiceFactory: IServiceFactory = obs.Service;
export const SimpleStreamingFactory: ISimpleStreamingFactory = obs.SimpleStreaming;
export const AdvancedStreamingFactory: IAdvancedStreamingFactory = obs.AdvancedStreaming;
+export const EnhancedBroadcastingAdvancedStreamingFactory: IEnhancedBroadcastingAdvancedStreamingFactory = obs.EnhancedBroadcastingAdvancedStreaming;
+export const EnhancedBroadcastingSimpleStreamingFactory: IEnhancedBroadcastingSimpleStreamingFactory = obs.EnhancedBroadcastingSimpleStreaming;
export const DelayFactory: IDelayFactory = obs.Delay;
export const ReconnectFactory: IReconnectFactory = obs.Reconnect;
export const NetworkFactory: INetworkFactory = obs.Network;
@@ -581,12 +583,12 @@ export interface IGlobal {
readonly version: number;
/**
- * Percentage of CPU being used
+ * Percentage of CPU being used
*/
readonly cpuPercentage: number;
/**
- * Current FPS
+ * Current FPS
*/
readonly currentFrameRate: number;
@@ -601,7 +603,7 @@ export interface IGlobal {
readonly diskSpaceAvailable: number;
/**
- * Current memory usage
+ * Current memory usage
*/
readonly memoryUsage: number;
}
@@ -1705,7 +1707,8 @@ export interface IVideoEncoderFactory {
}
export interface IStreaming {
- videoEncoder: IVideoEncoder,
+ // Video encoder value is ignored only in the Enhanced Broadcasting mode, otherwise it should be set
+ videoEncoder?: IVideoEncoder,
service: IService,
enforceServiceBitrate: boolean,
enableTwitchVOD: boolean,
@@ -1714,7 +1717,7 @@ export interface IStreaming {
network: INetwork,
video: IVideo,
signalHandler: (signal: EOutputSignal) => void,
- start(): void,
+ start(): void, // throws
stop(force?: boolean): void,
droppedFrames: number;
totalFrames: number;
@@ -1755,6 +1758,30 @@ export interface IAdvancedStreamingFactory {
legacySettings: IAdvancedStreaming;
}
+export interface IEnhancedBroadcastingAdvancedStreaming extends IAdvancedStreaming {
+ // If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
+ // This value should be initialized before the stream start.
+ additionalVideo?: IVideo,
+}
+
+export interface IEnhancedBroadcastingAdvancedStreamingFactory {
+ create(): IEnhancedBroadcastingAdvancedStreaming;
+ destroy(stream: IEnhancedBroadcastingAdvancedStreaming): void;
+ legacySettings: IEnhancedBroadcastingAdvancedStreaming;
+}
+
+export interface IEnhancedBroadcastingSimpleStreaming extends ISimpleStreaming {
+ // If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
+ // This value should be initialized before the stream start.
+ additionalVideo?: IVideo,
+}
+
+export interface IEnhancedBroadcastingSimpleStreamingFactory {
+ create(): IEnhancedBroadcastingSimpleStreaming;
+ destroy(stream: IEnhancedBroadcastingSimpleStreaming): void;
+ legacySettings: IEnhancedBroadcastingSimpleStreaming;
+}
+
export interface IFileOutput {
path: string,
format: ERecordingFormat,
diff --git a/obs-studio-client/CMakeLists.txt b/obs-studio-client/CMakeLists.txt
index b8abce6c9..ec3530915 100644
--- a/obs-studio-client/CMakeLists.txt
+++ b/obs-studio-client/CMakeLists.txt
@@ -98,10 +98,18 @@ SET(osn-client_SOURCES
"source/audio.cpp"
"source/streaming.hpp"
"source/streaming.cpp"
+ "source/simple-streaming-base.hpp"
+ "source/simple-streaming-base.cpp"
"source/simple-streaming.hpp"
"source/simple-streaming.cpp"
+ "source/advanced-streaming-base.hpp"
+ "source/advanced-streaming-base.cpp"
"source/advanced-streaming.hpp"
"source/advanced-streaming.cpp"
+ "source/enhanced-broadcasting-advanced-streaming.hpp"
+ "source/enhanced-broadcasting-advanced-streaming.cpp"
+ "source/enhanced-broadcasting-simple-streaming.hpp"
+ "source/enhanced-broadcasting-simple-streaming.cpp"
"source/worker-signals.hpp"
"source/delay.hpp"
"source/delay.cpp"
@@ -187,7 +195,7 @@ target_link_libraries(${PROJECT_NAME} ${LIBOBS_LIBRARIES})
add_definitions(-DNAPI_VERSION=7)
#Define the OSN_VERSION
-add_compile_definitions(OSN_VERSION=\"$ENV{tagartifact}\")
+add_compile_definitions(OSN_VERSION=\"$ENV{tagartifact}\")
set_target_properties(
obs_studio_client
PROPERTIES
@@ -235,5 +243,5 @@ install(
TARGETS obs_studio_client
RUNTIME DESTINATION "./" COMPONENT Runtime
LIBRARY DESTINATION "./" COMPONENT Runtime
- ARCHIVE DESTINATION "./" COMPONENT Runtime
+ ARCHIVE DESTINATION "./" COMPONENT Runtime
)
diff --git a/obs-studio-client/source/advanced-streaming-base.cpp b/obs-studio-client/source/advanced-streaming-base.cpp
new file mode 100644
index 000000000..3c13403ef
--- /dev/null
+++ b/obs-studio-client/source/advanced-streaming-base.cpp
@@ -0,0 +1,134 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#include "advanced-streaming-base.hpp"
+
+Napi::Value osn::AdvancedStreamingBase::GetAudioTrack(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetAudioTrack", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::Number::New(info.Env(), response[1].value_union.ui32);
+}
+
+void osn::AdvancedStreamingBase::SetAudioTrack(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("AdvancedStreaming", "SetAudioTrack", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
+}
+
+Napi::Value osn::AdvancedStreamingBase::GetTwitchTrack(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetTwitchTrack", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::Number::New(info.Env(), response[1].value_union.ui32);
+}
+
+void osn::AdvancedStreamingBase::SetTwitchTrack(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("AdvancedStreaming", "SetTwitchTrack", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
+}
+
+Napi::Value osn::AdvancedStreamingBase::GetRescaling(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetRescaling", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::Boolean::New(info.Env(), response[1].value_union.ui32);
+}
+
+void osn::AdvancedStreamingBase::SetRescaling(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("AdvancedStreaming", "SetRescaling", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
+}
+
+Napi::Value osn::AdvancedStreamingBase::GetOutputWidth(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetOutputWidth", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::Number::New(info.Env(), response[1].value_union.ui32);
+}
+
+void osn::AdvancedStreamingBase::SetOutputWidth(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("AdvancedStreaming", "SetOutputWidth", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
+}
+
+Napi::Value osn::AdvancedStreamingBase::GetOutputHeight(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetOutputHeight", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::Number::New(info.Env(), response[1].value_union.ui32);
+}
+
+void osn::AdvancedStreamingBase::SetOutputHeight(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("AdvancedStreaming", "SetOutputHeight", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
+}
diff --git a/obs-studio-client/source/advanced-streaming-base.hpp b/obs-studio-client/source/advanced-streaming-base.hpp
new file mode 100644
index 000000000..1ad27dea1
--- /dev/null
+++ b/obs-studio-client/source/advanced-streaming-base.hpp
@@ -0,0 +1,39 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#pragma once
+#include
+#include "streaming.hpp"
+
+namespace osn {
+
+class AdvancedStreamingBase : public osn::Streaming {
+public:
+ Napi::Value GetAudioTrack(const Napi::CallbackInfo &info);
+ void SetAudioTrack(const Napi::CallbackInfo &info, const Napi::Value &value);
+ Napi::Value GetTwitchTrack(const Napi::CallbackInfo &info);
+ void SetTwitchTrack(const Napi::CallbackInfo &info, const Napi::Value &value);
+ Napi::Value GetRescaling(const Napi::CallbackInfo &info);
+ void SetRescaling(const Napi::CallbackInfo &info, const Napi::Value &value);
+ Napi::Value GetOutputWidth(const Napi::CallbackInfo &info);
+ void SetOutputWidth(const Napi::CallbackInfo &info, const Napi::Value &value);
+ Napi::Value GetOutputHeight(const Napi::CallbackInfo &info);
+ void SetOutputHeight(const Napi::CallbackInfo &info, const Napi::Value &value);
+};
+
+}
\ No newline at end of file
diff --git a/obs-studio-client/source/advanced-streaming.cpp b/obs-studio-client/source/advanced-streaming.cpp
index 267169b07..45697af65 100644
--- a/obs-studio-client/source/advanced-streaming.cpp
+++ b/obs-studio-client/source/advanced-streaming.cpp
@@ -116,121 +116,6 @@ void osn::AdvancedStreaming::Destroy(const Napi::CallbackInfo &info)
return;
}
-Napi::Value osn::AdvancedStreaming::GetAudioTrack(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetAudioTrack", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::Number::New(info.Env(), response[1].value_union.ui32);
-}
-
-void osn::AdvancedStreaming::SetAudioTrack(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("AdvancedStreaming", "SetAudioTrack", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
-}
-
-Napi::Value osn::AdvancedStreaming::GetTwitchTrack(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetTwitchTrack", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::Number::New(info.Env(), response[1].value_union.ui32);
-}
-
-void osn::AdvancedStreaming::SetTwitchTrack(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("AdvancedStreaming", "SetTwitchTrack", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
-}
-
-Napi::Value osn::AdvancedStreaming::GetRescaling(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetRescaling", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::Boolean::New(info.Env(), response[1].value_union.ui32);
-}
-
-void osn::AdvancedStreaming::SetRescaling(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("AdvancedStreaming", "SetRescaling", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
-}
-
-Napi::Value osn::AdvancedStreaming::GetOutputWidth(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetOutputWidth", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::Number::New(info.Env(), response[1].value_union.ui32);
-}
-
-void osn::AdvancedStreaming::SetOutputWidth(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("AdvancedStreaming", "SetOutputWidth", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
-}
-
-Napi::Value osn::AdvancedStreaming::GetOutputHeight(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("AdvancedStreaming", "GetOutputHeight", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::Number::New(info.Env(), response[1].value_union.ui32);
-}
-
-void osn::AdvancedStreaming::SetOutputHeight(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("AdvancedStreaming", "SetOutputHeight", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
-}
-
Napi::Value osn::AdvancedStreaming::GetLegacySettings(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
diff --git a/obs-studio-client/source/advanced-streaming.hpp b/obs-studio-client/source/advanced-streaming.hpp
index 261c5585c..b15274bf5 100644
--- a/obs-studio-client/source/advanced-streaming.hpp
+++ b/obs-studio-client/source/advanced-streaming.hpp
@@ -18,10 +18,11 @@
#pragma once
#include
-#include "streaming.hpp"
+#include "advanced-streaming-base.hpp"
namespace osn {
-class AdvancedStreaming : public Napi::ObjectWrap, public osn::Streaming {
+
+class AdvancedStreaming : public Napi::ObjectWrap, public osn::AdvancedStreamingBase {
public:
static Napi::FunctionReference constructor;
static Napi::Object Init(Napi::Env env, Napi::Object exports);
@@ -30,18 +31,8 @@ class AdvancedStreaming : public Napi::ObjectWrap, publi
static Napi::Value Create(const Napi::CallbackInfo &info);
static void Destroy(const Napi::CallbackInfo &info);
- Napi::Value GetAudioTrack(const Napi::CallbackInfo &info);
- void SetAudioTrack(const Napi::CallbackInfo &info, const Napi::Value &value);
- Napi::Value GetTwitchTrack(const Napi::CallbackInfo &info);
- void SetTwitchTrack(const Napi::CallbackInfo &info, const Napi::Value &value);
- Napi::Value GetRescaling(const Napi::CallbackInfo &info);
- void SetRescaling(const Napi::CallbackInfo &info, const Napi::Value &value);
- Napi::Value GetOutputWidth(const Napi::CallbackInfo &info);
- void SetOutputWidth(const Napi::CallbackInfo &info, const Napi::Value &value);
- Napi::Value GetOutputHeight(const Napi::CallbackInfo &info);
- void SetOutputHeight(const Napi::CallbackInfo &info, const Napi::Value &value);
-
static Napi::Value GetLegacySettings(const Napi::CallbackInfo &info);
static void SetLegacySettings(const Napi::CallbackInfo &info, const Napi::Value &value);
};
+
}
\ No newline at end of file
diff --git a/obs-studio-client/source/enhanced-broadcasting-advanced-streaming.cpp b/obs-studio-client/source/enhanced-broadcasting-advanced-streaming.cpp
new file mode 100644
index 000000000..0744f9899
--- /dev/null
+++ b/obs-studio-client/source/enhanced-broadcasting-advanced-streaming.cpp
@@ -0,0 +1,201 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#include "enhanced-broadcasting-advanced-streaming.hpp"
+#include "utility.hpp"
+#include "service.hpp"
+#include "delay.hpp"
+#include "reconnect.hpp"
+#include "network.hpp"
+#include "video.hpp"
+
+Napi::FunctionReference osn::EnhancedBroadcastingAdvancedStreaming::constructor;
+
+Napi::Object osn::EnhancedBroadcastingAdvancedStreaming::Init(Napi::Env env, Napi::Object exports)
+{
+ Napi::HandleScope scope(env);
+ Napi::Function func = DefineClass(
+ env, "EnhancedBroadcastingAdvancedStreaming",
+ {StaticMethod("create", &osn::EnhancedBroadcastingAdvancedStreaming::Create),
+ StaticMethod("destroy", &osn::EnhancedBroadcastingAdvancedStreaming::Destroy),
+
+ InstanceAccessor("videoEncoder", &osn::EnhancedBroadcastingAdvancedStreaming::GetVideoEncoder,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetVideoEncoder),
+ InstanceAccessor("service", &osn::EnhancedBroadcastingAdvancedStreaming::GetService, &osn::EnhancedBroadcastingAdvancedStreaming::SetService),
+ InstanceAccessor("enforceServiceBitrate", &osn::EnhancedBroadcastingAdvancedStreaming::GetEnforceServiceBirate,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetEnforceServiceBirate),
+ InstanceAccessor("enableTwitchVOD", &osn::EnhancedBroadcastingAdvancedStreaming::GetEnableTwitchVOD,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetEnableTwitchVOD),
+ InstanceAccessor("signalHandler", &osn::EnhancedBroadcastingAdvancedStreaming::GetSignalHandler,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetSignalHandler),
+ InstanceAccessor("delay", &osn::EnhancedBroadcastingAdvancedStreaming::GetDelay, &osn::EnhancedBroadcastingAdvancedStreaming::SetDelay),
+ InstanceAccessor("reconnect", &osn::EnhancedBroadcastingAdvancedStreaming::GetReconnect,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetReconnect),
+ InstanceAccessor("network", &osn::EnhancedBroadcastingAdvancedStreaming::GetNetwork, &osn::EnhancedBroadcastingAdvancedStreaming::SetNetwork),
+ InstanceAccessor("video", &osn::EnhancedBroadcastingAdvancedStreaming::GetCanvas, &osn::EnhancedBroadcastingAdvancedStreaming::SetCanvas),
+ InstanceAccessor("additionalVideo", &osn::EnhancedBroadcastingAdvancedStreaming::GetAdditionalCanvas,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetAdditionalCanvas),
+ InstanceAccessor("droppedFrames", &osn::EnhancedBroadcastingAdvancedStreaming::GetDroppedFrames, nullptr),
+ InstanceAccessor("totalFrames", &osn::EnhancedBroadcastingAdvancedStreaming::GetTotalFrames, nullptr),
+ InstanceAccessor("kbitsPerSec", &osn::EnhancedBroadcastingAdvancedStreaming::GetKBitsPerSec, nullptr),
+ InstanceAccessor("dataOutput", &osn::EnhancedBroadcastingAdvancedStreaming::GetDataOutput, nullptr),
+
+ InstanceAccessor("audioTrack", &osn::EnhancedBroadcastingAdvancedStreaming::GetAudioTrack,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetAudioTrack),
+ InstanceAccessor("twitchTrack", &osn::EnhancedBroadcastingAdvancedStreaming::GetTwitchTrack,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetTwitchTrack),
+ InstanceAccessor("rescaling", &osn::EnhancedBroadcastingAdvancedStreaming::GetRescaling,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetRescaling),
+ InstanceAccessor("outputWidth", &osn::EnhancedBroadcastingAdvancedStreaming::GetOutputWidth,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetOutputWidth),
+ InstanceAccessor("outputHeight", &osn::EnhancedBroadcastingAdvancedStreaming::GetOutputHeight,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetOutputHeight),
+
+ InstanceMethod("start", &osn::EnhancedBroadcastingAdvancedStreaming::Start),
+ InstanceMethod("stop", &osn::EnhancedBroadcastingAdvancedStreaming::Stop),
+
+ StaticAccessor("legacySettings", &osn::EnhancedBroadcastingAdvancedStreaming::GetLegacySettings,
+ &osn::EnhancedBroadcastingAdvancedStreaming::SetLegacySettings)});
+
+ exports.Set("EnhancedBroadcastingAdvancedStreaming", func);
+ osn::EnhancedBroadcastingAdvancedStreaming::constructor = Napi::Persistent(func);
+ osn::EnhancedBroadcastingAdvancedStreaming::constructor.SuppressDestruct();
+
+ return exports;
+}
+
+osn::EnhancedBroadcastingAdvancedStreaming::EnhancedBroadcastingAdvancedStreaming(const Napi::CallbackInfo &info)
+ : Napi::ObjectWrap(info)
+{
+ Napi::Env env = info.Env();
+ Napi::HandleScope scope(env);
+ size_t length = info.Length();
+
+ if (length <= 0 || !info[0].IsNumber()) {
+ Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
+ return;
+ }
+
+ this->uid = (uint64_t)info[0].ToNumber().Int64Value();
+ this->className = std::string("EnhancedBroadcastingAdvancedStreaming");
+}
+
+Napi::Value osn::EnhancedBroadcastingAdvancedStreaming::Create(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingAdvancedStreaming", "Create", {});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance =
+ osn::EnhancedBroadcastingAdvancedStreaming::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+
+ return instance;
+}
+
+void osn::EnhancedBroadcastingAdvancedStreaming::Destroy(const Napi::CallbackInfo &info)
+{
+ if (info.Length() != 1)
+ return;
+
+ auto stream = Napi::ObjectWrap::Unwrap(info[0].ToObject());
+
+ stream->stopWorker();
+ stream->cb.Reset();
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingAdvancedStreaming", "Destroy", {ipc::value(stream->uid)});
+
+ if (!ValidateResponse(info, response))
+ return;
+}
+
+Napi::Value osn::EnhancedBroadcastingAdvancedStreaming::GetAdditionalCanvas(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper(className, "GetAdditionalVideoCanvas", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance = osn::Video::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+
+ return instance;
+}
+
+void osn::EnhancedBroadcastingAdvancedStreaming::SetAdditionalCanvas(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ osn::Video *canvas = Napi::ObjectWrap::Unwrap(value.ToObject());
+
+ if (!canvas) {
+ Napi::TypeError::New(info.Env(), "Invalid canvas argument").ThrowAsJavaScriptException();
+ return;
+ }
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call(className, "SetAdditionalVideoCanvas", {ipc::value(this->uid), ipc::value(canvas->canvasId)});
+}
+
+Napi::Value osn::EnhancedBroadcastingAdvancedStreaming::GetLegacySettings(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingAdvancedStreaming", "GetLegacySettings", {});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance =
+ osn::EnhancedBroadcastingAdvancedStreaming::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+
+ return instance;
+}
+
+void osn::EnhancedBroadcastingAdvancedStreaming::SetLegacySettings(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ osn::EnhancedBroadcastingAdvancedStreaming *streaming = Napi::ObjectWrap::Unwrap(value.ToObject());
+
+ if (!streaming) {
+ Napi::TypeError::New(info.Env(), "Invalid service argument").ThrowAsJavaScriptException();
+ return;
+ }
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingAdvancedStreaming", "SetLegacySettings", {streaming->uid});
+
+ if (!ValidateResponse(info, response))
+ return;
+}
\ No newline at end of file
diff --git a/obs-studio-client/source/enhanced-broadcasting-advanced-streaming.hpp b/obs-studio-client/source/enhanced-broadcasting-advanced-streaming.hpp
new file mode 100644
index 000000000..37ee11a2f
--- /dev/null
+++ b/obs-studio-client/source/enhanced-broadcasting-advanced-streaming.hpp
@@ -0,0 +1,39 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#pragma once
+#include
+#include "advanced-streaming.hpp"
+
+namespace osn {
+class EnhancedBroadcastingAdvancedStreaming : public Napi::ObjectWrap, public osn::AdvancedStreamingBase {
+public:
+ static Napi::FunctionReference constructor;
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
+ EnhancedBroadcastingAdvancedStreaming(const Napi::CallbackInfo &info);
+
+ static Napi::Value Create(const Napi::CallbackInfo &info);
+ static void Destroy(const Napi::CallbackInfo &info);
+
+ Napi::Value GetAdditionalCanvas(const Napi::CallbackInfo &info);
+ void SetAdditionalCanvas(const Napi::CallbackInfo &info, const Napi::Value &value);
+
+ static Napi::Value GetLegacySettings(const Napi::CallbackInfo &info);
+ static void SetLegacySettings(const Napi::CallbackInfo &info, const Napi::Value &value);
+};
+}
\ No newline at end of file
diff --git a/obs-studio-client/source/enhanced-broadcasting-simple-streaming.cpp b/obs-studio-client/source/enhanced-broadcasting-simple-streaming.cpp
new file mode 100644
index 000000000..01d95d940
--- /dev/null
+++ b/obs-studio-client/source/enhanced-broadcasting-simple-streaming.cpp
@@ -0,0 +1,198 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#include "enhanced-broadcasting-simple-streaming.hpp"
+#include "utility.hpp"
+#include "service.hpp"
+#include "delay.hpp"
+#include "reconnect.hpp"
+#include "network.hpp"
+#include "video.hpp"
+
+Napi::FunctionReference osn::EnhancedBroadcastingSimpleStreaming::constructor;
+
+Napi::Object osn::EnhancedBroadcastingSimpleStreaming::Init(Napi::Env env, Napi::Object exports)
+{
+ Napi::HandleScope scope(env);
+ Napi::Function func = DefineClass(
+ env, "EnhancedBroadcastingSimpleStreaming",
+ {StaticMethod("create", &osn::EnhancedBroadcastingSimpleStreaming::Create),
+ StaticMethod("destroy", &osn::EnhancedBroadcastingSimpleStreaming::Destroy),
+
+ InstanceAccessor("videoEncoder", &osn::EnhancedBroadcastingSimpleStreaming::GetVideoEncoder,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetVideoEncoder),
+ InstanceAccessor("audioEncoder", &osn::EnhancedBroadcastingSimpleStreaming::GetAudioEncoder,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetAudioEncoder),
+ InstanceAccessor("service", &osn::EnhancedBroadcastingSimpleStreaming::GetService, &osn::EnhancedBroadcastingSimpleStreaming::SetService),
+ InstanceAccessor("enforceServiceBitrate", &osn::EnhancedBroadcastingSimpleStreaming::GetEnforceServiceBirate,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetEnforceServiceBirate),
+ InstanceAccessor("enableTwitchVOD", &osn::EnhancedBroadcastingSimpleStreaming::GetEnableTwitchVOD,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetEnableTwitchVOD),
+ InstanceAccessor("audioEncoder", &osn::EnhancedBroadcastingSimpleStreaming::GetAudioEncoder,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetAudioEncoder),
+ InstanceAccessor("useAdvanced", &osn::EnhancedBroadcastingSimpleStreaming::GetUseAdvanced,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetUseAdvanced),
+ InstanceAccessor("customEncSettings", &osn::EnhancedBroadcastingSimpleStreaming::GetCustomEncSettings,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetCustomEncSettings),
+ InstanceAccessor("signalHandler", &osn::EnhancedBroadcastingSimpleStreaming::GetSignalHandler,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetSignalHandler),
+ InstanceAccessor("delay", &osn::EnhancedBroadcastingSimpleStreaming::GetDelay, &osn::EnhancedBroadcastingSimpleStreaming::SetDelay),
+ InstanceAccessor("reconnect", &osn::EnhancedBroadcastingSimpleStreaming::GetReconnect,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetReconnect),
+ InstanceAccessor("network", &osn::EnhancedBroadcastingSimpleStreaming::GetNetwork, &osn::EnhancedBroadcastingSimpleStreaming::SetNetwork),
+ InstanceAccessor("video", &osn::EnhancedBroadcastingSimpleStreaming::GetCanvas, &osn::EnhancedBroadcastingSimpleStreaming::SetCanvas),
+ InstanceAccessor("additionalVideo", &osn::EnhancedBroadcastingSimpleStreaming::GetAdditionalCanvas,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetAdditionalCanvas),
+ InstanceAccessor("droppedFrames", &osn::EnhancedBroadcastingSimpleStreaming::GetDroppedFrames, nullptr),
+ InstanceAccessor("totalFrames", &osn::EnhancedBroadcastingSimpleStreaming::GetTotalFrames, nullptr),
+ InstanceAccessor("kbitsPerSec", &osn::EnhancedBroadcastingSimpleStreaming::GetKBitsPerSec, nullptr),
+ InstanceAccessor("dataOutput", &osn::EnhancedBroadcastingSimpleStreaming::GetDataOutput, nullptr),
+
+ InstanceMethod("start", &osn::EnhancedBroadcastingSimpleStreaming::Start),
+ InstanceMethod("stop", &osn::EnhancedBroadcastingSimpleStreaming::Stop),
+
+ StaticAccessor("legacySettings", &osn::EnhancedBroadcastingSimpleStreaming::GetLegacySettings,
+ &osn::EnhancedBroadcastingSimpleStreaming::SetLegacySettings)});
+
+ exports.Set("EnhancedBroadcastingSimpleStreaming", func);
+ osn::EnhancedBroadcastingSimpleStreaming::constructor = Napi::Persistent(func);
+ osn::EnhancedBroadcastingSimpleStreaming::constructor.SuppressDestruct();
+
+ return exports;
+}
+
+osn::EnhancedBroadcastingSimpleStreaming::EnhancedBroadcastingSimpleStreaming(const Napi::CallbackInfo &info)
+ : Napi::ObjectWrap(info)
+{
+ Napi::Env env = info.Env();
+ Napi::HandleScope scope(env);
+ size_t length = info.Length();
+
+ if (length <= 0 || !info[0].IsNumber()) {
+ Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
+ return;
+ }
+
+ this->uid = (uint64_t)info[0].ToNumber().Int64Value();
+ this->className = std::string("EnhancedBroadcastingSimpleStreaming");
+}
+
+Napi::Value osn::EnhancedBroadcastingSimpleStreaming::Create(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingSimpleStreaming", "Create", {});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance =
+ osn::EnhancedBroadcastingSimpleStreaming::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+
+ return instance;
+}
+
+void osn::EnhancedBroadcastingSimpleStreaming::Destroy(const Napi::CallbackInfo &info)
+{
+ if (info.Length() != 1)
+ return;
+
+ auto stream = Napi::ObjectWrap::Unwrap(info[0].ToObject());
+
+ stream->stopWorker();
+ stream->cb.Reset();
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingSimpleStreaming", "Destroy", {ipc::value(stream->uid)});
+
+ if (!ValidateResponse(info, response))
+ return;
+}
+
+Napi::Value osn::EnhancedBroadcastingSimpleStreaming::GetAdditionalCanvas(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper(className, "GetAdditionalVideoCanvas", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance = osn::Video::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+
+ return instance;
+}
+
+void osn::EnhancedBroadcastingSimpleStreaming::SetAdditionalCanvas(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ osn::Video *canvas = Napi::ObjectWrap::Unwrap(value.ToObject());
+
+ if (!canvas) {
+ Napi::TypeError::New(info.Env(), "Invalid canvas argument").ThrowAsJavaScriptException();
+ return;
+ }
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call(className, "SetAdditionalVideoCanvas", {ipc::value(this->uid), ipc::value(canvas->canvasId)});
+}
+
+Napi::Value osn::EnhancedBroadcastingSimpleStreaming::GetLegacySettings(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingSimpleStreaming", "GetLegacySettings", {});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance =
+ osn::EnhancedBroadcastingSimpleStreaming::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+
+ return instance;
+}
+
+void osn::EnhancedBroadcastingSimpleStreaming::SetLegacySettings(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ osn::EnhancedBroadcastingSimpleStreaming *streaming = Napi::ObjectWrap::Unwrap(value.ToObject());
+
+ if (!streaming) {
+ Napi::TypeError::New(info.Env(), "Invalid service argument").ThrowAsJavaScriptException();
+ return;
+ }
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ std::vector response = conn->call_synchronous_helper("EnhancedBroadcastingSimpleStreaming", "SetLegacySettings", {streaming->uid});
+
+ if (!ValidateResponse(info, response))
+ return;
+}
\ No newline at end of file
diff --git a/obs-studio-client/source/enhanced-broadcasting-simple-streaming.hpp b/obs-studio-client/source/enhanced-broadcasting-simple-streaming.hpp
new file mode 100644
index 000000000..00b60d49b
--- /dev/null
+++ b/obs-studio-client/source/enhanced-broadcasting-simple-streaming.hpp
@@ -0,0 +1,39 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#pragma once
+#include
+#include "simple-streaming.hpp"
+
+namespace osn {
+class EnhancedBroadcastingSimpleStreaming : public Napi::ObjectWrap, public osn::SimpleStreamingBase {
+public:
+ static Napi::FunctionReference constructor;
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
+ EnhancedBroadcastingSimpleStreaming(const Napi::CallbackInfo &info);
+
+ static Napi::Value Create(const Napi::CallbackInfo &info);
+ static void Destroy(const Napi::CallbackInfo &info);
+
+ Napi::Value GetAdditionalCanvas(const Napi::CallbackInfo &info);
+ void SetAdditionalCanvas(const Napi::CallbackInfo &info, const Napi::Value &value);
+
+ static Napi::Value GetLegacySettings(const Napi::CallbackInfo &info);
+ static void SetLegacySettings(const Napi::CallbackInfo &info, const Napi::Value &value);
+};
+}
\ No newline at end of file
diff --git a/obs-studio-client/source/main.cpp b/obs-studio-client/source/main.cpp
index 132f8efac..5b439f5ca 100644
--- a/obs-studio-client/source/main.cpp
+++ b/obs-studio-client/source/main.cpp
@@ -54,6 +54,8 @@
#include "advanced-recording.hpp"
#include "simple-replay-buffer.hpp"
#include "advanced-replay-buffer.hpp"
+#include "enhanced-broadcasting-advanced-streaming.hpp"
+#include "enhanced-broadcasting-simple-streaming.hpp"
#if defined(_WIN32)
// Checks ForceGPUAsRenderDevice setting
@@ -138,6 +140,8 @@ Napi::Object main_node(Napi::Env env, Napi::Object exports)
osn::AdvancedRecording::Init(env, exports);
osn::SimpleReplayBuffer::Init(env, exports);
osn::AdvancedReplayBuffer::Init(env, exports);
+ osn::EnhancedBroadcastingAdvancedStreaming::Init(env, exports);
+ osn::EnhancedBroadcastingSimpleStreaming::Init(env, exports);
return exports;
};
diff --git a/obs-studio-client/source/simple-streaming-base.cpp b/obs-studio-client/source/simple-streaming-base.cpp
new file mode 100644
index 000000000..4e9aef8ae
--- /dev/null
+++ b/obs-studio-client/source/simple-streaming-base.cpp
@@ -0,0 +1,98 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#include "simple-streaming-base.hpp"
+
+#include "audio-encoder.hpp"
+
+Napi::Value osn::SimpleStreamingBase::GetAudioEncoder(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("SimpleStreaming", "GetAudioEncoder", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ auto instance = osn::AudioEncoder::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
+ return instance;
+}
+
+Napi::Value osn::SimpleStreamingBase::GetUseAdvanced(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("SimpleStreaming", "GetUseAdvanced", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::Boolean::New(info.Env(), response[1].value_union.ui32);
+}
+
+void osn::SimpleStreamingBase::SetUseAdvanced(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("SimpleStreaming", "SetUseAdvanced", {ipc::value(this->uid), ipc::value(value.ToBoolean().Value())});
+}
+
+Napi::Value osn::SimpleStreamingBase::GetCustomEncSettings(const Napi::CallbackInfo &info)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return info.Env().Undefined();
+
+ std::vector response = conn->call_synchronous_helper("SimpleStreaming", "GetCustomEncSettings", {ipc::value(this->uid)});
+
+ if (!ValidateResponse(info, response))
+ return info.Env().Undefined();
+
+ return Napi::String::New(info.Env(), response[1].value_str.c_str());
+}
+
+void osn::SimpleStreamingBase::SetCustomEncSettings(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call_synchronous_helper("SimpleStreaming", "SetCustomEncSettings", {ipc::value(this->uid), ipc::value(value.ToString().Utf8Value())});
+}
+
+void osn::SimpleStreamingBase::SetAudioEncoder(const Napi::CallbackInfo &info, const Napi::Value &value)
+{
+ osn::AudioEncoder *encoder = Napi::ObjectWrap::Unwrap(value.ToObject());
+
+ if (!encoder) {
+ Napi::TypeError::New(info.Env(), "Invalid encoder argument").ThrowAsJavaScriptException();
+ return;
+ }
+
+ auto conn = GetConnection(info);
+ if (!conn)
+ return;
+
+ conn->call(className, "SetAudioEncoder", {ipc::value(this->uid), ipc::value(encoder->uid)});
+}
diff --git a/obs-studio-server/source/osn-output-signals.hpp b/obs-studio-client/source/simple-streaming-base.hpp
similarity index 56%
rename from obs-studio-server/source/osn-output-signals.hpp
rename to obs-studio-client/source/simple-streaming-base.hpp
index 50da406ed..b92a38463 100644
--- a/obs-studio-server/source/osn-output-signals.hpp
+++ b/obs-studio-client/source/simple-streaming-base.hpp
@@ -17,46 +17,19 @@
******************************************************************************/
#pragma once
-#include
-#include
-#include
-#include
+#include
+#include "streaming.hpp"
namespace osn {
-struct signalInfo {
- std::string signal;
- int code;
- std::string errorMessage;
-};
-
-class OutputSignals {
-public:
- OutputSignals()
- {
- output = nullptr;
- canvas = nullptr;
- }
- virtual ~OutputSignals() {}
+class SimpleStreamingBase : public osn::Streaming {
public:
- std::mutex signalsMtx;
- std::queue signalsReceived;
- std::vector signals;
- obs_output_t *output;
- obs_video_info *canvas;
-
- void ConnectSignals();
-
-public:
- std::condition_variable cvStop;
- std::mutex mtxOutputStop;
- void createOutput(const std::string &type, const std::string &name);
- void deleteOutput();
- void startOutput();
+ Napi::Value GetAudioEncoder(const Napi::CallbackInfo &info);
+ void SetAudioEncoder(const Napi::CallbackInfo &info, const Napi::Value &value);
+ Napi::Value GetUseAdvanced(const Napi::CallbackInfo &info);
+ void SetUseAdvanced(const Napi::CallbackInfo &info, const Napi::Value &value);
+ Napi::Value GetCustomEncSettings(const Napi::CallbackInfo &info);
+ void SetCustomEncSettings(const Napi::CallbackInfo &info, const Napi::Value &value);
};
-struct cbData {
- std::string signal;
- OutputSignals *outputClass;
-};
-}
+}
\ No newline at end of file
diff --git a/obs-studio-client/source/simple-streaming.cpp b/obs-studio-client/source/simple-streaming.cpp
index 8c3e56246..7f5edc455 100644
--- a/obs-studio-client/source/simple-streaming.cpp
+++ b/obs-studio-client/source/simple-streaming.cpp
@@ -115,83 +115,6 @@ void osn::SimpleStreaming::Destroy(const Napi::CallbackInfo &info)
return;
}
-Napi::Value osn::SimpleStreaming::GetAudioEncoder(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("SimpleStreaming", "GetAudioEncoder", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- auto instance = osn::AudioEncoder::constructor.New({Napi::Number::New(info.Env(), static_cast(response[1].value_union.ui64))});
- return instance;
-}
-
-Napi::Value osn::SimpleStreaming::GetUseAdvanced(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("SimpleStreaming", "GetUseAdvanced", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::Boolean::New(info.Env(), response[1].value_union.ui32);
-}
-
-void osn::SimpleStreaming::SetUseAdvanced(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("SimpleStreaming", "SetUseAdvanced", {ipc::value(this->uid), ipc::value(value.ToBoolean().Value())});
-}
-
-Napi::Value osn::SimpleStreaming::GetCustomEncSettings(const Napi::CallbackInfo &info)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return info.Env().Undefined();
-
- std::vector response = conn->call_synchronous_helper("SimpleStreaming", "GetCustomEncSettings", {ipc::value(this->uid)});
-
- if (!ValidateResponse(info, response))
- return info.Env().Undefined();
-
- return Napi::String::New(info.Env(), response[1].value_str.c_str());
-}
-
-void osn::SimpleStreaming::SetCustomEncSettings(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call_synchronous_helper("SimpleStreaming", "SetCustomEncSettings", {ipc::value(this->uid), ipc::value(value.ToString().Utf8Value())});
-}
-
-void osn::SimpleStreaming::SetAudioEncoder(const Napi::CallbackInfo &info, const Napi::Value &value)
-{
- osn::AudioEncoder *encoder = Napi::ObjectWrap::Unwrap(value.ToObject());
-
- if (!encoder) {
- Napi::TypeError::New(info.Env(), "Invalid encoder argument").ThrowAsJavaScriptException();
- return;
- }
-
- auto conn = GetConnection(info);
- if (!conn)
- return;
-
- conn->call(className, "SetAudioEncoder", {ipc::value(this->uid), ipc::value(encoder->uid)});
-}
-
Napi::Value osn::SimpleStreaming::GetLegacySettings(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
diff --git a/obs-studio-client/source/simple-streaming.hpp b/obs-studio-client/source/simple-streaming.hpp
index 95edee1ab..a94bd5861 100644
--- a/obs-studio-client/source/simple-streaming.hpp
+++ b/obs-studio-client/source/simple-streaming.hpp
@@ -18,10 +18,11 @@
#pragma once
#include
-#include "streaming.hpp"
+#include "simple-streaming-base.hpp"
namespace osn {
-class SimpleStreaming : public Napi::ObjectWrap, public osn::Streaming {
+
+class SimpleStreaming : public Napi::ObjectWrap, public SimpleStreamingBase {
public:
static Napi::FunctionReference constructor;
static Napi::Object Init(Napi::Env env, Napi::Object exports);
@@ -30,13 +31,6 @@ class SimpleStreaming : public Napi::ObjectWrap, public os
static Napi::Value Create(const Napi::CallbackInfo &info);
static void Destroy(const Napi::CallbackInfo &info);
- Napi::Value GetAudioEncoder(const Napi::CallbackInfo &info);
- void SetAudioEncoder(const Napi::CallbackInfo &info, const Napi::Value &value);
- Napi::Value GetUseAdvanced(const Napi::CallbackInfo &info);
- void SetUseAdvanced(const Napi::CallbackInfo &info, const Napi::Value &value);
- Napi::Value GetCustomEncSettings(const Napi::CallbackInfo &info);
- void SetCustomEncSettings(const Napi::CallbackInfo &info, const Napi::Value &value);
-
static Napi::Value GetLegacySettings(const Napi::CallbackInfo &info);
static void SetLegacySettings(const Napi::CallbackInfo &info, const Napi::Value &value);
};
diff --git a/obs-studio-client/source/streaming.cpp b/obs-studio-client/source/streaming.cpp
index c51b906a6..86c6c482b 100644
--- a/obs-studio-client/source/streaming.cpp
+++ b/obs-studio-client/source/streaming.cpp
@@ -290,7 +290,8 @@ void osn::Streaming::Start(const Napi::CallbackInfo &info)
startWorker(info.Env(), this->cb.Value(), className, this->uid);
- conn->call(className, "Start", {ipc::value(this->uid)});
+ std::vector response = conn->call_synchronous_helper(className, "Start", {ipc::value(this->uid)});
+ ValidateResponse(info, response);
}
void osn::Streaming::Stop(const Napi::CallbackInfo &info)
diff --git a/obs-studio-server/CMakeLists.txt b/obs-studio-server/CMakeLists.txt
index 3f91439fc..9399093c8 100644
--- a/obs-studio-server/CMakeLists.txt
+++ b/obs-studio-server/CMakeLists.txt
@@ -292,9 +292,11 @@ SET(osn-server_SOURCES
"${PROJECT_SOURCE_DIR}/source/osn-multitrack-video-data-model.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-multitrack-video-output.cpp"
"${PROJECT_SOURCE_DIR}/source/osn-multitrack-video-output.hpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-multitrack-video-system-info.hpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-multitrack-video.cpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-multitrack-video.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-audio-bitrate.cpp"
"${PROJECT_SOURCE_DIR}/source/osn-audio-bitrate.hpp"
- "${PROJECT_SOURCE_DIR}/source/osn-multitrack-video-system-info.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-output.cpp"
"${PROJECT_SOURCE_DIR}/source/osn-output.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-properties.cpp"
@@ -321,6 +323,10 @@ SET(osn-server_SOURCES
"${PROJECT_SOURCE_DIR}/source/osn-simple-streaming.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-advanced-streaming.cpp"
"${PROJECT_SOURCE_DIR}/source/osn-advanced-streaming.hpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-enhanced-broadcasting-advanced-streaming.cpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-enhanced-broadcasting-advanced-streaming.hpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-enhanced-broadcasting-simple-streaming.cpp"
+ "${PROJECT_SOURCE_DIR}/source/osn-enhanced-broadcasting-simple-streaming.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-delay.cpp"
"${PROJECT_SOURCE_DIR}/source/osn-delay.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-reconnect.cpp"
@@ -345,8 +351,6 @@ SET(osn-server_SOURCES
"${PROJECT_SOURCE_DIR}/source/osn-file-output.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-advanced-replay-buffer.cpp"
"${PROJECT_SOURCE_DIR}/source/osn-advanced-replay-buffer.hpp"
- "${PROJECT_SOURCE_DIR}/source/osn-output-signals.cpp"
- "${PROJECT_SOURCE_DIR}/source/osn-output-signals.hpp"
###### utlity graphics ######
"${PROJECT_SOURCE_DIR}/source/gs-limits.h"
diff --git a/obs-studio-server/source/main.cpp b/obs-studio-server/source/main.cpp
index 6e7f7b71b..52d02cbaf 100644
--- a/obs-studio-server/source/main.cpp
+++ b/obs-studio-server/source/main.cpp
@@ -61,6 +61,8 @@
#include "osn-simple-replay-buffer.hpp"
#include "osn-advanced-replay-buffer.hpp"
#include "osn-file-output.hpp"
+#include "osn-enhanced-broadcasting-simple-streaming.hpp"
+#include "osn-enhanced-broadcasting-advanced-streaming.hpp"
#include "util-crashmanager.h"
#include "shared.hpp"
@@ -273,6 +275,8 @@ int main(int argc, char *argv[])
osn::ISimpleReplayBuffer::Register(myServer);
osn::IAdvancedReplayBuffer::Register(myServer);
osn::IFileOutput::Register(myServer);
+ osn::IEnhancedBroadcastingSimpleStreaming::Register(myServer);
+ osn::IEnhancedBroadcastingAdvancedStreaming::Register(myServer);
OBS_API::CreateCrashHandlerExitPipe();
diff --git a/obs-studio-server/source/nodeobs_service.cpp b/obs-studio-server/source/nodeobs_service.cpp
index cbab155e0..e1fa6779b 100644
--- a/obs-studio-server/source/nodeobs_service.cpp
+++ b/obs-studio-server/source/nodeobs_service.cpp
@@ -28,9 +28,7 @@
#include
#include "osn-vcam.hpp"
-#include "osn-multitrack-video-configuration.hpp"
-#include "osn-audio-bitrate.hpp"
-#include "osn-multitrack-video-output.hpp"
+#include "osn-multitrack-video.hpp"
#ifdef __APPLE__
#include
@@ -92,13 +90,7 @@ std::mutex signalMutex;
std::queue outputSignal;
std::thread releaseWorker;
-struct EnhancedBroadcastOutputObjects {
- OBSOutputAutoRelease obsOutput;
- std::shared_ptr videoEncoderGroup;
- std::vector audioEncoders;
- OBSServiceAutoRelease multitrackVideoService;
-};
-static std::optional enhancedBroadcastContext;
+static std::optional enhancedBroadcastContext;
OBS_service::OBS_service() {}
OBS_service::~OBS_service() {}
@@ -1266,18 +1258,6 @@ const char *OBS_service::getStreamOutputType(const obs_service_t *service)
return nullptr;
}
-static int GetAudioBitrate()
-{
- const char *audio_encoder_id = config_get_string(ConfigManager::getInstance().getBasic(), "SimpleOutput", "StreamAudioEncoder");
-
- const int bitrate = (int)config_get_uint(ConfigManager::getInstance().getBasic(), "SimpleOutput", "ABitrate");
-
- if (audio_encoder_id && strcmp(audio_encoder_id, "opus") == 0)
- return osn::FindClosestAvailableSimpleOpusBitrate(bitrate);
-
- return osn::FindClosestAvailableSimpleAACBitrate(bitrate);
-}
-
static inline bool ServiceSupportsVodTrack(const char *service)
{
static const char *vodTrackServices[] = {"Twitch"};
@@ -1307,11 +1287,6 @@ static bool IsVodTrackEnabled(obs_service_t *service)
return vodTrackEnabledAdv && ServiceSupportsVodTrack(name);
}
-static bool IsMultitrackVideoEnabled()
-{
- return config_get_bool(ConfigManager::getInstance().getBasic(), "EnhancedBroadcasting", "EnableMultitrackVideo");
-}
-
bool OBS_service::startSingleTrackStreaming(StreamServiceId serviceId)
{
const char *type = getStreamOutputType(services[serviceId]);
@@ -1398,13 +1373,23 @@ bool OBS_service::startMultiTrackStreaming(StreamServiceId serviceId, bool dualS
auto vod_track_mixer = IsVodTrackEnabled(services[serviceId]) ? std::optional{vodTrackIndex} : std::nullopt;
- auto go_live_post = osn::constructGoLivePost(serviceId, dualStreamingMode, key, std::nullopt, std::nullopt, vod_track_mixer.has_value());
+ std::vector canvases;
+ canvases.push_back(videoInfo[serviceId]);
+ if (dualStreamingMode) {
+ if (serviceId == StreamServiceId::Main) {
+ canvases.push_back(videoInfo[StreamServiceId::Second]);
+ } else if (serviceId == StreamServiceId::Second) {
+ canvases.push_back(videoInfo[StreamServiceId::Main]);
+ }
+ }
+
+ auto go_live_post = osn::constructGoLivePost(canvases, key, std::nullopt, std::nullopt, vod_track_mixer.has_value());
std::optional go_live_config = osn::DownloadGoLiveConfig(auto_config_url, go_live_post);
if (!go_live_config.has_value()) {
throw std::runtime_error("startStreaming - go live config is empty");
}
- const auto audio_bitrate = GetAudioBitrate();
+ const auto audio_bitrate = osn::GetMultitrackAudioBitrate();
const auto audio_encoder_id = osn::GetSimpleAACEncoderForBitrate(audio_bitrate);
std::vector audio_encoders;
@@ -1429,7 +1414,7 @@ bool OBS_service::startMultiTrackStreaming(StreamServiceId serviceId, bool dualS
isStreaming[serviceId] = obs_output_start(output);
- enhancedBroadcastContext.emplace(EnhancedBroadcastOutputObjects{
+ enhancedBroadcastContext.emplace(osn::EnhancedBroadcastOutputObjects{
std::move(output),
video_encoder_group,
std::move(audio_encoders),
@@ -1447,7 +1432,7 @@ bool OBS_service::startStreaming(StreamServiceId serviceId, bool dualStreamingMo
}
try {
- if (isTwitchStream(serviceId) && (IsMultitrackVideoEnabled() || dualStreamingMode)) {
+ if (isTwitchStream(serviceId) && (osn::IsMultitrackVideoEnabled() || dualStreamingMode)) {
return startMultiTrackStreaming(serviceId, dualStreamingMode);
}
@@ -1634,7 +1619,7 @@ bool OBS_service::updateRecordingEncoders(bool isSimpleMode, StreamServiceId ser
bool simpleUsesStream = false;
bool advancedUsesStream = false;
- if (!IsMultitrackVideoEnabled()) {
+ if (!osn::IsMultitrackVideoEnabled()) {
simpleUsesStream = isSimpleMode && simpleQuality.compare("Stream") == 0;
advancedUsesStream = !isSimpleMode && (advancedQuality.compare("") == 0 || advancedQuality.compare("none") == 0);
}
@@ -1766,7 +1751,7 @@ void OBS_service::stopStreaming(bool forceStop, StreamServiceId serviceId)
obs_output_stop(streamingOutput[serviceId]);
/* Unregister the BPM (Broadcast Performance Metrics) callback and destroy the allocated metrics data. */
- if (isTwitchStream(serviceId) && IsMultitrackVideoEnabled()) {
+ if (isTwitchStream(serviceId) && osn::IsMultitrackVideoEnabled()) {
obs_output_remove_packet_callback(streamingOutput[serviceId], bpm_inject, NULL);
bpm_destroy(streamingOutput[serviceId]);
}
diff --git a/obs-studio-server/source/osn-advanced-recording.cpp b/obs-studio-server/source/osn-advanced-recording.cpp
index a4a949849..beb1d3f6b 100644
--- a/obs-studio-server/source/osn-advanced-recording.cpp
+++ b/obs-studio-server/source/osn-advanced-recording.cpp
@@ -186,9 +186,9 @@ bool osn::AdvancedRecording::UpdateEncoders()
return false;
if (obs_get_multiple_rendering()) {
- obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(canvas, OBS_RECORDING_VIDEO_RENDERING));
+ obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(this->GetCanvas(), OBS_RECORDING_VIDEO_RENDERING));
} else {
- obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(canvas, OBS_MAIN_VIDEO_RENDERING));
+ obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(this->GetCanvas(), OBS_MAIN_VIDEO_RENDERING));
}
return true;
@@ -201,10 +201,10 @@ void osn::IAdvancedRecording::Start(void *data, const int64_t id, const std::vec
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Simple recording reference is not valid.");
}
- if (!recording->output)
- recording->createOutput("ffmpeg_muxer", "recording");
+ if (!recording->GetOutput())
+ recording->CreateOutput("ffmpeg_muxer", "recording");
- if (!recording->output) {
+ if (!recording->GetOutput()) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Error while creating the recording output.");
}
@@ -213,9 +213,9 @@ void osn::IAdvancedRecording::Start(void *data, const int64_t id, const std::vec
osn::AudioTrack *audioTrack = osn::IAudioTrack::audioTracks[i];
if ((recording->mixer & (1 << i)) != 0 && audioTrack && audioTrack->audioEnc) {
obs_encoder_set_audio(audioTrack->audioEnc, obs_get_audio());
- obs_output_set_audio_encoder(recording->output, audioTrack->audioEnc, idx);
+ obs_output_set_audio_encoder(recording->GetOutput(), audioTrack->audioEnc, idx);
- obs_encoder_set_video_mix(audioTrack->audioEnc, obs_video_mix_get(recording->canvas, OBS_RECORDING_VIDEO_RENDERING));
+ obs_encoder_set_video_mix(audioTrack->audioEnc, obs_video_mix_get(recording->GetCanvas(), OBS_RECORDING_VIDEO_RENDERING));
idx++;
}
}
@@ -224,7 +224,7 @@ void osn::IAdvancedRecording::Start(void *data, const int64_t id, const std::vec
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid video encoder.");
}
- obs_output_set_video_encoder(recording->output, recording->videoEncoder);
+ obs_output_set_video_encoder(recording->GetOutput(), recording->videoEncoder);
std::string path = recording->path;
@@ -232,8 +232,8 @@ void osn::IAdvancedRecording::Start(void *data, const int64_t id, const std::vec
if (lastChar != '/' && lastChar != '\\')
path += "/";
- path += GenerateSpecifiedFilename(recording->format, recording->noSpace, recording->fileFormat, recording->canvas->base_width,
- recording->canvas->base_height);
+ path += GenerateSpecifiedFilename(recording->format, recording->noSpace, recording->fileFormat, recording->GetCanvas()->base_width,
+ recording->GetCanvas()->base_height);
if (!recording->overwrite)
FindBestFilename(path, recording->noSpace);
@@ -241,13 +241,13 @@ void osn::IAdvancedRecording::Start(void *data, const int64_t id, const std::vec
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "path", path.c_str());
obs_data_set_string(settings, "muxer_settings", recording->muxerSettings.c_str());
- obs_output_update(recording->output, settings);
+ obs_output_update(recording->GetOutput(), settings);
obs_data_release(settings);
if (recording->enableFileSplit)
recording->ConfigureRecFileSplitting();
- recording->startOutput();
+ recording->StartOutput();
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
@@ -260,7 +260,7 @@ void osn::IAdvancedRecording::Stop(void *data, const int64_t id, const std::vect
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Simple recording reference is not valid.");
}
- obs_output_stop(recording->output);
+ obs_output_stop(recording->GetOutput());
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
diff --git a/obs-studio-server/source/osn-advanced-replay-buffer.cpp b/obs-studio-server/source/osn-advanced-replay-buffer.cpp
index 1d8a7ee5d..79439f2ea 100644
--- a/obs-studio-server/source/osn-advanced-replay-buffer.cpp
+++ b/obs-studio-server/source/osn-advanced-replay-buffer.cpp
@@ -123,15 +123,15 @@ void osn::IAdvancedReplayBuffer::Start(void *data, const int64_t id, const std::
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Simple replay buffer reference is not valid.");
}
- if (!replayBuffer->output)
- replayBuffer->createOutput("replay_buffer", "replay-buffer");
+ if (!replayBuffer->GetOutput())
+ replayBuffer->CreateOutput("replay_buffer", "replay-buffer");
int idx = 0;
for (int i = 0; i < MAX_AUDIO_MIXES; i++) {
osn::AudioTrack *audioTrack = osn::IAudioTrack::audioTracks[i];
if ((replayBuffer->mixer & (1 << i)) != 0 && audioTrack && audioTrack->audioEnc) {
obs_encoder_set_audio(audioTrack->audioEnc, obs_get_audio());
- obs_output_set_audio_encoder(replayBuffer->output, audioTrack->audioEnc, idx);
+ obs_output_set_audio_encoder(replayBuffer->GetOutput(), audioTrack->audioEnc, idx);
idx++;
}
}
@@ -154,7 +154,7 @@ void osn::IAdvancedReplayBuffer::Start(void *data, const int64_t id, const std::
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid video encoder.");
}
- obs_output_set_video_encoder(replayBuffer->output, videoEncoder);
+ obs_output_set_video_encoder(replayBuffer->GetOutput(), videoEncoder);
if (!replayBuffer->path.size()) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid recording path.");
@@ -185,10 +185,10 @@ void osn::IAdvancedReplayBuffer::Start(void *data, const int64_t id, const std::
obs_data_set_bool(settings, "allow_spaces", !replayBuffer->noSpace);
obs_data_set_int(settings, "max_time_sec", replayBuffer->duration);
obs_data_set_int(settings, "max_size_mb", rbSize);
- obs_output_update(replayBuffer->output, settings);
+ obs_output_update(replayBuffer->GetOutput(), settings);
obs_data_release(settings);
- replayBuffer->startOutput();
+ replayBuffer->StartOutput();
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
@@ -200,11 +200,11 @@ void osn::IAdvancedReplayBuffer::Stop(void *data, const int64_t id, const std::v
if (!replayBuffer) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Simple replay buffer reference is not valid.");
}
- if (!replayBuffer->output) {
+ if (!replayBuffer->GetOutput()) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid replay buffer output.");
}
- obs_output_stop(replayBuffer->output);
+ obs_output_stop(replayBuffer->GetOutput());
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
diff --git a/obs-studio-server/source/osn-advanced-streaming.cpp b/obs-studio-server/source/osn-advanced-streaming.cpp
index 265ac9d49..e01fc209d 100644
--- a/obs-studio-server/source/osn-advanced-streaming.cpp
+++ b/obs-studio-server/source/osn-advanced-streaming.cpp
@@ -241,8 +241,8 @@ static bool setAudioEncoder(osn::AdvancedStreaming *streaming)
return false;
obs_encoder_set_audio(audioTrack->audioEnc, obs_get_audio());
- obs_output_set_audio_encoder(streaming->output, audioTrack->audioEnc, 0);
- obs_encoder_set_video_mix(audioTrack->audioEnc, obs_video_mix_get(streaming->canvas, OBS_STREAMING_VIDEO_RENDERING));
+ obs_output_set_audio_encoder(streaming->GetOutput(), audioTrack->audioEnc, 0);
+ obs_encoder_set_video_mix(audioTrack->audioEnc, obs_video_mix_get(streaming->GetCanvas(), OBS_STREAMING_VIDEO_RENDERING));
return true;
}
@@ -289,8 +289,8 @@ static void SetupTwitchSoundtrackAudio(osn::AdvancedStreaming *streaming)
obs_encoder_set_audio(streaming->streamArchive, obs_get_audio());
}
- obs_output_set_audio_encoder(streaming->output, streaming->streamArchive, kSoundtrackArchiveEncoderIdx);
- obs_encoder_set_video_mix(streaming->streamArchive, obs_video_mix_get(streaming->canvas, OBS_STREAMING_VIDEO_RENDERING));
+ obs_output_set_audio_encoder(streaming->GetOutput(), streaming->streamArchive, kSoundtrackArchiveEncoderIdx);
+ obs_encoder_set_video_mix(streaming->streamArchive, obs_video_mix_get(streaming->GetCanvas(), OBS_STREAMING_VIDEO_RENDERING));
osn::AudioTrack *audioTrack = osn::IAudioTrack::audioTracks[streaming->twitchTrack];
if (!audioTrack)
@@ -356,9 +356,9 @@ void osn::AdvancedStreaming::UpdateEncoders()
obs_data_release(settings);
if (obs_get_multiple_rendering()) {
- obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(canvas, OBS_STREAMING_VIDEO_RENDERING));
+ obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(this->GetCanvas(), OBS_STREAMING_VIDEO_RENDERING));
} else {
- obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(canvas, OBS_MAIN_VIDEO_RENDERING));
+ obs_encoder_set_video_mix(videoEncoder, obs_video_mix_get(this->GetCanvas(), OBS_MAIN_VIDEO_RENDERING));
}
}
@@ -366,34 +366,34 @@ void osn::IAdvancedStreaming::Start(void *data, const int64_t id, const std::vec
{
AdvancedStreaming *streaming = static_cast(osn::IAdvancedStreaming::Manager::GetInstance().find(args[0].value_union.ui64));
if (!streaming) {
- PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Simple streaming reference is not valid.");
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Advanced streaming reference is not valid.");
+ }
+
+ if (!streaming->service) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid service.");
}
if (!streaming->videoEncoder) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid video encoder.");
}
- streaming->UpdateEncoders();
-
- if (!streaming->service) {
- PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid service.");
+ if (!streaming->GetCanvas()) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid main canvas.");
}
+ streaming->UpdateEncoders();
+
const char *type = OBS_service::getStreamOutputType(streaming->service);
if (!type)
type = "rtmp_output";
- if (!streaming->output || strcmp(obs_output_get_id(streaming->output), type) != 0)
- streaming->createOutput(type, "stream");
+ if (!streaming->GetOutput() || strcmp(obs_output_get_id(streaming->GetOutput()), type) != 0)
+ streaming->CreateOutput(type, "stream");
- if (!streaming->output) {
+ if (!streaming->GetOutput()) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Error while creating the streaming output.");
}
- if (!streaming->videoEncoder) {
- PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Error while creating the video encoder.");
- }
-
if (!setAudioEncoder(streaming)) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Error while creating the audio encoder.");
}
@@ -401,7 +401,7 @@ void osn::IAdvancedStreaming::Start(void *data, const int64_t id, const std::vec
if (streaming->rescaling)
obs_encoder_set_scaled_size(streaming->videoEncoder, streaming->outputWidth, streaming->outputHeight);
- obs_output_set_video_encoder(streaming->output, streaming->videoEncoder);
+ obs_output_set_video_encoder(streaming->GetOutput(), streaming->videoEncoder);
if (streaming->enableTwitchVOD) {
streaming->twitchVODSupported = streaming->isTwitchVODSupported();
@@ -409,19 +409,19 @@ void osn::IAdvancedStreaming::Start(void *data, const int64_t id, const std::vec
SetupTwitchSoundtrackAudio(streaming);
}
- obs_output_set_service(streaming->output, streaming->service);
+ obs_output_set_service(streaming->GetOutput(), streaming->service);
if (!streaming->delay) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid delay.");
}
- obs_output_set_delay(streaming->output, streaming->delay->enabled ? uint32_t(streaming->delay->delaySec) : 0,
+ obs_output_set_delay(streaming->GetOutput(), streaming->delay->enabled ? uint32_t(streaming->delay->delaySec) : 0,
streaming->delay->preserveDelay ? OBS_OUTPUT_DELAY_PRESERVE : 0);
if (!streaming->reconnect) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid reconnect.");
}
uint32_t maxReties = streaming->reconnect->enabled ? streaming->reconnect->maxRetries : 0;
- obs_output_set_reconnect_settings(streaming->output, maxReties, streaming->reconnect->retryDelay);
+ obs_output_set_reconnect_settings(streaming->GetOutput(), maxReties, streaming->reconnect->retryDelay);
if (!streaming->network) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid network.");
@@ -432,10 +432,10 @@ void osn::IAdvancedStreaming::Start(void *data, const int64_t id, const std::vec
obs_data_set_bool(settings, "dyn_bitrate", streaming->network->enableDynamicBitrate);
obs_data_set_bool(settings, "new_socket_loop_enabled", streaming->network->enableOptimizations);
obs_data_set_bool(settings, "low_latency_mode_enabled", streaming->network->enableLowLatency);
- obs_output_update(streaming->output, settings);
+ obs_output_update(streaming->GetOutput(), settings);
obs_data_release(settings);
- streaming->startOutput();
+ streaming->StartOutput();
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
@@ -443,21 +443,22 @@ void osn::IAdvancedStreaming::Start(void *data, const int64_t id, const std::vec
void osn::IAdvancedStreaming::Stop(void *data, const int64_t id, const std::vector &args, std::vector &rval)
{
+ blog(LOG_INFO, "IAdvancedStreaming::Stop");
Streaming *streaming = osn::IStreaming::Manager::GetInstance().find(args[0].value_union.ui64);
if (!streaming) {
- PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Simple streaming reference is not valid.");
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Streaming reference is not valid.");
}
- if (!streaming->output) {
+ if (!streaming->GetOutput()) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid streaming output.");
}
bool force = args[1].value_union.ui32;
if (force)
- obs_output_force_stop(streaming->output);
+ obs_output_force_stop(streaming->GetOutput());
else
- obs_output_stop(streaming->output);
+ obs_output_stop(streaming->GetOutput());
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
diff --git a/obs-studio-server/source/osn-enhanced-broadcasting-advanced-streaming.cpp b/obs-studio-server/source/osn-enhanced-broadcasting-advanced-streaming.cpp
new file mode 100644
index 000000000..ec5e3e202
--- /dev/null
+++ b/obs-studio-server/source/osn-enhanced-broadcasting-advanced-streaming.cpp
@@ -0,0 +1,177 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#include "osn-enhanced-broadcasting-advanced-streaming.hpp"
+#include "osn-video-encoder.hpp"
+#include "osn-service.hpp"
+#include "osn-error.hpp"
+#include "shared.hpp"
+#include "nodeobs_audio_encoders.h"
+#include "osn-audio-track.hpp"
+#include
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::Register(ipc::server &srv)
+{
+ std::shared_ptr cls = std::make_shared("EnhancedBroadcastingAdvancedStreaming");
+ cls->register_function(std::make_shared("Create", std::vector{}, Create));
+ cls->register_function(std::make_shared("Destroy", std::vector{ipc::type::UInt64}, Destroy));
+ cls->register_function(std::make_shared("GetService", std::vector{ipc::type::UInt64}, GetService));
+ cls->register_function(std::make_shared("SetService", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetService));
+ cls->register_function(std::make_shared("GetVideoEncoder", std::vector{ipc::type::UInt64}, GetVideoEncoder));
+ cls->register_function(
+ std::make_shared("SetVideoEncoder", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetVideoEncoder));
+ cls->register_function(std::make_shared("GetVideoCanvas", std::vector{ipc::type::UInt64}, GetVideoCanvas));
+ cls->register_function(std::make_shared("SetVideoCanvas", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetVideoCanvas));
+ cls->register_function(std::make_shared("GetEnforceServiceBirate", std::vector{ipc::type::UInt64}, GetEnforceServiceBirate));
+ cls->register_function(std::make_shared("SetEnforceServiceBirate", std::vector{ipc::type::UInt64, ipc::type::UInt32},
+ SetEnforceServiceBirate));
+ cls->register_function(std::make_shared("GetEnableTwitchVOD", std::vector{ipc::type::UInt64}, GetEnableTwitchVOD));
+ cls->register_function(
+ std::make_shared("SetEnableTwitchVOD", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetEnableTwitchVOD));
+ cls->register_function(std::make_shared("GetAudioTrack", std::vector{ipc::type::UInt64}, GetAudioTrack));
+ cls->register_function(std::make_shared("SetAudioTrack", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetAudioTrack));
+ cls->register_function(std::make_shared("GetTwitchTrack", std::vector{ipc::type::UInt64}, GetTwitchTrack));
+ cls->register_function(std::make_shared("SetTwitchTrack", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetTwitchTrack));
+ cls->register_function(std::make_shared("GetRescaling", std::vector{ipc::type::UInt64}, GetRescaling));
+ cls->register_function(std::make_shared("SetRescaling", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetRescaling));
+ cls->register_function(std::make_shared("GetOutputWidth", std::vector{ipc::type::UInt64}, GetOutputWidth));
+ cls->register_function(std::make_shared("SetOutputWidth", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetOutputWidth));
+ cls->register_function(std::make_shared("GetOutputHeight", std::vector{ipc::type::UInt64}, GetOutputHeight));
+ cls->register_function(
+ std::make_shared("SetOutputHeight", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetOutputHeight));
+ cls->register_function(std::make_shared("GetDelay", std::vector{ipc::type::UInt64}, GetDelay));
+ cls->register_function(std::make_shared("SetDelay", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetDelay));
+ cls->register_function(std::make_shared("GetReconnect", std::vector{ipc::type::UInt64}, GetReconnect));
+ cls->register_function(std::make_shared("SetReconnect", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetReconnect));
+ cls->register_function(std::make_shared("GetNetwork", std::vector{ipc::type::UInt64}, GetNetwork));
+ cls->register_function(std::make_shared("SetNetwork", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetNetwork));
+ cls->register_function(std::make_shared("Start", std::vector{ipc::type::UInt64}, Start));
+ cls->register_function(std::make_shared("Stop", std::vector{ipc::type::UInt64, ipc::type::UInt32}, Stop));
+ cls->register_function(std::make_shared("Query", std::vector{ipc::type::UInt64}, Query));
+ cls->register_function(std::make_shared("GetLegacySettings", std::vector{}, GetLegacySettings));
+ cls->register_function(std::make_shared("SetLegacySettings", std::vector{ipc::type::UInt64}, SetLegacySettings));
+ cls->register_function(std::make_shared("GetDroppedFrames", std::vector{ipc::type::UInt64}, GetDroppedFrames));
+ cls->register_function(std::make_shared("GetTotalFrames", std::vector{ipc::type::UInt64}, GetTotalFrames));
+ cls->register_function(std::make_shared("GetKBitsPerSec", std::vector{ipc::type::UInt64}, GetKBitsPerSec));
+ cls->register_function(std::make_shared("GetDataOutput", std::vector{ipc::type::UInt64}, GetDataOutput));
+
+ cls->register_function(
+ std::make_shared("GetAdditionalVideoCanvas", std::vector{ipc::type::UInt64}, GetAdditionalVideoCanvas));
+ cls->register_function(std::make_shared("SetAdditionalVideoCanvas", std::vector{ipc::type::UInt64, ipc::type::UInt64},
+ SetAdditionalVideoCanvas));
+
+ srv.register_collection(cls);
+}
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::Create(void *data, const int64_t id, const std::vector &args, std::vector &rval)
+{
+ uint64_t uid = osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().allocate(new EnhancedBroadcastingAdvancedStreaming());
+ if (uid == UINT64_MAX) {
+ PRETTY_ERROR_RETURN(ErrorCode::CriticalError, "Index list is full.");
+ }
+
+ rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
+ rval.push_back(ipc::value(uid));
+ AUTO_DEBUG;
+}
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::Destroy(void *data, const int64_t id, const std::vector &args, std::vector &rval)
+{
+ EnhancedBroadcastingAdvancedStreaming *streaming = static_cast(
+ osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().find(args[0].value_union.ui64));
+ if (!streaming) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Streaming reference is not valid.");
+ }
+
+ osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().free(streaming);
+ delete streaming;
+
+ rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
+ AUTO_DEBUG;
+}
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::Start(void *data, const int64_t id, const std::vector &args, std::vector &rval)
+{
+ EnhancedBroadcastingAdvancedStreaming *streaming = static_cast(
+ osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().find(args[0].value_union.ui64));
+ if (!streaming) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Streaming reference is not valid.");
+ }
+
+ if (!streaming->service) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid service.");
+ }
+
+ auto vod_track_mixer = (streaming->twitchVODSupported && streaming->enableTwitchVOD) ? std::optional{streaming->twitchTrack} : std::nullopt;
+ streaming->StartEnhancedBroadcastingStream(vod_track_mixer);
+
+ rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
+ AUTO_DEBUG;
+}
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::Stop(void *data, const int64_t id, const std::vector &args, std::vector &rval)
+{
+ EnhancedBroadcastingAdvancedStreaming *streaming = static_cast(
+ osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().find(args[0].value_union.ui64));
+ if (!streaming) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Streaming reference is not valid.");
+ }
+
+ streaming->StopEnhancedBroadcastingStream();
+
+ IAdvancedStreaming::Stop(data, id, args, rval);
+
+ AUTO_DEBUG;
+}
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::GetAdditionalVideoCanvas(void *data, const int64_t id, const std::vector &args,
+ std::vector &rval)
+{
+ EnhancedBroadcastingAdvancedStreaming *streaming = static_cast(
+ osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().find(args[0].value_union.ui64));
+ if (!streaming) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Streaming reference is not valid.");
+ }
+
+ const uint64_t uid = osn::Video::Manager::GetInstance().find(streaming->GetAdditionalVideoCanvas());
+
+ rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
+ rval.push_back(ipc::value(uid));
+
+ AUTO_DEBUG;
+}
+
+void osn::IEnhancedBroadcastingAdvancedStreaming::SetAdditionalVideoCanvas(void *data, const int64_t id, const std::vector &args,
+ std::vector &rval)
+{
+ EnhancedBroadcastingAdvancedStreaming *streaming = static_cast(
+ osn::IEnhancedBroadcastingAdvancedStreaming::Manager::GetInstance().find(args[0].value_union.ui64));
+ if (!streaming) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Streaming reference is not valid.");
+ }
+
+ obs_video_info *canvas = osn::Video::Manager::GetInstance().find(args[1].value_union.ui64);
+ if (!canvas) {
+ PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Canvas reference is not valid.");
+ }
+
+ streaming->SetAdditionalVideoCanvas(canvas);
+
+ rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
+ AUTO_DEBUG;
+}
diff --git a/obs-studio-server/source/osn-enhanced-broadcasting-advanced-streaming.hpp b/obs-studio-server/source/osn-enhanced-broadcasting-advanced-streaming.hpp
new file mode 100644
index 000000000..b5400dc39
--- /dev/null
+++ b/obs-studio-server/source/osn-enhanced-broadcasting-advanced-streaming.hpp
@@ -0,0 +1,54 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#pragma once
+#include
+#include "utility.hpp"
+#include "osn-delay.hpp"
+#include "osn-advanced-streaming.hpp"
+#include "osn-reconnect.hpp"
+#include "osn-network.hpp"
+#include "osn-output.hpp"
+#include "osn-video-encoder.hpp"
+#include "osn-multitrack-video.hpp"
+#include "osn-enhanced-broadcasting.hpp"
+
+#include "nodeobs_configManager.hpp"
+
+namespace osn {
+
+class EnhancedBroadcastingAdvancedStreaming : public EnhancedBroadcasting {
+public:
+ EnhancedBroadcastingAdvancedStreaming() : EnhancedBroadcasting() {}
+ ~EnhancedBroadcastingAdvancedStreaming() {}
+};
+
+class IEnhancedBroadcastingAdvancedStreaming : public IAdvancedStreaming {
+public:
+ static void Register(ipc::server &);
+
+ static void Create(void *data, const int64_t id, const std::vector &args, std::vector &rval);
+ static void Destroy(void *data, const int64_t id, const std::vector &args, std::vector &rval);
+
+ static void Start(void *data, const int64_t id, const std::vector &args, std::vector &rval);
+ static void Stop(void *data, const int64_t id, const std::vector &args, std::vector &rval);
+
+ static void GetAdditionalVideoCanvas(void *data, const int64_t id, const std::vector &args, std::vector &rval);
+ static void SetAdditionalVideoCanvas(void *data, const int64_t id, const std::vector &args, std::vector &rval);
+};
+}
diff --git a/obs-studio-server/source/osn-enhanced-broadcasting-simple-streaming.cpp b/obs-studio-server/source/osn-enhanced-broadcasting-simple-streaming.cpp
new file mode 100644
index 000000000..681470add
--- /dev/null
+++ b/obs-studio-server/source/osn-enhanced-broadcasting-simple-streaming.cpp
@@ -0,0 +1,174 @@
+/******************************************************************************
+ Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+******************************************************************************/
+
+#include "osn-enhanced-broadcasting-simple-streaming.hpp"
+#include "osn-video-encoder.hpp"
+#include "osn-service.hpp"
+#include "osn-error.hpp"
+#include "shared.hpp"
+#include "nodeobs_audio_encoders.h"
+#include "osn-audio-track.hpp"
+#include
+
+void osn::IEnhancedBroadcastingSimpleStreaming::Register(ipc::server &srv)
+{
+ std::shared_ptr cls = std::make_shared("EnhancedBroadcastingSimpleStreaming");
+ cls->register_function(std::make_shared("Create", std::vector{}, Create));
+ cls->register_function(std::make_shared("Destroy", std::vector{ipc::type::UInt64}, Destroy));
+ cls->register_function(std::make_shared("GetService", std::vector{ipc::type::UInt64}, GetService));
+ cls->register_function(std::make_shared("SetService", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetService));
+ cls->register_function(std::make_shared("GetVideoEncoder", std::vector{ipc::type::UInt64}, GetVideoEncoder));
+ cls->register_function(
+ std::make_shared("SetVideoEncoder", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetVideoEncoder));
+ cls->register_function(std::make_shared("GetVideoCanvas", std::vector{ipc::type::UInt64}, GetVideoCanvas));
+ cls->register_function(std::make_shared("SetVideoCanvas", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetVideoCanvas));
+ cls->register_function(std::make_shared("GetAudioEncoder", std::vector{ipc::type::UInt64}, GetAudioEncoder));
+ cls->register_function(
+ std::make_shared("SetAudioEncoder", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetAudioEncoder));
+ cls->register_function(std::make_shared("GetUseAdvanced", std::vector{ipc::type::UInt64}, GetUseAdvanced));
+ cls->register_function(std::make_shared("SetUseAdvanced", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetUseAdvanced));
+ cls->register_function(std::make_shared("GetCustomEncSettings", std::vector{ipc::type::UInt64}, GetCustomEncSettings));
+ cls->register_function(
+ std::make_shared("SetCustomEncSettings", std::vector{ipc::type::UInt64, ipc::type::String}, SetCustomEncSettings));
+ cls->register_function(std::make_shared("GetEnforceServiceBirate", std::vector{ipc::type::UInt64}, GetEnforceServiceBirate));
+ cls->register_function(std::make_shared("SetEnforceServiceBirate", std::vector{ipc::type::UInt64, ipc::type::UInt32},
+ SetEnforceServiceBirate));
+ cls->register_function(std::make_shared("GetEnableTwitchVOD", std::vector{ipc::type::UInt64}, GetEnableTwitchVOD));
+ cls->register_function(
+ std::make_shared("SetEnableTwitchVOD", std::vector{ipc::type::UInt64, ipc::type::UInt32}, SetEnableTwitchVOD));
+ cls->register_function(std::make_shared("GetDelay", std::vector{ipc::type::UInt64}, GetDelay));
+ cls->register_function(std::make_shared("SetDelay", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetDelay));
+ cls->register_function(std::make_shared("GetReconnect", std::vector{ipc::type::UInt64}, GetReconnect));
+ cls->register_function(std::make_shared("SetReconnect", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetReconnect));
+ cls->register_function(std::make_shared("GetNetwork", std::vector{ipc::type::UInt64}, GetNetwork));
+ cls->register_function(std::make_shared("SetNetwork", std::vector{ipc::type::UInt64, ipc::type::UInt64}, SetNetwork));
+ cls->register_function(std::make_shared("Start", std::vector{ipc::type::UInt64}, Start));
+ cls->register_function(std::make_shared("Stop", std::vector{ipc::type::UInt64, ipc::type::UInt32}, Stop));
+ cls->register_function(std::make_shared("Query", std::vector{ipc::type::UInt64}, Query));
+ cls->register_function(std::make_shared("GetLegacySettings", std::vector{}, GetLegacySettings));
+ cls->register_function(std::make_shared("SetLegacySettings", std::vector{ipc::type::UInt64}, SetLegacySettings));
+ cls->register_function(std::make_shared("GetDroppedFrames", std::vector{ipc::type::UInt64}, GetDroppedFrames));
+ cls->register_function(std::make_shared