(API Change) libobs: Make obs_encoder refcounted

master
Palana 2015-05-04 02:01:38 +02:00
parent f094bf199d
commit ba0b8eb0e1
6 changed files with 133 additions and 4 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)

View File

@ -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);

View File

@ -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 */

View File

@ -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),