mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-08-29 02:03:03 +08:00
libobs: Pair video encoder with all audio encoders
This commit is contained in:
+16
-9
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user