Skip to content

Implement object clean up for encoders and outputs related objects #1531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions js/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,8 @@ export declare const enum ERecordingFormat {
FLV = "flv",
MOV = "mov",
MKV = "mkv",
TS = "mpegts",
M3M8 = "m3m8"
MPEGTS = "ts",
HLS = "m3u8"
}
export declare const enum ERecordingQuality {
Stream = 0,
Expand All @@ -773,19 +773,19 @@ export declare const enum EProcessPriority {
BelowNormal = "BelowNormal",
Idle = "Idle"
}
export interface IVideoEncoder extends IConfigurable {
export interface IVideoEncoder extends IConfigurable, IReleasable {
name: string;
readonly type: EVideoEncoderType;
readonly active: boolean;
readonly id: string;
readonly lastError: string;
}
export interface IAudioEncoder {
export interface IAudioEncoder extends IReleasable {
name: string;
bitrate: number;
}
export interface IAudioEncoderFactory {
create(): IAudioEncoder;
create(id: string, name: string): IAudioEncoder;
}
export interface IVideoEncoderFactory {
types(): string[];
Expand Down Expand Up @@ -910,7 +910,7 @@ export interface ISimpleReplayBufferFactory {
export interface IAdvancedReplayBufferFactory {
create(): IAdvancedReplayBuffer;
destroy(stream: IAdvancedReplayBuffer): void;
legacySettings: IAdvancedReplayBufferFactory;
legacySettings: IAdvancedReplayBuffer;
}
export interface IDelay {
enabled: boolean;
Expand Down
12 changes: 6 additions & 6 deletions js/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1652,8 +1652,8 @@ export const enum ERecordingFormat {
FLV = 'flv',
MOV = 'mov',
MKV = 'mkv',
TS = 'mpegts',
M3M8 = 'm3m8'
MPEGTS = 'ts',
HLS = 'm3u8'
}

export const enum ERecordingQuality {
Expand All @@ -1676,21 +1676,21 @@ export const enum EProcessPriority {
Idle = 'Idle'
}

export interface IVideoEncoder extends IConfigurable {
export interface IVideoEncoder extends IConfigurable, IReleasable {
name: string,
readonly type: EVideoEncoderType,
readonly active: boolean,
readonly id: string,
readonly lastError: string
}

export interface IAudioEncoder {
export interface IAudioEncoder extends IReleasable {
name: string,
bitrate: number
}

export interface IAudioEncoderFactory {
create(): IAudioEncoder
create(id: string, name: string): IAudioEncoder
}

export interface IVideoEncoderFactory {
Expand Down Expand Up @@ -1833,7 +1833,7 @@ export interface ISimpleReplayBufferFactory {
export interface IAdvancedReplayBufferFactory {
create(): IAdvancedReplayBuffer;
destroy(stream: IAdvancedReplayBuffer): void;
legacySettings: IAdvancedReplayBufferFactory;
legacySettings: IAdvancedReplayBuffer;
}

export interface IDelay {
Expand Down
49 changes: 35 additions & 14 deletions obs-studio-client/source/advanced-recording.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ osn::AdvancedRecording::AdvancedRecording(const Napi::CallbackInfo &info) : Napi
this->className = std::string("AdvancedRecording");
}

void osn::AdvancedRecording::Finalize(Napi::Env)
{
ReleaseObjects();
}

void osn::AdvancedRecording::ReleaseObjects()
{
if (!videoEncoderRef.IsEmpty())
videoEncoderRef.Reset();
if (!streamingRef.IsEmpty())
streamingRef.Reset();
}

Napi::Value osn::AdvancedRecording::Create(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
Expand All @@ -107,6 +120,8 @@ void osn::AdvancedRecording::Destroy(const Napi::CallbackInfo &info)
recording->stopWorker();
recording->cb.Reset();

recording->ReleaseObjects();

auto conn = GetConnection(info);
if (!conn)
return;
Expand Down Expand Up @@ -268,32 +283,38 @@ void osn::AdvancedRecording::SetLegacySettings(const Napi::CallbackInfo &info, c
}

Napi::Value osn::AdvancedRecording::GetStreaming(const Napi::CallbackInfo &info)
{
return streamingRef.IsEmpty() ? info.Env().Undefined() : streamingRef.Value();
}

void osn::AdvancedRecording::SetStreaming(const Napi::CallbackInfo &info, const Napi::Value &value)
{
auto conn = GetConnection(info);
if (!conn)
return info.Env().Undefined();

std::vector<ipc::value> response = conn->call_synchronous_helper(className, "GetStreaming", {ipc::value(this->uid)});
return;

if (!ValidateResponse(info, response))
return info.Env().Undefined();
if (value.IsNull() || value.IsUndefined()) {
if (!streamingRef.IsEmpty())
streamingRef.Reset();
conn->call(className, "SetStreaming", {ipc::value(this->uid), ipc::value(UINT64_MAX)});
return;
}

auto instance = osn::AdvancedStreaming::constructor.New({Napi::Number::New(info.Env(), static_cast<double>(response[1].value_union.ui64))});
return instance;
}
Napi::Object obj = value.As<Napi::Object>();
if (!obj.InstanceOf(osn::AdvancedStreaming::constructor.Value()))
Napi::TypeError::New(info.Env(), "Object is not a AdvancedStreaming").ThrowAsJavaScriptException();

void osn::AdvancedRecording::SetStreaming(const Napi::CallbackInfo &info, const Napi::Value &value)
{
osn::AdvancedStreaming *streaming = Napi::ObjectWrap<osn::AdvancedStreaming>::Unwrap(value.ToObject());

if (!streaming) {
Napi::TypeError::New(info.Env(), "Invalid streaming argument").ThrowAsJavaScriptException();
return;
}

auto conn = GetConnection(info);
if (!conn)
return;

conn->call(className, "SetStreaming", {ipc::value(this->uid), ipc::value(streaming->uid)});

if (!streamingRef.IsEmpty())
streamingRef.Reset();

streamingRef = Napi::Persistent(obj);
}
3 changes: 2 additions & 1 deletion obs-studio-client/source/advanced-recording.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class AdvancedRecording : public Napi::ObjectWrap<osn::AdvancedRecording>, publi
static Napi::FunctionReference constructor;
static Napi::Object Init(Napi::Env env, Napi::Object exports);
AdvancedRecording(const Napi::CallbackInfo &info);

void Finalize(Napi::Env);
void ReleaseObjects();
static Napi::Value Create(const Napi::CallbackInfo &info);
static void Destroy(const Napi::CallbackInfo &info);

Expand Down
94 changes: 63 additions & 31 deletions obs-studio-client/source/advanced-replay-buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ osn::AdvancedReplayBuffer::AdvancedReplayBuffer(const Napi::CallbackInfo &info)
this->className = std::string("AdvancedReplayBuffer");
}

void osn::AdvancedReplayBuffer::Finalize(Napi::Env)
{
ReleaseObjects();
}

void osn::AdvancedReplayBuffer::ReleaseObjects()
{
if (!parentOutputRef.IsEmpty())
parentOutputRef.Reset();
}

Napi::Value osn::AdvancedReplayBuffer::Create(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
Expand All @@ -103,6 +114,7 @@ void osn::AdvancedReplayBuffer::Destroy(const Napi::CallbackInfo &info)

replayBuffer->stopWorker();
replayBuffer->cb.Reset();
replayBuffer->ReleaseObjects();

auto conn = GetConnection(info);
if (!conn)
Expand Down Expand Up @@ -174,62 +186,82 @@ void osn::AdvancedReplayBuffer::SetLegacySettings(const Napi::CallbackInfo &info

Napi::Value osn::AdvancedReplayBuffer::GetStreaming(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
if (!conn)
return info.Env().Undefined();

std::vector<ipc::value> response = conn->call_synchronous_helper(className, "GetStreaming", {ipc::value(this->uid)});

if (!ValidateResponse(info, response))
if (usesStream) {
return parentOutputRef.IsEmpty() ? info.Env().Undefined() : parentOutputRef.Value();
} else {
return info.Env().Undefined();

auto instance = osn::AdvancedStreaming::constructor.New({Napi::Number::New(info.Env(), static_cast<double>(response[1].value_union.ui64))});
return instance;
}
}

void osn::AdvancedReplayBuffer::SetStreaming(const Napi::CallbackInfo &info, const Napi::Value &value)
{
osn::AdvancedStreaming *encoder = Napi::ObjectWrap<osn::AdvancedStreaming>::Unwrap(value.ToObject());
auto conn = GetConnection(info);
if (!conn)
return;

if (!encoder) {
Napi::TypeError::New(info.Env(), "Invalid streaming argument").ThrowAsJavaScriptException();
if (value.IsNull() || value.IsUndefined()) {
if (!parentOutputRef.IsEmpty())
parentOutputRef.Reset();
conn->call(className, "SetStreaming", {ipc::value(this->uid), ipc::value(UINT64_MAX)});
usesStream = false;
return;
}

auto conn = GetConnection(info);
if (!conn)
Napi::Object obj = value.As<Napi::Object>();
if (!obj.InstanceOf(osn::AdvancedStreaming::constructor.Value()))
Napi::TypeError::New(info.Env(), "Object is not a valid Streaming").ThrowAsJavaScriptException();

osn::AdvancedStreaming *streaming = Napi::ObjectWrap<osn::AdvancedStreaming>::Unwrap(value.ToObject());

if (!streaming) {
Napi::TypeError::New(info.Env(), "Invalid streaming argument").ThrowAsJavaScriptException();
return;
}

conn->call(className, "SetStreaming", {ipc::value(this->uid), ipc::value(streaming->uid)});
usesStream = true;
if (!parentOutputRef.IsEmpty())
parentOutputRef.Reset();

conn->call(className, "SetStreaming", {ipc::value(this->uid), ipc::value(encoder->uid)});
parentOutputRef = Napi::Persistent(obj);
}

Napi::Value osn::AdvancedReplayBuffer::GetRecording(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
if (!conn)
if (usesStream) {
return info.Env().Undefined();

std::vector<ipc::value> response = conn->call_synchronous_helper(className, "GetRecording", {ipc::value(this->uid)});

if (!ValidateResponse(info, response))
return info.Env().Undefined();

auto instance = osn::AdvancedRecording::constructor.New({Napi::Number::New(info.Env(), static_cast<double>(response[1].value_union.ui64))});
return instance;
} else {
return parentOutputRef.IsEmpty() ? info.Env().Undefined() : parentOutputRef.Value();
}
}

void osn::AdvancedReplayBuffer::SetRecording(const Napi::CallbackInfo &info, const Napi::Value &value)
{
osn::AdvancedRecording *recording = Napi::ObjectWrap<osn::AdvancedRecording>::Unwrap(value.ToObject());
auto conn = GetConnection(info);
if (!conn)
return;

if (!recording) {
Napi::TypeError::New(info.Env(), "Invalid streaming argument").ThrowAsJavaScriptException();
if (value.IsNull() || value.IsUndefined()) {
if (!parentOutputRef.IsEmpty())
parentOutputRef.Reset();
conn->call(className, "SetRecording", {ipc::value(this->uid), ipc::value(UINT64_MAX)});
usesStream = false;
return;
}

auto conn = GetConnection(info);
if (!conn)
Napi::Object obj = value.As<Napi::Object>();
if (!obj.InstanceOf(osn::AdvancedRecording::constructor.Value()))
Napi::TypeError::New(info.Env(), "Object is not a Valid Recording").ThrowAsJavaScriptException();

osn::AdvancedRecording *recording = Napi::ObjectWrap<osn::AdvancedRecording>::Unwrap(obj);
if (!recording) {
Napi::TypeError::New(info.Env(), "Invalid recording argument").ThrowAsJavaScriptException();
return;
}

conn->call(className, "SetRecording", {ipc::value(this->uid), ipc::value(recording->uid)});
usesStream = false;
if (!parentOutputRef.IsEmpty())
parentOutputRef.Reset();
parentOutputRef = Napi::Persistent(obj);
}
3 changes: 2 additions & 1 deletion obs-studio-client/source/advanced-replay-buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class AdvancedReplayBuffer : public Napi::ObjectWrap<osn::AdvancedReplayBuffer>,
static Napi::FunctionReference constructor;
static Napi::Object Init(Napi::Env env, Napi::Object exports);
AdvancedReplayBuffer(const Napi::CallbackInfo &info);

void Finalize(Napi::Env);
void ReleaseObjects();
static Napi::Value Create(const Napi::CallbackInfo &info);
static void Destroy(const Napi::CallbackInfo &info);

Expand Down
12 changes: 12 additions & 0 deletions obs-studio-client/source/advanced-streaming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ osn::AdvancedStreaming::AdvancedStreaming(const Napi::CallbackInfo &info) : Napi
this->className = std::string("AdvancedStreaming");
}

void osn::AdvancedStreaming::Finalize(Napi::Env)
{
ReleaseObjects();
}

void osn::AdvancedStreaming::ReleaseObjects()
{
osn::Streaming::ReleaseObjects();
}

Napi::Value osn::AdvancedStreaming::Create(const Napi::CallbackInfo &info)
{
auto conn = GetConnection(info);
Expand All @@ -106,6 +116,8 @@ void osn::AdvancedStreaming::Destroy(const Napi::CallbackInfo &info)
stream->stopWorker();
stream->cb.Reset();

stream->ReleaseObjects();

auto conn = GetConnection(info);
if (!conn)
return;
Expand Down
3 changes: 2 additions & 1 deletion obs-studio-client/source/advanced-streaming.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class AdvancedStreaming : public Napi::ObjectWrap<osn::AdvancedStreaming>, publi
static Napi::FunctionReference constructor;
static Napi::Object Init(Napi::Env env, Napi::Object exports);
AdvancedStreaming(const Napi::CallbackInfo &info);

void Finalize(Napi::Env);
void ReleaseObjects();
static Napi::Value Create(const Napi::CallbackInfo &info);
static void Destroy(const Napi::CallbackInfo &info);

Expand Down
Loading
Loading