Merge pull request #8289 from derrod/more-audio-codecs

libobs,obs-ffmpeg: Add option for recording lossless audio
This commit is contained in:
Jim
2023-03-25 16:52:49 -07:00
committed by GitHub
6 changed files with 190 additions and 8 deletions
+5
View File
@@ -1,6 +1,11 @@
FFmpegOutput="FFmpeg Output"
FFmpegAAC="FFmpeg AAC"
FFmpegOpus="FFmpeg Opus"
FFmpegALAC="FFmpeg ALAC (24-bit)"
FFmpegFLAC="FFmpeg FLAC (16-bit)"
FFmpegPCM16Bit="FFmpeg PCM (16-bit)"
FFmpegPCM24Bit="FFmpeg PCM (24-bit)"
FFmpegPCM32BitFloat="FFmpeg PCM (32-bit float)"
FFmpegOpts="FFmpeg Options"
FFmpegOpts.ToolTip.Source="Allows you to set FFmpeg options. This only accepts options in the option=value format.\nMultiple options can be set by separating them with a space.\nExample: rtsp_transport=tcp rtsp_flags=prefer_tcp"
Bitrate="Bitrate"
+14 -4
View File
@@ -526,7 +526,14 @@ static void create_audio_stream(struct ffmpeg_mux *ffm, int idx)
const char *name = ffm->params.acodec;
int channels;
const AVCodecDescriptor *codec = avcodec_descriptor_get_by_name(name);
const AVCodecDescriptor *codec_desc =
avcodec_descriptor_get_by_name(name);
if (!codec_desc) {
fprintf(stderr, "Couldn't find codec descriptor '%s'\n", name);
return;
}
const AVCodec *codec = avcodec_find_encoder(codec_desc->id);
if (!codec) {
fprintf(stderr, "Couldn't find codec '%s'\n", name);
return;
@@ -547,14 +554,17 @@ static void create_audio_stream(struct ffmpeg_mux *ffm, int idx)
context = avcodec_alloc_context3(NULL);
context->codec_type = codec->type;
context->codec_id = codec->id;
context->bit_rate = (int64_t)ffm->audio[idx].abitrate * 1000;
if (!(codec_desc->props & AV_CODEC_PROP_LOSSLESS))
context->bit_rate = (int64_t)ffm->audio[idx].abitrate * 1000;
channels = ffm->audio[idx].channels;
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 24, 100)
context->channels = channels;
#endif
context->sample_rate = ffm->audio[idx].sample_rate;
context->frame_size = ffm->audio[idx].frame_size;
context->sample_fmt = AV_SAMPLE_FMT_S16;
if (!(codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE))
context->frame_size = ffm->audio[idx].frame_size;
context->time_base = stream->time_base;
context->extradata = extradata;
context->extradata_size = ffm->audio_header[idx].size;
+152 -3
View File
@@ -95,6 +95,36 @@ static const char *opus_getname(void *unused)
return obs_module_text("FFmpegOpus");
}
static const char *pcm_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("FFmpegPCM16Bit");
}
static const char *pcm24_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("FFmpegPCM24Bit");
}
static const char *pcm32_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("FFmpegPCM32BitFloat");
}
static const char *alac_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("FFmpegALAC");
}
static const char *flac_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("FFmpegFLAC");
}
static void enc_destroy(void *data)
{
struct enc_encoder *enc = data;
@@ -207,9 +237,17 @@ static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder,
goto fail;
}
if (!bitrate) {
const AVCodecDescriptor *codec_desc =
avcodec_descriptor_get(enc->codec->id);
if (!codec_desc) {
warn("Failed to get codec descriptor");
goto fail;
}
if (!bitrate && !(codec_desc->props & AV_CODEC_PROP_LOSSLESS)) {
warn("Invalid bitrate specified");
return NULL;
goto fail;
}
enc->context = avcodec_alloc_context3(enc->codec);
@@ -218,7 +256,12 @@ static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder,
goto fail;
}
enc->context->bit_rate = bitrate * 1000;
if (codec_desc->props & AV_CODEC_PROP_LOSSLESS)
// Set by encoder on init, not known at this time
enc->context->bit_rate = -1;
else
enc->context->bit_rate = bitrate * 1000;
const struct audio_output_info *aoi;
aoi = audio_output_get_info(audio);
@@ -300,6 +343,31 @@ static void *opus_create(obs_data_t *settings, obs_encoder_t *encoder)
return enc_create(settings, encoder, "libopus", "opus");
}
static void *pcm_create(obs_data_t *settings, obs_encoder_t *encoder)
{
return enc_create(settings, encoder, "pcm_s16le", NULL);
}
static void *pcm24_create(obs_data_t *settings, obs_encoder_t *encoder)
{
return enc_create(settings, encoder, "pcm_s24le", NULL);
}
static void *pcm32_create(obs_data_t *settings, obs_encoder_t *encoder)
{
return enc_create(settings, encoder, "pcm_f32le", NULL);
}
static void *alac_create(obs_data_t *settings, obs_encoder_t *encoder)
{
return enc_create(settings, encoder, "alac", NULL);
}
static void *flac_create(obs_data_t *settings, obs_encoder_t *encoder)
{
return enc_create(settings, encoder, "flac", NULL);
}
static bool do_encode(struct enc_encoder *enc, struct encoder_packet *packet,
bool *received_packet)
{
@@ -418,6 +486,12 @@ static void enc_audio_info(void *data, struct audio_convert_info *info)
info->speakers = SPEAKERS_UNKNOWN;
}
static void enc_audio_info_float(void *data, struct audio_convert_info *info)
{
enc_audio_info(data, info);
info->allow_clipping = true;
}
static size_t enc_frame_size(void *data)
{
struct enc_encoder *enc = data;
@@ -453,3 +527,78 @@ struct obs_encoder_info opus_encoder_info = {
.get_extra_data = enc_extra_data,
.get_audio_info = enc_audio_info,
};
struct obs_encoder_info pcm_encoder_info = {
.id = "ffmpeg_pcm_s16le",
.type = OBS_ENCODER_AUDIO,
.codec = "pcm_s16le",
.get_name = pcm_getname,
.create = pcm_create,
.destroy = enc_destroy,
.encode = enc_encode,
.get_frame_size = enc_frame_size,
.get_defaults = enc_defaults,
.get_properties = enc_properties,
.get_extra_data = enc_extra_data,
.get_audio_info = enc_audio_info,
};
struct obs_encoder_info pcm24_encoder_info = {
.id = "ffmpeg_pcm_s24le",
.type = OBS_ENCODER_AUDIO,
.codec = "pcm_s24le",
.get_name = pcm24_getname,
.create = pcm24_create,
.destroy = enc_destroy,
.encode = enc_encode,
.get_frame_size = enc_frame_size,
.get_defaults = enc_defaults,
.get_properties = enc_properties,
.get_extra_data = enc_extra_data,
.get_audio_info = enc_audio_info,
};
struct obs_encoder_info pcm32_encoder_info = {
.id = "ffmpeg_pcm_f32le",
.type = OBS_ENCODER_AUDIO,
.codec = "pcm_f32le",
.get_name = pcm32_getname,
.create = pcm32_create,
.destroy = enc_destroy,
.encode = enc_encode,
.get_frame_size = enc_frame_size,
.get_defaults = enc_defaults,
.get_properties = enc_properties,
.get_extra_data = enc_extra_data,
.get_audio_info = enc_audio_info_float,
};
struct obs_encoder_info alac_encoder_info = {
.id = "ffmpeg_alac",
.type = OBS_ENCODER_AUDIO,
.codec = "alac",
.get_name = alac_getname,
.create = alac_create,
.destroy = enc_destroy,
.encode = enc_encode,
.get_frame_size = enc_frame_size,
.get_defaults = enc_defaults,
.get_properties = enc_properties,
.get_extra_data = enc_extra_data,
.get_audio_info = enc_audio_info,
};
struct obs_encoder_info flac_encoder_info = {
.id = "ffmpeg_flac",
.type = OBS_ENCODER_AUDIO,
.codec = "flac",
.get_name = flac_getname,
.create = flac_create,
.destroy = enc_destroy,
.encode = enc_encode,
.get_frame_size = enc_frame_size,
.get_defaults = enc_defaults,
.get_properties = enc_properties,
.get_extra_data = enc_extra_data,
.get_audio_info = enc_audio_info,
};
+10
View File
@@ -36,6 +36,11 @@ extern struct obs_output_info replay_buffer;
extern struct obs_output_info ffmpeg_hls_muxer;
extern struct obs_encoder_info aac_encoder_info;
extern struct obs_encoder_info opus_encoder_info;
extern struct obs_encoder_info pcm_encoder_info;
extern struct obs_encoder_info pcm24_encoder_info;
extern struct obs_encoder_info pcm32_encoder_info;
extern struct obs_encoder_info alac_encoder_info;
extern struct obs_encoder_info flac_encoder_info;
extern struct obs_encoder_info h264_nvenc_encoder_info;
#ifdef ENABLE_HEVC
extern struct obs_encoder_info hevc_nvenc_encoder_info;
@@ -387,6 +392,11 @@ bool obs_module_load(void)
register_encoder_if_available(&svt_av1_encoder_info, "libsvtav1");
register_encoder_if_available(&aom_av1_encoder_info, "libaom-av1");
obs_register_encoder(&opus_encoder_info);
obs_register_encoder(&pcm_encoder_info);
obs_register_encoder(&pcm24_encoder_info);
obs_register_encoder(&pcm32_encoder_info);
obs_register_encoder(&alac_encoder_info);
obs_register_encoder(&flac_encoder_info);
#ifndef __APPLE__
bool h264 = false;
bool hevc = false;