(API Change) libobs: Make obs_encoder refcounted
This commit is contained in:
parent
f094bf199d
commit
ba0b8eb0e1
@ -76,6 +76,9 @@ static struct obs_encoder *create_encoder(const char *id,
|
||||
encoder = NULL;
|
||||
}
|
||||
|
||||
encoder->control = bzalloc(sizeof(obs_weak_encoder_t));
|
||||
encoder->control->encoder = encoder;
|
||||
|
||||
obs_context_data_insert(&encoder->context,
|
||||
&obs->data.encoders_mutex,
|
||||
&obs->data.first_encoder);
|
||||
@ -783,3 +786,78 @@ enum video_format obs_encoder_get_preferred_video_format(
|
||||
|
||||
return encoder->preferred_format;
|
||||
}
|
||||
|
||||
void obs_encoder_addref(obs_encoder_t *encoder)
|
||||
{
|
||||
if (!encoder)
|
||||
return;
|
||||
|
||||
obs_ref_addref(&encoder->control->ref);
|
||||
}
|
||||
|
||||
void obs_encoder_release(obs_encoder_t *encoder)
|
||||
{
|
||||
if (!encoder)
|
||||
return;
|
||||
|
||||
obs_weak_encoder_t *control = encoder->control;
|
||||
if (obs_ref_release(&control->ref)) {
|
||||
// The order of operations is important here since
|
||||
// get_context_by_name in obs.c relies on weak refs
|
||||
// being alive while the context is listed
|
||||
obs_encoder_destroy(encoder);
|
||||
obs_weak_encoder_release(control);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_weak_encoder_addref(obs_weak_encoder_t *weak)
|
||||
{
|
||||
if (!weak)
|
||||
return;
|
||||
|
||||
obs_weak_ref_addref(&weak->ref);
|
||||
}
|
||||
|
||||
void obs_weak_encoder_release(obs_weak_encoder_t *weak)
|
||||
{
|
||||
if (!weak)
|
||||
return;
|
||||
|
||||
if (obs_weak_ref_release(&weak->ref))
|
||||
bfree(weak);
|
||||
}
|
||||
|
||||
obs_encoder_t *obs_encoder_get_ref(obs_encoder_t *encoder)
|
||||
{
|
||||
if (!encoder)
|
||||
return NULL;
|
||||
|
||||
return obs_weak_encoder_get_encoder(encoder->control);
|
||||
}
|
||||
|
||||
obs_weak_encoder_t *obs_encoder_get_weak_encoder(obs_encoder_t *encoder)
|
||||
{
|
||||
if (!encoder)
|
||||
return NULL;
|
||||
|
||||
obs_weak_encoder_t *weak = encoder->control;
|
||||
obs_weak_encoder_addref(weak);
|
||||
return weak;
|
||||
}
|
||||
|
||||
obs_encoder_t *obs_weak_encoder_get_encoder(obs_weak_encoder_t *weak)
|
||||
{
|
||||
if (!weak)
|
||||
return NULL;
|
||||
|
||||
if (obs_weak_ref_get_ref(&weak->ref))
|
||||
return weak->encoder;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool obs_weak_encoder_references_encoder(obs_weak_encoder_t *weak,
|
||||
obs_encoder_t *encoder)
|
||||
{
|
||||
return weak && encoder && weak->encoder == encoder;
|
||||
}
|
||||
|
@ -507,6 +507,11 @@ void obs_output_destroy(obs_output_t *output);
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* encoders */
|
||||
|
||||
struct obs_weak_encoder {
|
||||
struct obs_weak_ref ref;
|
||||
struct obs_encoder *encoder;
|
||||
};
|
||||
|
||||
struct encoder_callback {
|
||||
bool sent_first_packet;
|
||||
void (*new_packet)(void *param, struct encoder_packet *packet);
|
||||
@ -516,6 +521,7 @@ struct encoder_callback {
|
||||
struct obs_encoder {
|
||||
struct obs_context_data context;
|
||||
struct obs_encoder_info info;
|
||||
struct obs_weak_encoder *control;
|
||||
|
||||
uint32_t samplerate;
|
||||
size_t planes;
|
||||
@ -575,6 +581,8 @@ extern void obs_encoder_add_output(struct obs_encoder *encoder,
|
||||
extern void obs_encoder_remove_output(struct obs_encoder *encoder,
|
||||
struct obs_output *output);
|
||||
|
||||
void obs_encoder_destroy(obs_encoder_t *encoder);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* services */
|
||||
|
||||
|
@ -1189,6 +1189,11 @@ static inline void *obs_output_addref_safe_(void *ref)
|
||||
return obs_output_get_ref(ref);
|
||||
}
|
||||
|
||||
static inline void *obs_encoder_addref_safe_(void *ref)
|
||||
{
|
||||
return obs_encoder_get_ref(ref);
|
||||
}
|
||||
|
||||
static inline void *obs_id_(void *data)
|
||||
{
|
||||
return data;
|
||||
@ -1205,7 +1210,7 @@ obs_encoder_t *obs_get_encoder_by_name(const char *name)
|
||||
{
|
||||
if (!obs) return NULL;
|
||||
return get_context_by_name(&obs->data.first_encoder, name,
|
||||
&obs->data.encoders_mutex, obs_id_);
|
||||
&obs->data.encoders_mutex, obs_encoder_addref_safe_);
|
||||
}
|
||||
|
||||
obs_service_t *obs_get_service_by_name(const char *name)
|
||||
|
19
libobs/obs.h
19
libobs/obs.h
@ -64,6 +64,7 @@ typedef struct obs_volmeter obs_volmeter_t;
|
||||
|
||||
typedef struct obs_weak_source obs_weak_source_t;
|
||||
typedef struct obs_weak_output obs_weak_output_t;
|
||||
typedef struct obs_weak_encoder obs_weak_encoder_t;
|
||||
|
||||
#include "obs-source.h"
|
||||
#include "obs-encoder.h"
|
||||
@ -1313,8 +1314,22 @@ EXPORT obs_encoder_t *obs_video_encoder_create(const char *id, const char *name,
|
||||
EXPORT obs_encoder_t *obs_audio_encoder_create(const char *id, const char *name,
|
||||
obs_data_t *settings, size_t mixer_idx);
|
||||
|
||||
/** Destroys an encoder context */
|
||||
EXPORT void obs_encoder_destroy(obs_encoder_t *encoder);
|
||||
/**
|
||||
* Adds/releases a reference to an encoder. When the last reference is
|
||||
* released, the encoder is destroyed.
|
||||
*/
|
||||
EXPORT void obs_encoder_addref(obs_encoder_t *encoder);
|
||||
EXPORT void obs_encoder_release(obs_encoder_t *encoder);
|
||||
|
||||
EXPORT void obs_weak_encoder_addref(obs_weak_encoder_t *weak);
|
||||
EXPORT void obs_weak_encoder_release(obs_weak_encoder_t *weak);
|
||||
|
||||
EXPORT obs_encoder_t *obs_encoder_get_ref(obs_encoder_t *encoder);
|
||||
EXPORT obs_weak_encoder_t *obs_encoder_get_weak_encoder(obs_encoder_t *encoder);
|
||||
EXPORT obs_encoder_t *obs_weak_encoder_get_encoder(obs_weak_encoder_t *weak);
|
||||
|
||||
EXPORT bool obs_weak_encoder_references_encoder(obs_weak_encoder_t *weak,
|
||||
obs_encoder_t *encoder);
|
||||
|
||||
EXPORT void obs_encoder_set_name(obs_encoder_t *encoder, const char *name);
|
||||
EXPORT const char *obs_encoder_get_name(const obs_encoder_t *encoder);
|
||||
|
@ -34,11 +34,15 @@ using OBSData = OBSRef<obs_data_t*, obs_data_addref, obs_data_release>;
|
||||
using OBSDataArray = OBSRef<obs_data_array_t*, obs_data_array_addref,
|
||||
obs_data_array_release>;
|
||||
using OBSOutput = OBSRef<obs_output_t*, obs_output_addref, obs_output_release>;
|
||||
using OBSEncoder = OBSRef<obs_encoder_t*, obs_encoder_addref,
|
||||
obs_encoder_release>;
|
||||
|
||||
using OBSWeakSource = OBSRef<obs_weak_source_t*, obs_weak_source_addref,
|
||||
obs_weak_source_release>;
|
||||
using OBSWeakOutput = OBSRef<obs_weak_output_t*, obs_weak_output_addref,
|
||||
obs_weak_output_release>;
|
||||
using OBSWeakEncoder = OBSRef<obs_weak_encoder_t*, obs_weak_encoder_addref,
|
||||
obs_weak_encoder_release>;
|
||||
|
||||
template<typename T, void addref(T), void release(T)>
|
||||
class OBSRef {
|
||||
@ -87,6 +91,9 @@ public:
|
||||
|
||||
friend OBSOutput OBSGetStrongRef(obs_weak_output_t *weak);
|
||||
friend OBSWeakOutput OBSGetWeakRef(obs_output_t *output);
|
||||
|
||||
friend OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak);
|
||||
friend OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder);
|
||||
};
|
||||
|
||||
inline OBSSource OBSGetStrongRef(obs_weak_source_t *weak)
|
||||
@ -111,6 +118,18 @@ inline OBSWeakOutput OBSGetWeakRef(obs_output_t *output)
|
||||
OBSWeakOutput::TakeOwnership()};
|
||||
}
|
||||
|
||||
inline OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak)
|
||||
{
|
||||
return {obs_weak_encoder_get_encoder(weak),
|
||||
OBSEncoder::TakeOwnership()};
|
||||
}
|
||||
|
||||
inline OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder)
|
||||
{
|
||||
return {obs_encoder_get_weak_encoder(encoder),
|
||||
OBSWeakEncoder::TakeOwnership()};
|
||||
}
|
||||
|
||||
/* objects that are not meant to be instanced */
|
||||
template<typename T, void destroy(T)> class OBSObj {
|
||||
T obj;
|
||||
@ -147,7 +166,6 @@ public:
|
||||
};
|
||||
|
||||
using OBSDisplay = OBSObj<obs_display_t*, obs_display_destroy>;
|
||||
using OBSEncoder = OBSObj<obs_encoder_t*, obs_encoder_destroy>;
|
||||
using OBSView = OBSObj<obs_view_t*, obs_view_destroy>;
|
||||
|
||||
/* signal handler connection */
|
||||
|
@ -79,6 +79,7 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
h264 = obs_video_encoder_create("obs_x264", "simple_h264", nullptr);
|
||||
if (!h264)
|
||||
throw "Failed to create h264 encoder (simple output)";
|
||||
obs_encoder_release(h264);
|
||||
|
||||
aac = obs_audio_encoder_create("libfdk_aac", "simple_aac", nullptr, 0);
|
||||
if (!aac)
|
||||
@ -86,6 +87,7 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
nullptr, 0);
|
||||
if (!aac)
|
||||
throw "Failed to create audio encoder (simple output)";
|
||||
obs_encoder_release(aac);
|
||||
|
||||
signal_handler_connect(obs_output_get_signal_handler(streamOutput),
|
||||
"start", OBSStartStreaming, this);
|
||||
@ -346,6 +348,7 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
if (!h264Recording)
|
||||
throw "Failed to create recording h264 "
|
||||
"encoder (advanced output)";
|
||||
obs_encoder_release(h264Recording);
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,6 +357,7 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
if (!h264Streaming)
|
||||
throw "Failed to create streaming h264 encoder "
|
||||
"(advanced output)";
|
||||
obs_encoder_release(h264Streaming);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
char name[9];
|
||||
@ -367,6 +371,7 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
if (!aacTrack[i])
|
||||
throw "Failed to create audio encoder "
|
||||
"(advanced output)";
|
||||
obs_encoder_release(aacTrack[i]);
|
||||
}
|
||||
|
||||
signal_handler_connect(obs_output_get_signal_handler(streamOutput),
|
||||
|
Loading…
x
Reference in New Issue
Block a user