From d966742a6317b1f1ed1aaaef8fa64ac62c6f79d8 Mon Sep 17 00:00:00 2001 From: Ruwen Hahn Date: Fri, 9 Feb 2024 14:32:54 +0100 Subject: [PATCH] libobs: Fix `highest_video_ts` tracking Calling `set_higher_ts` before offsets are known pollutes `highest_video_ts` with timestamps that are out of range of actual timestamps. They're generally somewhere high above 0 until an offset for all streams is found, where they are then reset to 0 or slightly below 0 in the presence of b-frames. `highest_video_ts` also needs to start below 0 for the same reason. Even with timestamps being reset to close to 0, b-frames will cause initial DTS to drop below 0, thus we need a value that should "always" be below any "real" timestamps observed. `highest_video_ts` tracking now only starts once all input streams are ready, and is computed based on all buffered packets at that point. --- libobs/obs-output.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 49459c31e..566432eb0 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -1919,11 +1919,6 @@ static bool initialize_interleaved_packets(struct obs_output *output) /* subtract offsets from highest TS offset variables */ output->highest_audio_ts -= audio[first_audio_idx]->dts_usec; - for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) { - if (video[i]) - output->highest_video_ts[i] -= video[i]->dts_usec; - } - /* apply new offsets to all existing packet DTS/PTS values */ for (size_t i = 0; i < output->interleaved_packets.num; i++) { struct encoder_packet *packet = @@ -1970,8 +1965,11 @@ static void resort_interleaved_packets(struct obs_output *output) memset(&output->interleaved_packets, 0, sizeof(output->interleaved_packets)); - for (size_t i = 0; i < old_array.num; i++) + for (size_t i = 0; i < old_array.num; i++) { + set_higher_ts(output, &old_array.array[i]); + insert_interleaved_packet(output, &old_array.array[i]); + } da_free(old_array); } @@ -2119,7 +2117,6 @@ static void interleave_packets(void *data, struct encoder_packet *packet) check_received(output, packet); insert_interleaved_packet(output, &out); - set_higher_ts(output, &out); received_video = true; for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) { @@ -2139,6 +2136,8 @@ static void interleave_packets(void *data, struct encoder_packet *packet) } } } else { + set_higher_ts(output, &out); + send_interleaved(output); } } @@ -2322,7 +2321,7 @@ static void reset_packet_data(obs_output_t *output) for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) { output->received_video[i] = false; output->video_offsets[i] = 0; - output->highest_video_ts[i] = 0; + output->highest_video_ts[i] = INT64_MIN; } for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) output->audio_offsets[i] = 0;