libobs: Use reference counting for encoder packets

Prevents reallocation of encoded packet data.

Deprecates:
obs_duplicate_encoder_packet
obs_free_encoder_packet

Replaces those functions with:
obs_encoder_packet_ref
obs_encoder_packet_release
This commit is contained in:
jp9000 2016-12-07 12:45:25 -08:00
parent eb6d8e10fa
commit 7d6e6eee79
7 changed files with 67 additions and 21 deletions

View File

@ -1035,17 +1035,55 @@ void obs_encoder_remove_output(struct obs_encoder *encoder,
pthread_mutex_unlock(&encoder->outputs_mutex);
}
void obs_encoder_packet_create_instance(struct encoder_packet *dst,
const struct encoder_packet *src)
{
long *p_refs;
*dst = *src;
p_refs = bmalloc(src->size + sizeof(long));
dst->data = (void*)(p_refs + 1);
*p_refs = 1;
memcpy(dst->data, src->data, src->size);
}
void obs_duplicate_encoder_packet(struct encoder_packet *dst,
const struct encoder_packet *src)
{
*dst = *src;
dst->data = bmemdup(src->data, src->size);
obs_encoder_packet_create_instance(dst, src);
}
void obs_free_encoder_packet(struct encoder_packet *packet)
{
bfree(packet->data);
memset(packet, 0, sizeof(struct encoder_packet));
obs_encoder_packet_release(packet);
}
void obs_encoder_packet_ref(struct encoder_packet *dst,
struct encoder_packet *src)
{
if (!src)
return;
if (src->data) {
long *p_refs = ((long*)src->data) - 1;
os_atomic_inc_long(p_refs);
}
*dst = *src;
}
void obs_encoder_packet_release(struct encoder_packet *pkt)
{
if (!pkt)
return;
if (pkt->data) {
long *p_refs = ((long*)pkt->data) - 1;
if (os_atomic_dec_long(p_refs) == 0)
bfree(p_refs);
}
memset(pkt, 0, sizeof(struct encoder_packet));
}
void obs_encoder_set_preferred_video_format(obs_encoder_t *encoder,

View File

@ -864,6 +864,8 @@ extern const struct obs_output_info *find_output(const char *id);
extern void obs_output_remove_encoder(struct obs_output *output,
struct obs_encoder *encoder);
extern void obs_encoder_packet_create_instance(struct encoder_packet *dst,
const struct encoder_packet *src);
void obs_output_destroy(obs_output_t *output);

View File

@ -35,7 +35,7 @@ static inline void push_packet(struct obs_output *output,
dd.msg = DELAY_MSG_PACKET;
dd.ts = t;
obs_duplicate_encoder_packet(&dd.packet, packet);
obs_encoder_packet_create_instance(&dd.packet, packet);
pthread_mutex_lock(&output->delay_mutex);
circlebuf_push_back(&output->delay_data, &dd, sizeof(dd));
@ -48,7 +48,7 @@ static inline void process_delay_data(struct obs_output *output,
switch (dd->msg) {
case DELAY_MSG_PACKET:
if (!delay_active(output) || !delay_capturing(output))
obs_free_encoder_packet(&dd->packet);
obs_encoder_packet_release(&dd->packet);
else
output->delay_callback(output, &dd->packet);
break;
@ -68,7 +68,7 @@ void obs_output_cleanup_delay(obs_output_t *output)
while (output->delay_data.size) {
circlebuf_pop_front(&output->delay_data, &dd, sizeof(dd));
if (dd.msg == DELAY_MSG_PACKET) {
obs_free_encoder_packet(&dd.packet);
obs_encoder_packet_release(&dd.packet);
}
}

View File

@ -157,7 +157,7 @@ fail:
static inline void free_packets(struct obs_output *output)
{
for (size_t i = 0; i < output->interleaved_packets.num; i++)
obs_free_encoder_packet(output->interleaved_packets.array+i);
obs_encoder_packet_release(output->interleaved_packets.array+i);
da_free(output->interleaved_packets);
}
@ -957,7 +957,7 @@ static inline void send_interleaved(struct obs_output *output)
da_erase(output->interleaved_packets, 0);
output->info.encoded_packet(output->context.data, &out);
obs_free_encoder_packet(&out);
obs_encoder_packet_release(&out);
}
static inline void set_higher_ts(struct obs_output *output,
@ -1056,7 +1056,7 @@ static void discard_to_idx(struct obs_output *output, size_t idx)
for (size_t i = 0; i < idx; i++) {
struct encoder_packet *packet =
&output->interleaved_packets.array[i];
obs_free_encoder_packet(packet);
obs_encoder_packet_release(packet);
}
da_erase_range(output->interleaved_packets, 0, idx);
@ -1304,7 +1304,7 @@ static void interleave_packets(void *data, struct encoder_packet *packet)
pthread_mutex_unlock(&output->interleaved_mutex);
if (output->active_delay_ns)
obs_free_encoder_packet(packet);
obs_encoder_packet_release(packet);
return;
}
@ -1313,7 +1313,7 @@ static void interleave_packets(void *data, struct encoder_packet *packet)
if (output->active_delay_ns)
out = *packet;
else
obs_duplicate_encoder_packet(&out, packet);
obs_encoder_packet_create_instance(&out, packet);
if (was_started)
apply_interleaved_packet_offset(output, &out);
@ -1356,7 +1356,7 @@ static void default_encoded_callback(void *param, struct encoder_packet *packet)
}
if (output->active_delay_ns)
obs_free_encoder_packet(packet);
obs_encoder_packet_release(packet);
}
static void default_raw_video_callback(void *param, struct video_data *frame)

View File

@ -1651,11 +1651,17 @@ EXPORT const char *obs_encoder_get_id(const obs_encoder_t *encoder);
EXPORT uint32_t obs_get_encoder_caps(const char *encoder_id);
/** Duplicates an encoder packet */
DEPRECATED
EXPORT void obs_duplicate_encoder_packet(struct encoder_packet *dst,
const struct encoder_packet *src);
DEPRECATED
EXPORT void obs_free_encoder_packet(struct encoder_packet *packet);
EXPORT void obs_encoder_packet_ref(struct encoder_packet *dst,
struct encoder_packet *src);
EXPORT void obs_encoder_packet_release(struct encoder_packet *packet);
/* ------------------------------------------------------------------------- */
/* Stream Services */

View File

@ -100,7 +100,7 @@ static int write_packet(struct flv_output *stream,
flv_packet_mux(packet, &data, &size, is_header);
fwrite(data, 1, size, stream->file);
bfree(data);
obs_free_encoder_packet(packet);
obs_encoder_packet_release(packet);
return ret;
}
@ -200,7 +200,7 @@ static void flv_output_data(void *data, struct encoder_packet *packet)
if (packet->type == OBS_ENCODER_VIDEO) {
obs_parse_avc_packet(&parsed_packet, packet);
write_packet(stream, &parsed_packet, false);
obs_free_encoder_packet(&parsed_packet);
obs_encoder_packet_release(&parsed_packet);
} else {
write_packet(stream, packet, false);
}

View File

@ -134,7 +134,7 @@ static inline void free_packets(struct rtmp_stream *stream)
while (stream->packets.size) {
struct encoder_packet packet;
circlebuf_pop_front(&stream->packets, &packet, sizeof(packet));
obs_free_encoder_packet(&packet);
obs_encoder_packet_release(&packet);
}
pthread_mutex_unlock(&stream->packets_mutex);
}
@ -375,7 +375,7 @@ static int send_packet(struct rtmp_stream *stream,
ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx);
bfree(data);
obs_free_encoder_packet(packet);
obs_encoder_packet_release(packet);
stream->total_bytes_sent += size;
return ret;
@ -414,7 +414,7 @@ static void *send_thread(void *data)
if (stopping(stream)) {
if (can_shutdown_stream(stream, &packet)) {
obs_free_encoder_packet(&packet);
obs_encoder_packet_release(&packet);
break;
}
}
@ -844,7 +844,7 @@ static void drop_frames(struct rtmp_stream *stream, const char *name,
} else {
num_frames_dropped++;
obs_free_encoder_packet(&packet);
obs_encoder_packet_release(&packet);
}
}
@ -929,7 +929,7 @@ static void rtmp_stream_data(void *data, struct encoder_packet *packet)
if (packet->type == OBS_ENCODER_VIDEO)
obs_parse_avc_packet(&new_packet, packet);
else
obs_duplicate_encoder_packet(&new_packet, packet);
obs_encoder_packet_ref(&new_packet, packet);
pthread_mutex_lock(&stream->packets_mutex);
@ -944,7 +944,7 @@ static void rtmp_stream_data(void *data, struct encoder_packet *packet)
if (added_packet)
os_sem_post(stream->send_sem);
else
obs_free_encoder_packet(&new_packet);
obs_encoder_packet_release(&new_packet);
}
static void rtmp_stream_defaults(obs_data_t *defaults)