diff --git a/docs/sphinx/reference-outputs.rst b/docs/sphinx/reference-outputs.rst index 3466ccb7f..dcfe16b62 100644 --- a/docs/sphinx/reference-outputs.rst +++ b/docs/sphinx/reference-outputs.rst @@ -772,6 +772,28 @@ General Output Functions .. versionadded:: 31.0 +--------------------- + +.. function:: void obs_output_set_reconnect_callback(obs_output_t *output, bool (*reconnect_cb)(void *data, obs_output_t *output, int code), void *param) + + Sets a callback that can be used to decide whether or not to attempt reconnecting. + Can also be used to reconfigure the output within the callback before continuing the reconnection attempts, + e.g., to update the stream key after the previous one has expired. + + Passing in a `NULL` pointer removes the callback. + + :param output: The output to register the reconnect_cb() function against + :param reconnect_cb: Function pointer to the callback function + :param param: Data passed to the callback + + reconnect_cb() arguments: + :param data: Data passed to the callback + :param output: The output associated with the invoked callback function + :param code: Error code the output was stopped with + :return: Whether or not to continue attempting to reconnect + + .. versionadded:: 31.1 + Functions used by outputs ------------------------- diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 7190465b8..ae7863389 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -78,6 +78,11 @@ struct packet_callback { void *param; }; +struct reconnect_callback { + bool (*reconnect_cb)(void *data, obs_output_t *output, int code); + void *param; +}; + /* ------------------------------------------------------------------------- */ /* validity checks */ @@ -1150,6 +1155,8 @@ struct obs_output { pthread_mutex_t pkt_callbacks_mutex; DARRAY(struct packet_callback) pkt_callbacks; + struct reconnect_callback reconnect_callback; + bool valid; uint64_t active_delay_ns; diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 6b0ce9af6..2a691548d 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -2874,10 +2874,21 @@ static void output_reconnect(struct obs_output *output) } } -static inline bool can_reconnect(const obs_output_t *output, int code) +static inline bool check_reconnect_cb(obs_output_t *output, int code) +{ + if (!output->reconnect_callback.reconnect_cb) + return true; + + return output->reconnect_callback.reconnect_cb(output->reconnect_callback.param, output, code); +} + +static inline bool can_reconnect(obs_output_t *output, int code) { bool reconnect_active = output->reconnect_retry_max != 0; + if (reconnect_active && !check_reconnect_cb(output, code)) + return false; + return (reconnecting(output) && code != OBS_OUTPUT_SUCCESS) || (reconnect_active && code == OBS_OUTPUT_DISCONNECTED); } @@ -3190,3 +3201,15 @@ void obs_output_remove_packet_callback(obs_output_t *output, da_erase_item(output->pkt_callbacks, &data); pthread_mutex_unlock(&output->pkt_callbacks_mutex); } + +void obs_output_set_reconnect_callback(obs_output_t *output, + bool (*reconnect_cb)(void *data, obs_output_t *output, int code), void *param) +{ + if (!reconnect_cb) { + output->reconnect_callback.reconnect_cb = NULL; + output->reconnect_callback.param = NULL; + } else { + output->reconnect_callback.reconnect_cb = reconnect_cb; + output->reconnect_callback.param = param; + } +} diff --git a/libobs/obs.h b/libobs/obs.h index a2b2b451d..9c738afd6 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -2074,6 +2074,12 @@ EXPORT void obs_output_remove_packet_callback(obs_output_t *output, struct encoder_packet_time *pkt_time, void *param), void *param); +/* Sets a callback to be called when the output checks if it should attempt to reconnect. + * If the callback returns false, the output will not attempt to reconnect. */ +EXPORT void obs_output_set_reconnect_callback(obs_output_t *output, + bool (*reconnect_cb)(void *data, obs_output_t *output, int code), + void *param); + /* ------------------------------------------------------------------------- */ /* Functions used by outputs */