From 244280335b89b66cb153a8a6f542948f828fdbc3 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Wed, 31 Dec 2014 01:30:54 -0800 Subject: [PATCH] libobs: Fix potential crash on output stop In certain circumstances where the output was stopping, and where data took a long enough time to send (such as when using an encoding preset that causes high CPU usage), the output would sometimes still send data even after it was stopped, typically causing the output to crash. --- libobs/obs-internal.h | 1 + libobs/obs-output.c | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index a77fb80f5..772b7ffbc 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -395,6 +395,7 @@ struct obs_output { int total_frames; bool active; + volatile bool stopped; video_t *video; audio_t *audio; obs_encoder_t *video_encoder; diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 5d00a6c01..61ce66304 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -159,6 +159,8 @@ bool obs_output_start(obs_output_t *output) if (!output) return false; + output->stopped = false; + success = output->info.start(output->context.data); if (success && output->video) { @@ -207,6 +209,8 @@ static void log_frame_info(struct obs_output *output) void obs_output_stop(obs_output_t *output) { if (output) { + output->stopped = true; + os_event_signal(output->reconnect_stop_event); if (output->reconnect_thread_active) pthread_join(output->reconnect_thread, NULL); @@ -617,7 +621,8 @@ static inline void send_interleaved(struct obs_output *output) output->total_frames++; da_erase(output->interleaved_packets, 0); - output->info.encoded_packet(output->context.data, &out); + if (!output->stopped) + output->info.encoded_packet(output->context.data, &out); obs_free_encoder_packet(&out); } @@ -787,7 +792,8 @@ static void interleave_packets(void *data, struct encoder_packet *packet) static void default_encoded_callback(void *param, struct encoder_packet *packet) { struct obs_output *output = param; - output->info.encoded_packet(output->context.data, packet); + if (!output->stopped) + output->info.encoded_packet(output->context.data, packet); if (packet->type == OBS_ENCODER_VIDEO) output->total_frames++; @@ -796,10 +802,18 @@ static void default_encoded_callback(void *param, struct encoder_packet *packet) static void default_raw_video_callback(void *param, struct video_data *frame) { struct obs_output *output = param; - output->info.raw_video(output->context.data, frame); + if (!output->stopped) + output->info.raw_video(output->context.data, frame); output->total_frames++; } +static void default_raw_audio_callback(void *param, struct audio_data *frames) +{ + struct obs_output *output = param; + if (!output->stopped) + output->info.raw_audio(output->context.data, frames); +} + static void hook_data_capture(struct obs_output *output, bool encoded, bool has_video, bool has_audio) { @@ -831,8 +845,7 @@ static void hook_data_capture(struct obs_output *output, bool encoded, if (has_audio) audio_output_connect(output->audio, get_audio_conversion(output), - output->info.raw_audio, - output->context.data); + default_raw_audio_callback, output); } }