diff --git a/src/mod/applications/mod_av/autoload_configs/av.conf.xml b/src/mod/applications/mod_av/autoload_configs/av.conf.xml
index cf28fab3d3..27b8140094 100644
--- a/src/mod/applications/mod_av/autoload_configs/av.conf.xml
+++ b/src/mod/applications/mod_av/autoload_configs/av.conf.xml
@@ -11,10 +11,6 @@
-
-
-
-
@@ -28,7 +24,7 @@
-
+
diff --git a/src/mod/applications/mod_av/avcodec.c b/src/mod/applications/mod_av/avcodec.c
index c0f8ccf293..4ce30d8e51 100644
--- a/src/mod/applications/mod_av/avcodec.c
+++ b/src/mod/applications/mod_av/avcodec.c
@@ -406,7 +406,7 @@ typedef struct h264_codec_context_s {
static uint8_t ff_input_buffer_padding[AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
-#define MAX_CODECS 4
+#define MAX_PROFILES 100
typedef struct avcodec_profile_s {
char name[20];
@@ -420,32 +420,83 @@ struct avcodec_globals {
uint32_t max_bitrate;
uint32_t rtp_slice_size;
uint32_t key_frame_min_freq;
+ uint32_t enc_threads;
+ uint32_t dec_threads;
- avcodec_profile_t profiles[MAX_CODECS];
+ avcodec_profile_t *profiles[MAX_PROFILES];
};
struct avcodec_globals avcodec_globals = { 0 };
-char *CODEC_MAPS[] = {
- "H263",
- "H263+",
- "H264",
- "H265",
- NULL
-};
+const char *get_profile_name(int codec_id)
+{
+ switch (codec_id) {
+ case AV_CODEC_ID_H263: return "H263";
+ case AV_CODEC_ID_H263P: return "H263+";
+ case AV_CODEC_ID_H264: return "H264";
+ case AV_CODEC_ID_H265: return "H265";
+ }
-static int get_codec_index(const char *cstr)
+ return "NONE";
+}
+
+static void init_profile(avcodec_profile_t *aprofile, const char *name);
+
+static avcodec_profile_t *find_profile(const char *name, switch_bool_t reconfig)
{
int i;
- for (i = 0; ; i++) {
- if (!strcasecmp(cstr, CODEC_MAPS[i])) {
- return i;
+ for (i = 0; i < MAX_PROFILES; i++) {
+ if (!avcodec_globals.profiles[i]) {
+ avcodec_globals.profiles[i] = malloc(sizeof(avcodec_profile_t));
+ switch_assert(avcodec_globals.profiles[i]);
+ memset(avcodec_globals.profiles[i], 0, sizeof(avcodec_profile_t));
+ init_profile(avcodec_globals.profiles[i], name);
+ return avcodec_globals.profiles[i];
+ }
+
+ if (!strcmp(name, avcodec_globals.profiles[i]->name)) {
+ if (reconfig) init_profile(avcodec_globals.profiles[i], name);
+ return avcodec_globals.profiles[i];
}
}
- abort();
- return -1;
+ return NULL;
+}
+
+#define UINTVAL(v) (v > 0 ? v : 0);
+
+static void init_profile(avcodec_profile_t *aprofile, const char *name)
+{
+ switch_set_string(aprofile->name, name);
+ aprofile->ctx.colorspace = AVCOL_SPC_RGB;
+ aprofile->ctx.color_range = AVCOL_RANGE_JPEG;
+ aprofile->ctx.flags = 0;
+ aprofile->ctx.me_cmp = -1;
+ aprofile->ctx.me_range = -1;
+ aprofile->ctx.max_b_frames = -1;
+ aprofile->ctx.refs = -1;
+ aprofile->ctx.gop_size = -1;
+ aprofile->ctx.keyint_min = -1;
+ aprofile->ctx.i_quant_factor = -1;
+ aprofile->ctx.b_quant_factor = -1;
+ aprofile->ctx.qcompress = -1;
+ aprofile->ctx.qmin = -1;
+ aprofile->ctx.qmax = -1;
+ aprofile->ctx.max_qdiff = -1;
+ aprofile->ctx.thread_count = avcodec_globals.enc_threads;
+ aprofile->decoder_thread_count = avcodec_globals.dec_threads;
+
+ if (!strcasecmp(name, "H264")) {
+ aprofile->ctx.profile = FF_PROFILE_H264_BASELINE;
+ aprofile->ctx.level = 41;
+#ifdef AV_CODEC_FLAG_PSNR
+ aprofile->ctx.flags |= AV_CODEC_FLAG_PSNR;
+#endif
+#ifdef CODEC_FLAG_LOOP_FILTER
+ aprofile->ctx.flags |= CODEC_FLAG_LOOP_FILTER;
+#endif
+ }
}
static switch_status_t buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *frame)
@@ -1160,17 +1211,7 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
return SWITCH_STATUS_FALSE;
}
- if (context->av_codec_id == AV_CODEC_ID_H263) {
- profile = &avcodec_globals.profiles[get_codec_index("H263")];
- } else if (context->av_codec_id == AV_CODEC_ID_H263P) {
- profile = &avcodec_globals.profiles[get_codec_index("H263+")];
- } else if (context->av_codec_id == AV_CODEC_ID_H264) {
- profile = &avcodec_globals.profiles[get_codec_index("H264")];
-#ifdef AV_CODEC_ID_H265
- } else if (context->av_codec_id == AV_CODEC_ID_H265) {
- profile = &avcodec_globals.profiles[get_codec_index("H265")];
-#endif
- }
+ profile = find_profile(get_profile_name(context->av_codec_id), SWITCH_FALSE);
if (!profile) return SWITCH_STATUS_FALSE;
@@ -1320,16 +1361,17 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
if (!strcmp(codec->implementation->iananame, "H263")) {
context->av_codec_id = AV_CODEC_ID_H263;
- profile = &avcodec_globals.profiles[get_codec_index("H263")];
} else if (!strcmp(codec->implementation->iananame, "H263-1998")) {
context->av_codec_id = AV_CODEC_ID_H263P;
- profile = &avcodec_globals.profiles[get_codec_index("H263+")];
} else {
context->av_codec_id = AV_CODEC_ID_H264;
- profile = &avcodec_globals.profiles[get_codec_index("H264")];
}
- switch_assert(profile);
+ profile = find_profile(get_profile_name(context->av_codec_id), SWITCH_FALSE);
+
+ if (!profile) {
+ goto error;
+ }
if (decoding) {
context->decoder = avcodec_find_decoder(context->av_codec_id);
@@ -1869,8 +1911,6 @@ void show_codecs(switch_stream_handle_t *stream)
av_free(codecs);
}
-#define UINTVAL(v) (v > 0 ? v : 0);
-
static void parse_profile(switch_xml_t profile)
{
switch_xml_t options = switch_xml_child(profile, "options");
@@ -1878,18 +1918,18 @@ static void parse_profile(switch_xml_t profile)
const char *profile_name = switch_xml_attr(profile, "name");
avcodec_profile_t *aprofile = NULL;
AVCodecContext *ctx = NULL;
- int i;
if (zstr(profile_name)) return;
- for (i = 0; i < MAX_CODECS; i++) {
- if (!strcmp(profile_name, avcodec_globals.profiles[i].name)) {
- aprofile = &avcodec_globals.profiles[i];
- ctx = &aprofile->ctx;
- break;
- }
+ aprofile = find_profile(profile_name, SWITCH_TRUE);
+
+ if (!aprofile) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot find profile %s\n", profile_name);
+ return;
}
+ ctx = &aprofile->ctx;
+
if (!ctx) return;
for (param = switch_xml_child(profile, "param"); param; param = param->next) {
@@ -1913,7 +1953,7 @@ static void parse_profile(switch_xml_t profile)
} else if (!strcmp(name, "profile")) {
ctx->profile = UINTVAL(val);
- if (ctx->profile == 0 && !strcasecmp(CODEC_MAPS[i], "H264")) {
+ if (ctx->profile == 0 && !strcasecmp(aprofile->name, "H264")) {
if (!strcasecmp(value, "baseline")) {
ctx->profile = FF_PROFILE_H264_BASELINE;
} else if (!strcasecmp(value, "main")) {
@@ -2097,47 +2137,10 @@ static void parse_profile(switch_xml_t profile)
static void load_config()
{
switch_xml_t cfg = NULL, xml = NULL;
- int i;
-
- switch_set_string(avcodec_globals.profiles[get_codec_index("H263")].name, "H263");
- switch_set_string(avcodec_globals.profiles[get_codec_index("H263+")].name, "H263+");
- switch_set_string(avcodec_globals.profiles[get_codec_index("H264")].name, "H264");
- switch_set_string(avcodec_globals.profiles[get_codec_index("H265")].name, "H265");
-
- for (i = 0; i < MAX_CODECS; i++) {
- avcodec_profile_t *profile = &avcodec_globals.profiles[i];
-
- profile->ctx.colorspace = AVCOL_SPC_RGB;
- profile->ctx.color_range = AVCOL_RANGE_JPEG;
- profile->ctx.flags = 0;
- profile->ctx.me_cmp = -1;
- profile->ctx.me_range = -1;
- profile->ctx.max_b_frames = -1;
- profile->ctx.refs = -1;
- profile->ctx.gop_size = -1;
- profile->ctx.keyint_min = -1;
- profile->ctx.i_quant_factor = -1;
- profile->ctx.b_quant_factor = -1;
- profile->ctx.qcompress = -1;
- profile->ctx.qmin = -1;
- profile->ctx.qmax = -1;
- profile->ctx.max_qdiff = -1;
- profile->ctx.thread_count = switch_parse_cpu_string("cpu/2/4");
- profile->decoder_thread_count = switch_parse_cpu_string("cpu/2/4");
-
- if (!strcasecmp(CODEC_MAPS[i], "H264")) {
- profile->ctx.profile = FF_PROFILE_H264_BASELINE;
- profile->ctx.level = 41;
-#ifdef AV_CODEC_FLAG_PSNR
- profile->ctx.flags |= AV_CODEC_FLAG_PSNR;
-#endif
-#ifdef CODEC_FLAG_LOOP_FILTER
- profile->ctx.flags |= CODEC_FLAG_LOOP_FILTER;
-#endif
- }
- }
avcodec_globals.max_bitrate = 0;
+ avcodec_globals.dec_threads = 1;
+ avcodec_globals.enc_threads = switch_parse_cpu_string("cpu/2/4");
xml = switch_xml_open_cfg("avcodec.conf", &cfg, NULL);
@@ -2164,27 +2167,9 @@ static void load_config()
avcodec_globals.key_frame_min_freq = UINTVAL(val);
avcodec_globals.key_frame_min_freq *= 1000;
} else if (!strcmp(name, "dec-threads")) {
- int i;
- unsigned int threads = switch_parse_cpu_string(value);
-
- for (i = 0; i < MAX_CODECS; i++) {
- avcodec_globals.profiles[i].decoder_thread_count = threads;
- }
+ avcodec_globals.dec_threads = switch_parse_cpu_string(value);
} else if (!strcmp(name, "enc-threads")) {
- int i;
- unsigned int threads = switch_parse_cpu_string(value);
-
- for (i = 0; i < MAX_CODECS; i++) {
- avcodec_globals.profiles[i].ctx.thread_count = threads;
- }
- } else if (!strcasecmp(name, "h263-profile")) {
- switch_set_string(avcodec_globals.profiles[get_codec_index("H263")].name, value);
- } else if (!strcasecmp(name, "h263+-profile")) {
- switch_set_string(avcodec_globals.profiles[get_codec_index("H263+")].name, value);
- } else if (!strcasecmp(name, "h264-profile")) {
- switch_set_string(avcodec_globals.profiles[get_codec_index("H264")].name, value);
- } else if (!strcasecmp(name, "h265-profile")) {
- switch_set_string(avcodec_globals.profiles[get_codec_index("H265")].name, value);
+ avcodec_globals.enc_threads = switch_parse_cpu_string(value);
}
}
}
@@ -2213,6 +2198,12 @@ static void load_config()
if (avcodec_globals.key_frame_min_freq < 10000 || avcodec_globals.key_frame_min_freq > 3 * 1000000) {
avcodec_globals.key_frame_min_freq = KEY_FRAME_MIN_FREQ;
}
+
+ // make sure profiles created
+ find_profile("H263", SWITCH_FALSE);
+ find_profile("H263+", SWITCH_FALSE);
+ find_profile("H264", SWITCH_FALSE);
+ find_profile("H265", SWITCH_FALSE);
}
SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load)
@@ -2242,12 +2233,16 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avcodec_shutdown)
{
int i;
- for (i = 0; i < MAX_CODECS; i++) {
- avcodec_profile_t *profile = &avcodec_globals.profiles[i];
+ for (i = 0; i < MAX_PROFILES; i++) {
+ avcodec_profile_t *profile = avcodec_globals.profiles[i];
+
+ if (!profile) break;
if (profile->options) {
switch_event_destroy(&profile->options);
}
+
+ free(profile);
}
return SWITCH_STATUS_SUCCESS;