diff --git a/plugins/obs-outputs/rtmp-stream.c b/plugins/obs-outputs/rtmp-stream.c index 4f1f4247c..4d59ad388 100644 --- a/plugins/obs-outputs/rtmp-stream.c +++ b/plugins/obs-outputs/rtmp-stream.c @@ -53,6 +53,8 @@ struct rtmp_stream { volatile bool disconnected; pthread_t send_thread; + bool stopping; + pthread_t stop_thread; int max_shutdown_time_sec; os_sem_t *send_sem; @@ -108,14 +110,28 @@ static inline void free_packets(struct rtmp_stream *stream) pthread_mutex_unlock(&stream->packets_mutex); } -static void rtmp_stream_stop(void *data); +static void *rtmp_stream_actual_stop(void *data); static void rtmp_stream_destroy(void *data) { struct rtmp_stream *stream = data; - if (stream->connecting || stream->active) - rtmp_stream_stop(data); + if (stream->stopping) { + pthread_join(stream->stop_thread, NULL); + + } else if (stream->connecting || stream->active) { + os_event_signal(stream->stop_event); + + if (stream->connecting) + pthread_join(stream->connect_thread, NULL); + + if (stream->active) { + os_sem_post(stream->send_sem); + obs_output_end_data_capture(stream->output); + } + + rtmp_stream_actual_stop(data); + } if (stream) { free_packets(stream); @@ -155,9 +171,30 @@ fail: return NULL; } +static void *rtmp_stream_actual_stop(void *data) +{ + struct rtmp_stream *stream = data; + void *ret; + + if (stream->active) { + pthread_join(stream->send_thread, &ret); + RTMP_Close(&stream->rtmp); + } + + os_event_reset(stream->stop_event); + + stream->sent_headers = false; + stream->stopping = false; + return NULL; +} + static void rtmp_stream_stop(void *data) { struct rtmp_stream *stream = data; + int ret; + + if (stream->stopping) + return; os_event_signal(stream->stop_event); @@ -166,14 +203,16 @@ static void rtmp_stream_stop(void *data) if (stream->active) { os_sem_post(stream->send_sem); - pthread_join(stream->send_thread, NULL); obs_output_end_data_capture(stream->output); - RTMP_Close(&stream->rtmp); } - os_event_reset(stream->stop_event); - - stream->sent_headers = false; + stream->stopping = true; + ret = pthread_create(&stream->stop_thread, NULL, + rtmp_stream_actual_stop, stream); + if (ret != 0) { + warn("Could not create stop thread! Stopping directly"); + rtmp_stream_actual_stop(stream); + } } static inline void set_rtmp_str(AVal *val, const char *str) @@ -472,10 +511,39 @@ static int try_connect(struct rtmp_stream *stream) return init_send(stream); } +static void init_connect(struct rtmp_stream *stream) +{ + obs_service_t *service = obs_output_get_service(stream->output); + obs_data_t *settings; + + if (stream->stopping) + pthread_join(stream->stop_thread, NULL); + + stream->disconnected = false; + stream->total_bytes_sent = 0; + stream->dropped_frames = 0; + stream->min_drop_dts_usec= 0; + stream->min_priority = 0; + + settings = obs_output_get_settings(stream->output); + dstr_copy(&stream->path, obs_service_get_url(service)); + dstr_copy(&stream->key, obs_service_get_key(service)); + dstr_copy(&stream->username, obs_service_get_username(service)); + dstr_copy(&stream->password, obs_service_get_password(service)); + stream->drop_threshold_usec = + (int64_t)obs_data_get_int(settings, OPT_DROP_THRESHOLD) * 1000; + stream->max_shutdown_time_sec = + (int)obs_data_get_int(settings, OPT_MAX_SHUTDOWN_TIME_SEC); + obs_data_release(settings); +} + static void *connect_thread(void *data) { struct rtmp_stream *stream = data; - int ret = try_connect(stream); + int ret; + + init_connect(stream); + ret = try_connect(stream); if (ret != OBS_OUTPUT_SUCCESS) { obs_output_signal_stop(stream->output, ret); @@ -492,32 +560,12 @@ static void *connect_thread(void *data) static bool rtmp_stream_start(void *data) { struct rtmp_stream *stream = data; - obs_service_t *service = obs_output_get_service(stream->output); - obs_data_t *settings; - - stream->disconnected = false; if (!obs_output_can_begin_data_capture(stream->output, 0)) return false; if (!obs_output_initialize_encoders(stream->output, 0)) return false; - stream->total_bytes_sent = 0; - stream->dropped_frames = 0; - stream->min_drop_dts_usec= 0; - stream->min_priority = 0; - - settings = obs_output_get_settings(stream->output); - dstr_copy(&stream->path, obs_service_get_url(service)); - dstr_copy(&stream->key, obs_service_get_key(service)); - dstr_copy(&stream->username, obs_service_get_username(service)); - dstr_copy(&stream->password, obs_service_get_password(service)); - stream->drop_threshold_usec = - (int64_t)obs_data_get_int(settings, OPT_DROP_THRESHOLD) * 1000; - stream->max_shutdown_time_sec = - (int)obs_data_get_int(settings, OPT_MAX_SHUTDOWN_TIME_SEC); - obs_data_release(settings); - return pthread_create(&stream->connect_thread, NULL, connect_thread, stream) == 0; }