提交 ffc7b3c6 编写于 作者: J jp9000

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.
上级 c2832b8b
......@@ -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;
......
......@@ -677,26 +677,29 @@ 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)
{
int64_t offset;
/* audio and video need to start at timestamp 0, and the encoders
* 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];
}
}
static inline void apply_interleaved_packet_offset(struct obs_output *output,
struct encoder_packet *out)
{
int64_t offset;
/* audio and video need to start at timestamp 0, and the encoders
* 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. */
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 =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册