From ffc7b3c666740f75d59f5e6ae31fe9eef287d523 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 10 Feb 2015 21:47:34 -0800 Subject: [PATCH] libobs: Fix multi. video encoder sync issues When using multiple video encoders together with a single audio encoder, the audio wouldn't be in sync. The reason why this occurred is because the dts_usec variable of the encoder packet (which is based on system time) would always be reset to a value based upon the dts (which is not guaranteed to be based on system time) in the apply_interleaved_packet_offset function. This would then in turn cause it to miscalculate the starting audio/video offsets, which are required to calculate sync. So instead of calling that function unnecessarily, separate the check for whether audio/video has been received in to a new function, and only start applying the interleaved offsets after audio and video have actually started up and the starting offsets have been calculated. --- libobs/obs-encoder.c | 5 ++++- libobs/obs-output.c | 38 ++++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index 91d9e4cc4..c2cccb979 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -671,7 +671,7 @@ static bool buffer_audio(struct obs_encoder *encoder, struct audio_data *data) size_t size = data->frames * encoder->blocksize; size_t offset_size = 0; - if (encoder->paired_encoder && !encoder->start_ts) { + if (!encoder->start_ts && encoder->paired_encoder) { uint64_t end_ts = data->timestamp; uint64_t v_start_ts = encoder->paired_encoder->start_ts; @@ -693,6 +693,9 @@ static bool buffer_audio(struct obs_encoder *encoder, struct audio_data *data) } encoder->start_ts = v_start_ts; + + } else if (!encoder->start_ts && !encoder->paired_encoder) { + encoder->start_ts = data->timestamp; } size -= offset_size; diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 13095913a..326add9eb 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -677,7 +677,19 @@ static size_t get_track_index(const struct obs_output *output, return 0; } -static void apply_interleaved_packet_offset(struct obs_output *output, +static inline void check_received(struct obs_output *output, + struct encoder_packet *out) +{ + if (out->type == OBS_ENCODER_VIDEO) { + if (!output->received_video) + output->received_video = true; + } else { + if (!output->received_audio) + output->received_audio = true; + } +} + +static inline void apply_interleaved_packet_offset(struct obs_output *output, struct encoder_packet *out) { int64_t offset; @@ -686,17 +698,8 @@ static void apply_interleaved_packet_offset(struct obs_output *output, * may not currently be at 0 when we get data. so, we store the * current dts as offset and subtract that value from the dts/pts * of the output packet. */ - if (out->type == OBS_ENCODER_VIDEO) { - if (!output->received_video) - output->received_video = true; - - offset = output->video_offset; - } else { - if (!output->received_audio) - output->received_audio = true; - - offset = output->audio_offsets[out->track_idx]; - } + offset = (out->type == OBS_ENCODER_VIDEO) ? + output->video_offset : output->audio_offsets[out->track_idx]; out->dts -= offset; out->pts -= offset; @@ -896,7 +899,12 @@ static void interleave_packets(void *data, struct encoder_packet *packet) was_started = output->received_audio && output->received_video; obs_duplicate_encoder_packet(&out, packet); - apply_interleaved_packet_offset(output, &out); + + if (was_started) + apply_interleaved_packet_offset(output, &out); + else + check_received(output, packet); + insert_interleaved_packet(output, &out); set_higher_ts(output, &out); @@ -1078,7 +1086,9 @@ static inline bool pair_encoders(obs_output_t *output, size_t num_mixes) { if (num_mixes == 1 && !output->audio_encoders[0]->active && - !output->video_encoder->active) { + !output->video_encoder->active && + !output->video_encoder->paired_encoder && + !output->audio_encoders[0]->paired_encoder) { output->audio_encoders[0]->wait_for_video = true; output->audio_encoders[0]->paired_encoder =