int decoder_thread_count;
AVCodecContext ctx;
switch_event_t *options;
+ switch_event_t *codecs;
} avcodec_profile_t;
struct avcodec_globals {
return "NONE";
}
+static void parse_profile(avcodec_profile_t *aprofile, switch_xml_t profile);
+
+static void parse_codec_specific_profile(avcodec_profile_t *aprofile, const char *codec_name)
+{
+ switch_xml_t cfg = NULL;
+ switch_xml_t xml = switch_xml_open_cfg("avcodec.conf", &cfg, NULL);
+ switch_xml_t profiles = cfg ? switch_xml_child(cfg, "profiles") : NULL;
+
+ // open config and find the profile to parse
+ if (profiles) {
+ switch_event_header_t *hp;
+
+ for (hp = aprofile->codecs->headers; hp; hp = hp->next) {
+ // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: %s\n", hp->name, hp->value);
+ if (!strcmp(hp->name, codec_name)) {
+ switch_xml_t profile;
+ for (profile = switch_xml_child(profiles, "profile"); profile; profile = profile->next) {
+ const char *name = switch_xml_attr(profile, "name");
+
+ if (!strcmp(hp->value, name)) {
+ parse_profile(aprofile, profile);
+ }
+ }
+ }
+ }
+ }
+
+ if (xml) switch_xml_free(xml);
+}
+
static void init_profile(avcodec_profile_t *aprofile, const char *name);
static avcodec_profile_t *find_profile(const char *name, switch_bool_t reconfig)
static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t width, uint32_t height)
{
int fps = 15;
- avcodec_profile_t *profile = NULL;
+ avcodec_profile_t *aprofile = NULL;
char codec_string[1024];
if (!context->encoder) {
}
if (!zstr(context->codec_settings.video.config_profile_name)) {
- profile = find_profile(context->codec_settings.video.config_profile_name, SWITCH_FALSE);
+ aprofile = find_profile(context->codec_settings.video.config_profile_name, SWITCH_FALSE);
}
- if (!profile) {
- profile = find_profile(get_profile_name(context->av_codec_id), SWITCH_FALSE);
+ if (!aprofile) {
+ aprofile = find_profile(get_profile_name(context->av_codec_id), SWITCH_FALSE);
}
- if (!profile) return SWITCH_STATUS_FALSE;
+ if (!aprofile) return SWITCH_STATUS_FALSE;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using config profile: [%s]\n", profile->name);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using config profile: [%s]\n", aprofile->name);
+
+ if (aprofile->codecs) {
+ parse_codec_specific_profile(aprofile, get_profile_name(context->av_codec_id));
+ }
if (context->encoder_ctx) {
if (avcodec_is_open(context->encoder_ctx)) {
context->encoder_ctx->width = context->codec_settings.video.width;
context->encoder_ctx->height = context->codec_settings.video.height;
context->encoder_ctx->time_base = (AVRational){1, 90};
- context->encoder_ctx->max_b_frames = profile->ctx.max_b_frames;
+ context->encoder_ctx->max_b_frames = aprofile->ctx.max_b_frames;
context->encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
- context->encoder_ctx->thread_count = profile->ctx.thread_count;
+ context->encoder_ctx->thread_count = aprofile->ctx.thread_count;
if (context->av_codec_id == AV_CODEC_ID_H263 || context->av_codec_id == AV_CODEC_ID_H263P) {
#ifndef H263_MODE_B
context->encoder_ctx->opaque = context;
av_opt_set_int(context->encoder_ctx->priv_data, "mb_info", SLICE_SIZE - 8, 0);
} else if (context->av_codec_id == AV_CODEC_ID_H264) {
- context->encoder_ctx->profile = profile->ctx.profile;
- context->encoder_ctx->level = profile->ctx.level;
+ context->encoder_ctx->profile = aprofile->ctx.profile;
+ context->encoder_ctx->level = aprofile->ctx.level;
- set_h264_private_data(context, profile);
+ set_h264_private_data(context, aprofile);
}
GCC_DIAG_OFF(deprecated-declarations)
av_free(codecs);
}
-static void parse_profile(switch_xml_t profile)
+static void parse_profile(avcodec_profile_t *aprofile, switch_xml_t profile)
{
switch_xml_t options = switch_xml_child(profile, "options");
switch_xml_t param = NULL;
const char *profile_name = switch_xml_attr(profile, "name");
- avcodec_profile_t *aprofile = NULL;
AVCodecContext *ctx = NULL;
if (zstr(profile_name)) return;
- 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 options
}
+static void parse_codecs(avcodec_profile_t *aprofile, switch_xml_t codecs)
+{
+ switch_xml_t codec = NULL;
+
+ if (!codecs) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no codecs in %s\n", aprofile->name);
+ return;
+ }
+
+ codec = switch_xml_child(codecs, "codec");
+
+ if (aprofile->codecs) {
+ switch_event_destroy(&aprofile->codecs);
+ }
+
+ switch_event_create(&aprofile->codecs, SWITCH_EVENT_CLONE);
+
+ for (; codec; codec = codec->next) {
+ const char *codec_name = switch_xml_attr(codec, "name");
+ const char *profile_name = switch_xml_attr(codec, "profile");
+
+ if (zstr(codec_name) || zstr(profile_name)) continue;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "codec: %s, profile: %s\n", codec_name, profile_name);
+
+ switch_event_add_header_string(aprofile->codecs, SWITCH_STACK_BOTTOM, codec_name, profile_name);
+ }
+}
+
+
static void load_config()
{
switch_xml_t cfg = NULL, xml = NULL;
switch_xml_t profile = switch_xml_child(profiles, "profile");
for (; profile; profile = profile->next) {
- parse_profile(profile);
+ switch_xml_t codecs = switch_xml_child(profile, "codecs");
+ const char *profile_name = switch_xml_attr(profile, "name");
+ avcodec_profile_t *aprofile = NULL;
+
+ if (zstr(profile_name)) continue;
+
+ 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);
+ continue;
+ }
+
+ parse_profile(aprofile, profile);
+ parse_codecs(aprofile, codecs);
} // for profile
} // profiles
switch_event_destroy(&profile->options);
}
+ if (profile->codecs) {
+ switch_event_destroy(&profile->codecs);
+ }
+
free(profile);
}