diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index f6a5e3713..400b36600 100644 --- a/libobs/media-io/audio-io.c +++ b/libobs/media-io/audio-io.c @@ -24,6 +24,7 @@ #include "../util/platform.h" #include "audio-io.h" +#include "audio-resampler.h" /* #define DEBUG_AUDIO */ @@ -31,10 +32,17 @@ struct audio_input { struct audio_convert_info conversion; + audio_resampler_t resampler; + void (*callback)(void *param, const struct audio_data *data); void *param; }; +static inline audio_input_free(struct audio_input *input) +{ + audio_resampler_destroy(input->resampler); +} + struct audio_line { char *name; @@ -313,6 +321,31 @@ static inline bool mix_audio_line(struct audio_output *audio, return true; } +static bool resample_audio_output(struct audio_input *input, + struct audio_data *data) +{ + bool success = true; + + if (input->resampler) { + uint8_t *output[MAX_AV_PLANES]; + uint32_t frames; + uint64_t offset; + + memset(output, 0, sizeof(output)); + + success = audio_resampler_resample(input->resampler, + output, &frames, &offset, + data->data, data->frames); + + for (size_t i = 0; i < MAX_AV_PLANES; i++) + data->data[i] = output[i]; + data->frames = frames; + data->timestamp -= offset; + } + + return success; +} + static inline void do_audio_output(struct audio_output *audio, uint64_t timestamp, uint32_t frames) { @@ -323,12 +356,15 @@ static inline void do_audio_output(struct audio_output *audio, data.timestamp = timestamp; data.volume = 1.0f; - /* TODO: conversion */ pthread_mutex_lock(&audio->input_mutex); + for (size_t i = 0; i < audio->inputs.num; i++) { struct audio_input *input = audio->inputs.array+i; - input->callback(input->param, &data); + + if (resample_audio_output(input, &data)) + input->callback(input->param, &data); } + pthread_mutex_unlock(&audio->input_mutex); } @@ -429,6 +465,30 @@ static size_t audio_get_input_idx(audio_t video, return DARRAY_INVALID; } +static inline void audio_input_init(struct audio_input *input, + struct audio_output *audio) +{ + if (input->conversion.format != audio->info.format || + input->conversion.samples_per_sec != audio->info.samples_per_sec || + input->conversion.speakers != audio->info.speakers) { + struct resample_info from = { + .format = audio->info.format, + .samples_per_sec = audio->info.samples_per_sec, + .speakers = audio->info.speakers + }; + + struct resample_info to = { + .format = input->conversion.format, + .samples_per_sec = input->conversion.samples_per_sec, + .speakers = input->conversion.speakers + }; + + input->resampler = audio_resampler_create(&to, &from); + } else { + input->resampler = NULL; + } +} + void audio_output_connect(audio_t audio, struct audio_convert_info *conversion, void (*callback)(void *param, const struct audio_data *data), @@ -441,7 +501,6 @@ void audio_output_connect(audio_t audio, input.callback = callback; input.param = param; - /* TODO: conversion */ if (conversion) { input.conversion = *conversion; } else { @@ -451,6 +510,7 @@ void audio_output_connect(audio_t audio, audio->info.samples_per_sec; } + audio_input_init(&input, audio); da_push_back(audio->inputs, &input); } @@ -464,8 +524,10 @@ void audio_output_disconnect(audio_t audio, pthread_mutex_lock(&audio->input_mutex); size_t idx = audio_get_input_idx(audio, callback, param); - if (idx != DARRAY_INVALID) + if (idx != DARRAY_INVALID) { + audio_input_free(audio->inputs.array+idx); da_erase(audio->inputs, idx); + } pthread_mutex_unlock(&audio->input_mutex); } @@ -536,9 +598,13 @@ void audio_output_close(audio_t audio) line = next; } + for (size_t i = 0; i < audio->inputs.num; i++) + audio_input_free(audio->inputs.array+i); + for (size_t i = 0; i < MAX_AV_PLANES; i++) da_free(audio->mix_buffers[i]); + da_free(audio->inputs); event_destroy(&audio->stop_event); pthread_mutex_destroy(&audio->line_mutex); bfree(audio); diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index 8ad83a7b4..85e4594f9 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -576,7 +576,7 @@ static bool ffmpeg_output_start(void *data) struct audio_convert_info aci; aci.samples_per_sec = SPS_TODO; - aci.format = AUDIO_FORMAT_FLOAT; + aci.format = AUDIO_FORMAT_FLOAT_PLANAR; aci.speakers = SPEAKERS_STEREO; struct video_convert_info vci;