libobs: Pair video encoder with all audio encoders

This commit is contained in:
derrod
2023-12-03 18:41:39 +01:00
committed by Lain
parent b680700bba
commit ca865f80cc
4 changed files with 49 additions and 38 deletions
+16 -9
View File
@@ -678,7 +678,7 @@ void obs_encoder_shutdown(obs_encoder_t *encoder)
if (encoder->context.data) {
encoder->info.destroy(encoder->context.data);
encoder->context.data = NULL;
encoder->paired_encoder = NULL;
da_free(encoder->paired_encoders);
encoder->first_received = false;
encoder->offset_usec = 0;
encoder->start_ts = 0;
@@ -1371,13 +1371,15 @@ static void receive_video(void *param, struct video_data *frame)
profile_start(receive_video_name);
struct obs_encoder *encoder = param;
struct obs_encoder *pair = encoder->paired_encoder;
struct obs_encoder **paired = encoder->paired_encoders.array;
struct encoder_frame enc_frame;
if (!encoder->first_received && pair) {
if (!pair->first_received ||
pair->first_raw_ts > frame->timestamp) {
goto wait_for_audio;
if (!encoder->first_received && encoder->paired_encoders.num) {
for (size_t i = 0; i < encoder->paired_encoders.num; i++) {
if (!paired[i]->first_received ||
paired[i]->first_raw_ts > frame->timestamp) {
goto wait_for_audio;
}
}
}
@@ -1465,9 +1467,14 @@ static bool buffer_audio(struct obs_encoder *encoder, struct audio_data *data)
size_t offset_size = 0;
bool success = true;
if (!encoder->start_ts && encoder->paired_encoder) {
struct obs_encoder *paired_encoder = NULL;
/* Audio encoders can only be paired to one video encoder */
if (encoder->paired_encoders.num)
paired_encoder = encoder->paired_encoders.array[0];
if (!encoder->start_ts && paired_encoder) {
uint64_t end_ts = data->timestamp;
uint64_t v_start_ts = encoder->paired_encoder->start_ts;
uint64_t v_start_ts = paired_encoder->start_ts;
/* no video yet, so don't start audio */
if (!v_start_ts) {
@@ -1498,7 +1505,7 @@ static bool buffer_audio(struct obs_encoder *encoder, struct audio_data *data)
start_from_buffer(encoder, v_start_ts);
}
} else if (!encoder->start_ts && !encoder->paired_encoder) {
} else if (!encoder->start_ts && !paired_encoder) {
encoder->start_ts = data->timestamp;
}
+1 -1
View File
@@ -1248,7 +1248,7 @@ struct obs_encoder {
* up at the specific timestamp. if this is the audio encoder,
* it waits until it's ready to sync up with video */
bool first_received;
struct obs_encoder *paired_encoder;
DARRAY(struct obs_encoder *) paired_encoders;
int64_t offset_usec;
uint64_t first_raw_ts;
uint64_t start_ts;
+16 -23
View File
@@ -2376,39 +2376,32 @@ static inline bool initialize_video_encoders(obs_output_t *output)
return true;
}
static inline obs_encoder_t *find_inactive_audio_encoder(obs_output_t *output)
{
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
struct obs_encoder *audio = output->audio_encoders[i];
if (audio && !audio->active && !audio->paired_encoder)
return audio;
}
return NULL;
}
static inline void pair_encoders(obs_output_t *output)
{
size_t first_venc_idx;
if (!get_first_video_encoder_index(output, &first_venc_idx))
return;
struct obs_encoder *video = output->video_encoders[first_venc_idx];
struct obs_encoder *audio = find_inactive_audio_encoder(output);
if (video && audio) {
pthread_mutex_lock(&audio->init_mutex);
pthread_mutex_lock(&video->init_mutex);
if (!audio->active && !video->active &&
!video->paired_encoder && !audio->paired_encoder) {
audio->paired_encoder = video;
video->paired_encoder = audio;
}
pthread_mutex_lock(&video->init_mutex);
if (video->active) {
pthread_mutex_unlock(&video->init_mutex);
return;
}
for (size_t i = 0; i < MAX_OUTPUT_AUDIO_ENCODERS; i++) {
struct obs_encoder *audio = output->audio_encoders[i];
if (!audio)
continue;
pthread_mutex_lock(&audio->init_mutex);
if (!audio->active && !audio->paired_encoders.num) {
da_push_back(video->paired_encoders, &audio);
da_push_back(audio->paired_encoders, &video);
}
pthread_mutex_unlock(&audio->init_mutex);
}
pthread_mutex_unlock(&video->init_mutex);
}
bool obs_output_initialize_encoders(obs_output_t *output, uint32_t flags)
+16 -5
View File
@@ -73,18 +73,29 @@ static void *gpu_encode_thread(struct obs_core_video_mix *video)
uint32_t skip = 0;
obs_encoder_t *encoder = encoders.array[i];
struct obs_encoder *pair = encoder->paired_encoder;
struct obs_encoder **paired =
encoder->paired_encoders.array;
size_t num_paired = encoder->paired_encoders.num;
pkt.timebase_num = encoder->timebase_num *
encoder->frame_rate_divisor;
pkt.timebase_den = encoder->timebase_den;
pkt.encoder = encoder;
if (!encoder->first_received && pair) {
if (!pair->first_received ||
pair->first_raw_ts > timestamp) {
continue;
if (!encoder->first_received && num_paired) {
bool wait_for_audio = false;
for (size_t idx = 0; idx < num_paired; idx++) {
if (!paired[idx]->first_received ||
paired[idx]->first_raw_ts >
timestamp) {
wait_for_audio = true;
break;
}
}
if (wait_for_audio)
continue;
}
if (video_pause_check(&encoder->pause, timestamp))