فهرست منبع

obs-ffmpeg: Make FFmpeg audio encoder abstractable

Abstracts the FFmpeg audio encoder to allow other codecs to use the same
code, and makes the AAC encoder derived from it.
jp9000 8 سال پیش
والد
کامیت
0089d379b0
1فایلهای تغییر یافته به همراه49 افزوده شده و 38 حذف شده
  1. 49 38
      plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c

+ 49 - 38
plugins/obs-ffmpeg/obs-ffmpeg-audio-encoders.c

@@ -26,17 +26,21 @@
 #include "obs-ffmpeg-compat.h"
 
 #define do_log(level, format, ...) \
-	blog(level, "[FFmpeg aac encoder: '%s'] " format, \
-			obs_encoder_get_name(enc->encoder), ##__VA_ARGS__)
+	blog(level, "[FFmpeg %s encoder: '%s'] " format, \
+			enc->type, \
+			obs_encoder_get_name(enc->encoder), \
+			##__VA_ARGS__)
 
 #define warn(format, ...)  do_log(LOG_WARNING, format, ##__VA_ARGS__)
 #define info(format, ...)  do_log(LOG_INFO,    format, ##__VA_ARGS__)
 #define debug(format, ...) do_log(LOG_DEBUG,   format, ##__VA_ARGS__)
 
-struct aac_encoder {
+struct enc_encoder {
 	obs_encoder_t    *encoder;
 
-	AVCodec          *aac;
+	const char       *type;
+
+	AVCodec          *codec;
 	AVCodecContext   *context;
 
 	uint8_t          *samples[MAX_AV_PLANES];
@@ -58,9 +62,9 @@ static const char *aac_getname(void *unused)
 	return obs_module_text("FFmpegAAC");
 }
 
-static void aac_destroy(void *data)
+static void enc_destroy(void *data)
 {
-	struct aac_encoder *enc = data;
+	struct enc_encoder *enc = data;
 
 	if (enc->samples[0])
 		av_freep(&enc->samples[0]);
@@ -73,7 +77,7 @@ static void aac_destroy(void *data)
 	bfree(enc);
 }
 
-static bool initialize_codec(struct aac_encoder *enc)
+static bool initialize_codec(struct enc_encoder *enc)
 {
 	int ret;
 
@@ -83,7 +87,7 @@ static bool initialize_codec(struct aac_encoder *enc)
 		return false;
 	}
 
-	ret = avcodec_open2(enc->context, enc->aac, NULL);
+	ret = avcodec_open2(enc->context, enc->codec, NULL);
 	if (ret < 0) {
 		warn("Failed to open AAC codec: %s", av_err2str(ret));
 		return false;
@@ -105,7 +109,7 @@ static bool initialize_codec(struct aac_encoder *enc)
 	return true;
 }
 
-static void init_sizes(struct aac_encoder *enc, audio_t *audio)
+static void init_sizes(struct enc_encoder *enc, audio_t *audio)
 {
 	const struct audio_output_info *aoi;
 	enum audio_format format;
@@ -121,21 +125,23 @@ static void init_sizes(struct aac_encoder *enc, audio_t *audio)
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 #endif
 
-static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
+static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder,
+		const char *type)
 {
-	struct aac_encoder *enc;
+	struct enc_encoder *enc;
 	int                bitrate = (int)obs_data_get_int(settings, "bitrate");
 	audio_t            *audio   = obs_encoder_audio(encoder);
 
 	avcodec_register_all();
 
-	enc          = bzalloc(sizeof(struct aac_encoder));
+	enc          = bzalloc(sizeof(struct enc_encoder));
 	enc->encoder = encoder;
-	enc->aac     = avcodec_find_encoder(AV_CODEC_ID_AAC);
+	enc->codec   = avcodec_find_encoder_by_name(type);
+	enc->type    = type;
 
 	blog(LOG_INFO, "---------------------------------");
 
-	if (!enc->aac) {
+	if (!enc->codec) {
 		warn("Couldn't find encoder");
 		goto fail;
 	}
@@ -145,7 +151,7 @@ static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
 		return NULL;
 	}
 
-	enc->context = avcodec_alloc_context3(enc->aac);
+	enc->context = avcodec_alloc_context3(enc->codec);
 	if (!enc->context) {
 		warn("Failed to create codec context");
 		goto fail;
@@ -154,12 +160,12 @@ static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
 	enc->context->bit_rate    = bitrate * 1000;
 	enc->context->channels    = (int)audio_output_get_channels(audio);
 	enc->context->sample_rate = audio_output_get_sample_rate(audio);
-	enc->context->sample_fmt  = enc->aac->sample_fmts ?
-		enc->aac->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
+	enc->context->sample_fmt  = enc->codec->sample_fmts ?
+		enc->codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
 
 	/* if using FFmpeg's AAC encoder, at least set a cutoff value
 	 * (recommended by konverter) */
-	if (strcmp(enc->aac->name, "aac") == 0) {
+	if (strcmp(enc->codec->name, "aac") == 0) {
 		int cutoff1 = 4000 + (int)enc->context->bit_rate / 8;
 		int cutoff2 = 12000 + (int)enc->context->bit_rate / 8;
 		int cutoff3 = enc->context->sample_rate / 2;
@@ -184,11 +190,16 @@ static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
 		return enc;
 
 fail:
-	aac_destroy(enc);
+	enc_destroy(enc);
 	return NULL;
 }
 
-static bool do_aac_encode(struct aac_encoder *enc,
+static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
+{
+	return enc_create(settings, encoder, "aac");
+}
+
+static bool do_encode(struct enc_encoder *enc,
 		struct encoder_packet *packet, bool *received_packet)
 {
 	AVRational time_base = {1, enc->context->sample_rate};
@@ -236,23 +247,23 @@ static bool do_aac_encode(struct aac_encoder *enc,
 	return true;
 }
 
-static bool aac_encode(void *data, struct encoder_frame *frame,
+static bool enc_encode(void *data, struct encoder_frame *frame,
 		struct encoder_packet *packet, bool *received_packet)
 {
-	struct aac_encoder *enc = data;
+	struct enc_encoder *enc = data;
 
 	for (size_t i = 0; i < enc->audio_planes; i++)
 		memcpy(enc->samples[i], frame->data[i], enc->frame_size_bytes);
 
-	return do_aac_encode(enc, packet, received_packet);
+	return do_encode(enc, packet, received_packet);
 }
 
-static void aac_defaults(obs_data_t *settings)
+static void enc_defaults(obs_data_t *settings)
 {
 	obs_data_set_default_int(settings, "bitrate", 128);
 }
 
-static obs_properties_t *aac_properties(void *unused)
+static obs_properties_t *enc_properties(void *unused)
 {
 	UNUSED_PARAMETER(unused);
 
@@ -263,24 +274,24 @@ static obs_properties_t *aac_properties(void *unused)
 	return props;
 }
 
-static bool aac_extra_data(void *data, uint8_t **extra_data, size_t *size)
+static bool enc_extra_data(void *data, uint8_t **extra_data, size_t *size)
 {
-	struct aac_encoder *enc = data;
+	struct enc_encoder *enc = data;
 
 	*extra_data = enc->context->extradata;
 	*size       = enc->context->extradata_size;
 	return true;
 }
 
-static void aac_audio_info(void *data, struct audio_convert_info *info)
+static void enc_audio_info(void *data, struct audio_convert_info *info)
 {
-	struct aac_encoder *enc = data;
+	struct enc_encoder *enc = data;
 	info->format = convert_ffmpeg_sample_format(enc->context->sample_fmt);
 }
 
-static size_t aac_frame_size(void *data)
+static size_t enc_frame_size(void *data)
 {
-	struct aac_encoder *enc =data;
+	struct enc_encoder *enc =data;
 	return enc->frame_size;
 }
 
@@ -290,11 +301,11 @@ struct obs_encoder_info aac_encoder_info = {
 	.codec          = "AAC",
 	.get_name       = aac_getname,
 	.create         = aac_create,
-	.destroy        = aac_destroy,
-	.encode         = aac_encode,
-	.get_frame_size = aac_frame_size,
-	.get_defaults   = aac_defaults,
-	.get_properties = aac_properties,
-	.get_extra_data = aac_extra_data,
-	.get_audio_info = aac_audio_info
+	.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
 };