diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c b/plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c index 24b686a95..1648687bf 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c @@ -210,7 +210,8 @@ static void init_sizes(struct enc_encoder *enc, audio_t *audio) #endif static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder, - const char *type, const char *alt) + const char *type, const char *alt, + enum AVSampleFormat sample_format) { struct enc_encoder *enc; int bitrate = (int)obs_data_get_int(settings, "bitrate"); @@ -283,9 +284,27 @@ static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder, #endif enc->context->sample_rate = audio_output_get_sample_rate(audio); - enc->context->sample_fmt = enc->codec->sample_fmts - ? enc->codec->sample_fmts[0] - : AV_SAMPLE_FMT_FLTP; + + if (enc->codec->sample_fmts) { + /* Check if the requested format is actually available for the specified + * encoder. This may not always be the case due to FFmpeg changes or a + * fallback being used (for example, when libopus is unavailable). */ + enum AVSampleFormat fmt = enc->codec->sample_fmts[0]; + while (fmt != AV_SAMPLE_FMT_NONE) { + if (fmt == sample_format) { + enc->context->sample_fmt = fmt; + break; + } + fmt++; + } + + /* Fall back to default if requested format was not found. */ + if (enc->context->sample_fmt == AV_SAMPLE_FMT_NONE) + enc->context->sample_fmt = enc->codec->sample_fmts[0]; + } else { + /* Fall back to planar float if codec does not specify formats. */ + enc->context->sample_fmt = AV_SAMPLE_FMT_FLTP; + } /* check to make sure sample rate is supported */ if (enc->codec->supported_samplerates) { @@ -335,37 +354,41 @@ fail: static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "aac", NULL); + return enc_create(settings, encoder, "aac", NULL, AV_SAMPLE_FMT_NONE); } static void *opus_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "libopus", "opus"); + return enc_create(settings, encoder, "libopus", "opus", + AV_SAMPLE_FMT_FLT); } static void *pcm_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "pcm_s16le", NULL); + return enc_create(settings, encoder, "pcm_s16le", NULL, + AV_SAMPLE_FMT_NONE); } static void *pcm24_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "pcm_s24le", NULL); + return enc_create(settings, encoder, "pcm_s24le", NULL, + AV_SAMPLE_FMT_NONE); } static void *pcm32_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "pcm_f32le", NULL); + return enc_create(settings, encoder, "pcm_f32le", NULL, + AV_SAMPLE_FMT_NONE); } static void *alac_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "alac", NULL); + return enc_create(settings, encoder, "alac", NULL, AV_SAMPLE_FMT_S32P); } static void *flac_create(obs_data_t *settings, obs_encoder_t *encoder) { - return enc_create(settings, encoder, "flac", NULL); + return enc_create(settings, encoder, "flac", NULL, AV_SAMPLE_FMT_S16); } static bool do_encode(struct enc_encoder *enc, struct encoder_packet *packet,