Skip to content

Commit fa74915

Browse files
Implemented enhanced broadcasting for the simple and advanced modes for the new API
1 parent 4d9b385 commit fa74915

File tree

8 files changed

+110
-85
lines changed

8 files changed

+110
-85
lines changed

js/module.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,8 @@ export interface IVideoEncoderFactory {
794794
create(id: string, name: string, settings?: ISettings): IVideoEncoder;
795795
}
796796
export interface IStreaming {
797-
videoEncoder: IVideoEncoder;
797+
// Video encoder value is ignored when enhancedBroadcasting === true
798+
videoEncoder?: IVideoEncoder;
798799
service: IService;
799800
enforceServiceBitrate: boolean;
800801
enableTwitchVOD: boolean;

js/module.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,12 +581,12 @@ export interface IGlobal {
581581
readonly version: number;
582582

583583
/**
584-
* Percentage of CPU being used
584+
* Percentage of CPU being used
585585
*/
586586
readonly cpuPercentage: number;
587587

588588
/**
589-
* Current FPS
589+
* Current FPS
590590
*/
591591
readonly currentFrameRate: number;
592592

@@ -601,7 +601,7 @@ export interface IGlobal {
601601
readonly diskSpaceAvailable: number;
602602

603603
/**
604-
* Current memory usage
604+
* Current memory usage
605605
*/
606606
readonly memoryUsage: number;
607607
}
@@ -1705,7 +1705,8 @@ export interface IVideoEncoderFactory {
17051705
}
17061706

17071707
export interface IStreaming {
1708-
videoEncoder: IVideoEncoder,
1708+
// Video encoder value is ignored when enhancedBroadcasting === true
1709+
videoEncoder?: IVideoEncoder,
17091710
service: IService,
17101711
enforceServiceBitrate: boolean,
17111712
enableTwitchVOD: boolean,

obs-studio-server/source/osn-advanced-streaming.cpp

Lines changed: 5 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -379,83 +379,13 @@ void osn::IAdvancedStreaming::Start(void *data, const int64_t id, const std::vec
379379
}
380380

381381
if (streaming->enhancedBroadcasting) {
382-
const bool dualStreamingMode = true;
383-
384-
blog(LOG_INFO, "osn::IAdvancedStreaming::Start - service id: %s", obs_service_get_id(streaming->service));
385-
386-
const bool is_custom = strncmp("rtmp_custom", obs_service_get_type(streaming->service), 11) == 0;
387-
388-
OBSDataAutoRelease settings = obs_service_get_settings(streaming->service);
389-
std::string key = obs_data_get_string(settings, "key");
390-
391-
const char *service_name = "<unknown>";
392-
if (is_custom && obs_data_has_user_value(settings, "service_name")) {
393-
service_name = obs_data_get_string(settings, "service_name");
394-
} else if (!is_custom) {
395-
service_name = obs_data_get_string(settings, "service");
396-
}
397-
398-
std::optional<std::string> custom_rtmp_url;
399-
auto server = obs_data_get_string(settings, "server");
400-
if (strcmp(server, "auto") != 0) {
401-
custom_rtmp_url = server;
402-
}
403-
404-
auto service_custom_server = obs_data_get_bool(settings, "using_custom_server");
405-
if (custom_rtmp_url.has_value()) {
406-
blog(LOG_INFO, "Using %sserver '%s'", service_custom_server ? "custom " : "", custom_rtmp_url->c_str());
407-
}
408-
409-
auto auto_config_url = osn::MultitrackVideoAutoConfigURL(streaming->service);
410-
blog(LOG_INFO, "Auto config URL: %s", auto_config_url.c_str());
411-
412-
// TODO: !!!!!!!!!!!!!!!! VOD track index from options instead of global config??????????????????????????????????????????????????????
413-
const auto vodTrackIndex = int(config_get_int(ConfigManager::getInstance().getBasic(), "AdvOut", "VodTrackIndex")) - 1;
414-
blog(LOG_INFO, "vodTrackIndex: %d", vodTrackIndex);
415-
416-
auto vod_track_mixer = streaming->enableTwitchVOD ? std::optional{vodTrackIndex} : std::nullopt;
417-
418-
auto go_live_post = osn::constructGoLivePost(StreamServiceId::Main, dualStreamingMode, key, std::nullopt, std::nullopt, vod_track_mixer.has_value());
419-
std::optional<osn::Config> go_live_config = osn::DownloadGoLiveConfig(auto_config_url, go_live_post);
420-
if (!go_live_config.has_value()) {
421-
throw std::runtime_error("startStreaming - go live config is empty");
422-
}
423-
424-
const auto audio_bitrate = osn::GetMultitrackAudioBitrate();
425-
const auto audio_encoder_id = osn::GetSimpleAACEncoderForBitrate(audio_bitrate);
426-
427-
std::vector<OBSEncoderAutoRelease> audio_encoders;
428-
std::shared_ptr<obs_encoder_group_t> video_encoder_group;
429-
auto output =
430-
osn::SetupOBSOutput("Enhanced Broadcasting", go_live_config.value(), audio_encoders, video_encoder_group, audio_encoder_id, 0, vod_track_mixer);
431-
if (!output) {
432-
throw std::runtime_error("startStreaming - failed to create multitrack output");
433-
}
434-
435-
auto multitrack_video_service = osn::create_service(*go_live_config, std::nullopt, ""); // Stream key is defined by config from Twitch
436-
if (!multitrack_video_service) {
437-
throw std::runtime_error("startStreaming - failed to create multitrack video service");
438-
}
439-
440-
streaming->SetOutput(output.Get());
441-
obs_output_set_service(output, multitrack_video_service);
442-
443-
// Register the BPM (Broadcast Performance Metrics) callback
444-
obs_output_add_packet_callback(output, bpm_inject, NULL);
445-
446-
streaming->StartOutput();
447-
448-
streaming->enhancedBroadcastContext.emplace(EnhancedBroadcastOutputObjects{
449-
std::move(output),
450-
video_encoder_group,
451-
std::move(audio_encoders),
452-
std::move(multitrack_video_service),
453-
});
382+
auto vod_track_mixer = (streaming->twitchVODSupported && streaming->enableTwitchVOD) ?
383+
std::optional{streaming->twitchTrack} :
384+
std::nullopt;
385+
streaming->StartEnhancedBroadcastingStream(vod_track_mixer);
386+
return;
454387
}
455388

456-
// TODO: enhanced broadcasting case
457-
return;
458-
459389
if (!streaming->videoEncoder) {
460390
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid video encoder.");
461391
}

obs-studio-server/source/osn-output.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ void osn::Output::DeleteOutput()
7171
if (!m_output)
7272
return;
7373

74+
blog(LOG_INFO, "osn::Output::DeleteOutput");
75+
7476
if (obs_output_active(m_output)) {
7577
obs_output_stop(m_output);
7678
std::unique_lock lock(m_mtxOutputStop);

obs-studio-server/source/osn-output.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Output {
4242
void ConnectSignals();
4343
void CreateOutput(const std::string &type, const std::string &name);
4444
void SetOutput(obs_output_t *output);
45-
void DeleteOutput();
45+
virtual void DeleteOutput();
4646
void StartOutput();
4747

4848
// If no signal, will return an empty optional. Thread safe.

obs-studio-server/source/osn-simple-streaming.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,11 @@ void osn::ISimpleStreaming::Start(void *data, const int64_t id, const std::vecto
337337
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid service.");
338338
}
339339

340+
if (streaming->enhancedBroadcasting) {
341+
streaming->StartEnhancedBroadcastingStream();
342+
return;
343+
}
344+
340345
const char *type = OBS_service::getStreamOutputType(streaming->service);
341346
if (!type)
342347
type = "rtmp_output";

obs-studio-server/source/osn-streaming.cpp

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ osn::Streaming::~Streaming()
3333
}
3434
}
3535

36+
void osn::Streaming::DeleteOutput() {
37+
blog(LOG_INFO, "osn::Streaming::DeleteOutput");
38+
Output::DeleteOutput();
39+
if (enhancedBroadcasting) {
40+
enhancedBroadcastingContext.reset();
41+
}
42+
}
43+
3644
void osn::IStreaming::GetService(void *data, const int64_t id, const std::vector<ipc::value> &args, std::vector<ipc::value> &rval)
3745
{
3846
Streaming *streaming = osn::IStreaming::Manager::GetInstance().find(args[0].value_union.ui64);
@@ -405,6 +413,79 @@ void osn::Streaming::setNetworkLegacySettings()
405413
config_set_bool(ConfigManager::getInstance().getBasic(), "Output", "LowLatencyEnable", network->enableDynamicBitrate);
406414
}
407415

416+
void osn::Streaming::StartEnhancedBroadcastingStream(std::optional<size_t> vod_track_mixer) {
417+
blog(LOG_INFO, "Streaming::StartEnhancedBroadcastingStream - service id: %s", obs_service_get_id(this->service));
418+
419+
if (vod_track_mixer.has_value()) {
420+
blog(LOG_INFO, "vod_track_mixer: %d", vod_track_mixer.value());
421+
}
422+
423+
const bool is_custom = strncmp("rtmp_custom", obs_service_get_type(this->service), 11) == 0;
424+
425+
OBSDataAutoRelease settings = obs_service_get_settings(this->service);
426+
const std::string key = obs_data_get_string(settings, "key");
427+
428+
const char *service_name = "<unknown>";
429+
if (is_custom && obs_data_has_user_value(settings, "service_name")) {
430+
service_name = obs_data_get_string(settings, "service_name");
431+
} else if (!is_custom) {
432+
service_name = obs_data_get_string(settings, "service");
433+
}
434+
435+
std::optional<std::string> custom_rtmp_url;
436+
auto server = obs_data_get_string(settings, "server");
437+
if (strcmp(server, "auto") != 0) {
438+
custom_rtmp_url = server;
439+
}
440+
441+
auto service_custom_server = obs_data_get_bool(settings, "using_custom_server");
442+
if (custom_rtmp_url.has_value()) {
443+
blog(LOG_INFO, "Using %s server '%s'", service_custom_server ? "custom " : "", custom_rtmp_url->c_str());
444+
}
445+
446+
auto auto_config_url = osn::MultitrackVideoAutoConfigURL(this->service);
447+
blog(LOG_INFO, "Auto config URL: %s", auto_config_url.c_str());
448+
449+
const bool dualStreamingMode = true; // TODO: revise this??????? Make this dynamic?????
450+
auto go_live_post = osn::constructGoLivePost(StreamServiceId::Main, dualStreamingMode, key, std::nullopt, std::nullopt, vod_track_mixer.has_value());
451+
std::optional<osn::Config> go_live_config = osn::DownloadGoLiveConfig(auto_config_url, go_live_post);
452+
if (!go_live_config.has_value()) {
453+
throw std::runtime_error("startStreaming - go live config is empty");
454+
}
455+
456+
const auto audio_bitrate = osn::GetMultitrackAudioBitrate();
457+
const auto audio_encoder_id = osn::GetSimpleAACEncoderForBitrate(audio_bitrate);
458+
459+
std::vector<OBSEncoderAutoRelease> audio_encoders;
460+
std::shared_ptr<obs_encoder_group_t> video_encoder_group;
461+
auto output =
462+
osn::SetupOBSOutput("Enhanced Broadcasting", go_live_config.value(), audio_encoders, video_encoder_group, audio_encoder_id, 0, vod_track_mixer);
463+
if (!output) {
464+
throw std::runtime_error("startStreaming - failed to create multitrack output");
465+
}
466+
467+
// Stream key is defined by config from Twitch
468+
auto multitrack_video_service = osn::create_service(*go_live_config, std::nullopt, "");
469+
if (!multitrack_video_service) {
470+
throw std::runtime_error("startStreaming - failed to create multitrack video service");
471+
}
472+
473+
this->SetOutput(output.Get());
474+
obs_output_set_service(output, multitrack_video_service);
475+
476+
// Register the BPM (Broadcast Performance Metrics) callback
477+
obs_output_add_packet_callback(output, bpm_inject, NULL);
478+
479+
this->StartOutput();
480+
481+
enhancedBroadcastingContext.emplace(EnhancedBroadcastOutputObjects{
482+
std::move(output),
483+
video_encoder_group,
484+
std::move(audio_encoders),
485+
std::move(multitrack_video_service),
486+
});
487+
}
488+
408489
void osn::IStreaming::GetDroppedFrames(void *data, const int64_t id, const std::vector<ipc::value> &args, std::vector<ipc::value> &rval)
409490
{
410491
Streaming *streaming = osn::IStreaming::Manager::GetInstance().find(args[0].value_union.ui64);
@@ -507,4 +588,4 @@ void osn::IStreaming::GetDataOutput(void *data, const int64_t id, const std::vec
507588
rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
508589
rval.push_back(ipc::value(dataOutput));
509590
AUTO_DEBUG;
510-
}
591+
}

obs-studio-server/source/osn-streaming.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
#include "nodeobs_configManager.hpp"
3030

31+
#include <optional>
32+
3133
namespace osn {
3234
class Streaming : public Output {
3335
public:
@@ -43,7 +45,6 @@ class Streaming : public Output {
4345
enhancedBroadcasting = false;
4446
oldMixer_desktopSource1 = 0;
4547
oldMixer_desktopSource2 = 0;
46-
//signals = {"start", "stop", "starting", "stopping", "activate", "deactivate", "reconnect", "reconnect_success"};
4748
delay = new Delay();
4849
reconnect = new Reconnect();
4950
network = new Network();
@@ -52,6 +53,8 @@ class Streaming : public Output {
5253
}
5354
virtual ~Streaming();
5455

56+
void DeleteOutput() override;
57+
5558
public:
5659
obs_encoder_t *videoEncoder;
5760
obs_encoder_t *streamArchive;
@@ -68,15 +71,17 @@ class Streaming : public Output {
6871
uint64_t lastBytesSent;
6972
uint64_t lastBytesSentTime;
7073

71-
std::optional<osn::EnhancedBroadcastOutputObjects> enhancedBroadcastContext;
72-
7374
bool isTwitchVODSupported();
7475
void getDelayLegacySettings();
7576
void getReconnectLegacySettings();
7677
void getNetworkLegacySettings();
7778
void setDelayLegacySettings();
7879
void setReconnectLegacySettings();
7980
void setNetworkLegacySettings();
81+
void StartEnhancedBroadcastingStream(std::optional<size_t> vod_track_mixer = std::nullopt);
82+
83+
protected:
84+
std::optional<osn::EnhancedBroadcastOutputObjects> enhancedBroadcastingContext;
8085
};
8186

8287
class IStreaming {

0 commit comments

Comments
 (0)