(API Change) libobs: Fix output data cutoff on stop
(Note: This commit also modifies obs-ffmpeg and obs-outputs) API Changed: obs_output_info::void (*stop)(void *data); To: obs_output_info::void (*stop)(void *data, uint64_t ts); This fixes the long-time design flaw where obs_output_stop and the output 'stop' callback would just shut down the output without considering the timing of when obs_output_stop was used, discarding any possible buffering and causing the output to get cut off at an unexpected timing. The 'stop' callback of obs_output_info now takes a timestamp with the expectation that the output will use that timestamp to stop output data in accordance to that timing. obs_output_stop now records the timestamp at the time that the function is called and calls the 'stop' callback with that timestamp. If needed, obs_output_force_stop will still stop the output immediately without buffering.
This commit is contained in:
@@ -63,6 +63,7 @@ struct rtmp_stream {
|
||||
|
||||
os_sem_t *send_sem;
|
||||
os_event_t *stop_event;
|
||||
uint64_t stop_ts;
|
||||
|
||||
struct dstr path, key;
|
||||
struct dstr username, password;
|
||||
@@ -146,6 +147,7 @@ static void rtmp_stream_destroy(void *data)
|
||||
if (stream->connecting)
|
||||
pthread_join(stream->connect_thread, NULL);
|
||||
|
||||
stream->stop_ts = 0;
|
||||
os_event_signal(stream->stop_event);
|
||||
|
||||
if (active(stream)) {
|
||||
@@ -193,7 +195,7 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rtmp_stream_stop(void *data)
|
||||
static void rtmp_stream_stop(void *data, uint64_t ts)
|
||||
{
|
||||
struct rtmp_stream *stream = data;
|
||||
|
||||
@@ -203,11 +205,12 @@ static void rtmp_stream_stop(void *data)
|
||||
if (connecting(stream))
|
||||
pthread_join(stream->connect_thread, NULL);
|
||||
|
||||
stream->stop_ts = ts / 1000ULL;
|
||||
os_event_signal(stream->stop_event);
|
||||
|
||||
if (active(stream)) {
|
||||
os_sem_post(stream->send_sem);
|
||||
obs_output_end_data_capture(stream->output);
|
||||
if (stream->stop_ts == 0)
|
||||
os_sem_post(stream->send_sem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,11 +325,20 @@ static void *send_thread(void *data)
|
||||
while (os_sem_wait(stream->send_sem) == 0) {
|
||||
struct encoder_packet packet;
|
||||
|
||||
if (stopping(stream))
|
||||
if (stopping(stream) && stream->stop_ts == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!get_next_packet(stream, &packet))
|
||||
continue;
|
||||
|
||||
if (stopping(stream)) {
|
||||
if (packet.sys_dts_usec >= (int64_t)stream->stop_ts) {
|
||||
obs_free_encoder_packet(&packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stream->sent_headers) {
|
||||
if (!send_headers(stream)) {
|
||||
os_atomic_set_bool(&stream->disconnected, true);
|
||||
@@ -351,6 +363,8 @@ static void *send_thread(void *data)
|
||||
if (!stopping(stream)) {
|
||||
pthread_detach(stream->send_thread);
|
||||
obs_output_signal_stop(stream->output, OBS_OUTPUT_DISCONNECTED);
|
||||
} else {
|
||||
obs_output_end_data_capture(stream->output);
|
||||
}
|
||||
|
||||
free_packets(stream);
|
||||
@@ -795,7 +809,7 @@ static void rtmp_stream_data(void *data, struct encoder_packet *packet)
|
||||
struct encoder_packet new_packet;
|
||||
bool added_packet = false;
|
||||
|
||||
if (disconnected(stream))
|
||||
if (disconnected(stream) || !active(stream))
|
||||
return;
|
||||
|
||||
if (packet->type == OBS_ENCODER_VIDEO)
|
||||
|
Reference in New Issue
Block a user