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:
parent
eb6d8e10fa
commit
7d6e6eee79
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user