int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod) { SCOPED_AO2WRLOCK(lock, codecs); struct ast_codec *codec_new; /* Some types have specific requirements */ if (codec->type == AST_MEDIA_TYPE_UNKNOWN) { ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name); return -1; } else if (codec->type == AST_MEDIA_TYPE_AUDIO) { if (!codec->sample_rate) { ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n", codec->name, ast_codec_media_type2str(codec->type)); return -1; } } codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK); if (codec_new) { ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n", codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate); ao2_ref(codec_new, -1); return -1; } codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, "")); if (!codec_new) { ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n", codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate); return -1; } *codec_new = *codec; codec_new->id = codec_id++; ao2_link_flags(codecs, codec_new, OBJ_NOLOCK); /* Once registered a codec can not be unregistered, and the module must persist until shutdown */ ast_module_shutdown_ref(mod); ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n", ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id); ao2_ref(codec_new, -1); return 0; }
static int stream_echo_write_error(struct ast_channel *chan, struct ast_frame *frame, int pos) { char frame_type[32]; const char *media_type; struct ast_stream *stream; ast_frame_type2str(frame->frametype, frame_type, sizeof(frame_type)); stream = pos < 0 ? ast_channel_get_default_stream(chan, ast_format_get_type(frame->subclass.format)) : ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), pos); media_type = ast_codec_media_type2str(ast_stream_get_type(stream)); ast_log(LOG_ERROR, "%s - unable to write frame type '%s' to stream type '%s' at " "position '%d'\n", ast_channel_name(chan), frame_type, media_type, ast_stream_get_position(stream)); return -1; }
static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ao2_iterator i; struct ast_codec *codec; switch (cmd) { case CLI_INIT: e->command = "core show codecs [audio|video|image|text]"; e->usage = "Usage: core show codecs [audio|video|image|text]\n" " Displays codec mapping\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc < 3) || (a->argc > 4)) { return CLI_SHOWUSAGE; } if (!ast_opt_dont_warn) { ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n" "\tIt does not indicate anything about your configuration.\n"); } ast_cli(a->fd, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION"); ast_cli(a->fd, "-----------------------------------------------------------------------------------\n"); ao2_rdlock(codecs); i = ao2_iterator_init(codecs, AO2_ITERATOR_DONTLOCK); for (; (codec = ao2_iterator_next(&i)); ao2_ref(codec, -1)) { if (a->argc == 4) { if (!strcasecmp(a->argv[3], "audio")) { if (codec->type != AST_MEDIA_TYPE_AUDIO) { continue; } } else if (!strcasecmp(a->argv[3], "video")) { if (codec->type != AST_MEDIA_TYPE_VIDEO) { continue; } } else if (!strcasecmp(a->argv[3], "image")) { if (codec->type != AST_MEDIA_TYPE_IMAGE) { continue; } } else if (!strcasecmp(a->argv[3], "text")) { if (codec->type != AST_MEDIA_TYPE_TEXT) { continue; } } else { continue; } } ast_cli(a->fd, "%8u %5s %8s (%s)\n", codec->id, ast_codec_media_type2str(codec->type), codec->name, codec->description); } ao2_iterator_destroy(&i); ao2_unlock(codecs); return CLI_SUCCESS; }