Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion libobs/media-io/audio-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static inline void audio_input_free(struct audio_input *input)
struct audio_mix {
DARRAY(struct audio_input) inputs;
float buffer[MAX_AUDIO_CHANNELS][AUDIO_OUTPUT_FRAMES];
float buffer_unclamped[MAX_AUDIO_CHANNELS][AUDIO_OUTPUT_FRAMES];
};

struct audio_output {
Expand Down Expand Up @@ -116,8 +117,12 @@ static inline void do_audio_output(struct audio_output *audio, size_t mix_idx,
for (size_t i = mix->inputs.num; i > 0; i--) {
struct audio_input *input = mix->inputs.array + (i - 1);

float(*buf)[AUDIO_OUTPUT_FRAMES] =
input->conversion.allow_clipping ? mix->buffer_unclamped
: mix->buffer;
for (size_t i = 0; i < audio->planes; i++)
data.data[i] = (uint8_t *)mix->buffer[i];
data.data[i] = (uint8_t *)buf[i];

data.frames = frames;
data.timestamp = timestamp;

Expand All @@ -142,6 +147,8 @@ static inline void clamp_audio_output(struct audio_output *audio, size_t bytes)
for (size_t plane = 0; plane < audio->planes; plane++) {
float *mix_data = mix->buffer[plane];
float *mix_end = &mix_data[float_size];
/* Unclamped mix is copied directly. */
memcpy(mix->buffer_unclamped[plane], mix_data, bytes);

while (mix_data < mix_end) {
float val = *mix_data;
Expand Down
1 change: 1 addition & 0 deletions libobs/media-io/audio-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct audio_convert_info {
uint32_t samples_per_sec;
enum audio_format format;
enum speaker_layout speakers;
bool allow_clipping;
};

static inline uint32_t get_audio_channels(enum speaker_layout speakers)
Expand Down
5 changes: 5 additions & 0 deletions plugins/obs-ffmpeg/data/locale/en-US.ini
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
18 changes: 14 additions & 4 deletions plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
155 changes: 152 additions & 3 deletions plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 changes: 10 additions & 0 deletions plugins/obs-ffmpeg/obs-ffmpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down