char *ast_getformatname_multiple_byid(char *buf, size_t size, enum ast_format_id id) { int x; unsigned len; char *start, *end = buf; size_t f_len; const struct ast_format_list *f_list = ast_format_list_get(&f_len); if (!size) { f_list = ast_format_list_destroy(f_list); return buf; } snprintf(end, size, "("); len = strlen(end); end += len; size -= len; start = end; for (x = 0; x < f_len; x++) { if (f_list[x].format.id == id) { snprintf(end, size, "%s|", f_list[x].name); len = strlen(end); end += len; size -= len; } } if (start == end) { ast_copy_string(start, "nothing)", size); } else if (size > 1) { *(end - 1) = ')'; } f_list = ast_format_list_destroy(f_list); return buf; }
/*! \brief Prepend codec to list */ void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing) { int x, newindex = 0; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); /* First step is to get the codecs "index number" */ for (x = 0; x < f_len; x++) { if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) { newindex = x + 1; break; } } /* Done if its unknown */ if (!newindex) { ast_format_list_destroy(f_list); return; } /* Now find any existing occurrence, or the end */ for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { if (!pref->order[x] || pref->order[x] == newindex) break; } /* If we failed to find any occurrence, set to the end */ if (x == AST_CODEC_PREF_SIZE) { --x; } if (only_if_existing && !pref->order[x]) { ast_format_list_destroy(f_list); return; } /* Move down to make space to insert - either all the way to the end, or as far as the existing location (which will be overwritten) */ for (; x > 0; x--) { pref->order[x] = pref->order[x - 1]; pref->framing[x] = pref->framing[x - 1]; ast_format_copy(&pref->formats[x], &pref->formats[x - 1]); } /* And insert the new entry */ pref->order[0] = newindex; pref->framing[0] = 0; /* ? */ ast_format_copy(&pref->formats[0], format); ast_format_list_destroy(f_list); }
void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) { size_t f_len; const const struct ast_format_list *f_list = ast_format_list_get(&f_len); int x, differential = (int) 'A', mem; char *from, *to; /* TODO re-evaluate this function. It is using the order of the formats specified * in the global format list in a way that may not be safe. */ if (right) { from = pref->order; to = buf; mem = size; } else { to = pref->order; from = buf; mem = AST_CODEC_PREF_SIZE; } memset(to, 0, mem); for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { if (!from[x]) { break; } to[x] = right ? (from[x] + differential) : (from[x] - differential); if (!right && to[x] && (to[x] < f_len)) { ast_format_copy(&pref->formats[x], &f_list[to[x]-1].format); } } ast_format_list_destroy(f_list); }
/*! \brief Pick a codec */ struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result) { int x, slot, found; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { slot = pref->order[x]; if (!slot) break; if (ast_format_cap_get_compatible_format(cap, &f_list[slot-1].format, result)) { found = 1; /*format is found and stored in result */ break; } } ast_format_list_destroy(f_list); if (found && (AST_FORMAT_GET_TYPE(result->id) == AST_FORMAT_TYPE_AUDIO)) { return result; } ast_format_clear(result); ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec"); return find_best ? ast_best_codec(cap, result) : NULL; }
/*! \brief Append codec to list */ int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format) { int x, newindex = 0; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); ast_codec_pref_remove(pref, format); for (x = 0; x < f_len; x++) { if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) { newindex = x + 1; break; } } if (newindex) { for (x = 0; x < f_len; x++) { if (!pref->order[x]) { pref->order[x] = newindex; ast_format_copy(&pref->formats[x], format); break; } } } ast_format_list_destroy(f_list); return x; }
/*! \brief Remove codec from pref list */ void ast_codec_pref_remove(struct ast_codec_pref *pref, struct ast_format *format) { struct ast_codec_pref oldorder; int x, y = 0; size_t f_len = 0; const const struct ast_format_list *f_list; if (!pref->order[0]) { return; } f_list = ast_format_list_get(&f_len); memcpy(&oldorder, pref, sizeof(oldorder)); memset(pref, 0, sizeof(*pref)); for (x = 0; x < f_len; x++) { if (!oldorder.order[x]) { break; } if (ast_format_cmp(&f_list[oldorder.order[x]-1].format, format) == AST_FORMAT_CMP_NOT_EQUAL) { pref->order[y] = oldorder.order[x]; ast_format_copy(&pref->formats[y], &oldorder.formats[x]); pref->framing[y++] = oldorder.framing[x]; } } ast_format_list_destroy(f_list); }
/*! \brief Get packet size for codec */ struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format) { int x, idx = -1, framems = 0; struct ast_format_list fmt = { { 0, }, }; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) { fmt = f_list[x]; idx = x; break; } } if (idx < 0) { ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format)); ast_format_list_destroy(f_list); return fmt; } for (x = 0; x < f_len; x++) { if (pref->order[x] == (idx + 1)) { framems = pref->framing[x]; break; } } /* size validation */ if (!framems) framems = f_list[idx].def_ms; if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */ framems -= framems % f_list[idx].inc_ms; if (framems < f_list[idx].min_ms) framems = f_list[idx].min_ms; if (framems > f_list[idx].max_ms) framems = f_list[idx].max_ms; fmt.cur_ms = framems; ast_format_list_destroy(f_list); return fmt; }
struct ast_format *ast_getformatbyname(const char *name, struct ast_format *result) { int x; size_t f_len; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { if (!strcasecmp(f_list[x].name, name) || !strcasecmp(f_list[x].name, ast_expand_codec_alias(name))) { ast_format_copy(result, &f_list[x].format); f_list = ast_format_list_destroy(f_list); return result; } } f_list = ast_format_list_destroy(f_list); return NULL; }
void ast_format_cap_add_all(struct ast_format_cap *cap) { int x; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { ast_format_cap_add(cap, &f_list[x].format); } ast_format_list_destroy(f_list); }
/*! \brief Set packet size for codec */ int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems) { int x, idx = -1; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) { idx = x; break; } } if (idx < 0) { ast_format_list_destroy(f_list); return -1; } /* size validation */ if (!framems) framems = f_list[idx].def_ms; if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */ framems -= framems % f_list[idx].inc_ms; if (framems < f_list[idx].min_ms) framems = f_list[idx].min_ms; if (framems > f_list[idx].max_ms) framems = f_list[idx].max_ms; for (x = 0; x < f_len; x++) { if (pref->order[x] == (idx + 1)) { pref->framing[x] = framems; break; } } ast_format_list_destroy(f_list); return x; }
void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type) { int x; size_t f_len = 0; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { if (AST_FORMAT_GET_TYPE(f_list[x].format.id) == type) { ast_format_cap_add(cap, &f_list[x].format); } } ast_format_list_destroy(f_list); }
const char* ast_getformatname(const struct ast_format *format) { int x; const char *ret = "unknown"; size_t f_len; const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) { ret = f_list[x].name; break; } } f_list = ast_format_list_destroy(f_list); return ret; }
static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { enum ast_format_id format_id; int x, found = 0; int type_punned_codec; size_t f_len; const struct ast_format_list *f_list; switch (cmd) { case CLI_INIT: e->command = "core show codec"; e->usage = "Usage: core show codec <number>\n" " Displays codec mapping\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 4) { return CLI_SHOWUSAGE; } if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) { return CLI_SHOWUSAGE; } format_id = type_punned_codec; f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { if (f_list[x].format.id == format_id) { found = 1; ast_cli(a->fd, "%11u %s\n", (unsigned int) format_id, f_list[x].desc); } } if (!found) { ast_cli(a->fd, "Codec %d not found\n", format_id); } f_list = ast_format_list_destroy(f_list); return CLI_SUCCESS; }
static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int x, found=0; size_t f_len; const struct ast_format_list *f_list; 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; } f_list = ast_format_list_get(&f_len); 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"); for (x = 0; x < f_len; x++) { if (a->argc == 4) { if (!strcasecmp(a->argv[3], "audio")) { if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_AUDIO) { continue; } } else if (!strcasecmp(a->argv[3], "video")) { if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_VIDEO) { continue; } } else if (!strcasecmp(a->argv[3], "image")) { if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_IMAGE) { continue; } } else if (!strcasecmp(a->argv[3], "text")) { if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_TEXT) { continue; } } else { continue; } } ast_cli(a->fd, "%8u %5s %8s (%s)\n", f_list[x].format.id, (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_AUDIO) ? "audio" : (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_IMAGE) ? "image" : (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_VIDEO) ? "video" : (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_TEXT) ? "text" : "(unk)", f_list[x].name, f_list[x].desc); found = 1; } f_list = ast_format_list_destroy(f_list); if (!found) { return CLI_SHOWUSAGE; } else { return CLI_SUCCESS; } }
int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, .joint_cap = NULL, }; it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return data.joint_found ? 1 : 0; } int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format *tmp; if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) { return 0; /* if they are not the same size, they are not identical */ } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (!ast_format_cap_iscompatible(cap2, tmp)) { ao2_ref(tmp, -1); ao2_iterator_destroy(&it); return 0; } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return 1; } struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format_cap *result = ast_format_cap_alloc_nolock(); struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, .joint_cap = result, }; if (!result) { return NULL; } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); if (ao2_container_count(result->formats)) { return result; } result = ast_format_cap_destroy(result); return NULL; } static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result, int append) { struct ao2_iterator it; struct ast_format *tmp; struct find_joint_data data = { .joint_cap = result, .joint_found = 0, }; if (!append) { ast_format_cap_remove_all(result); } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return ao2_container_count(result->formats) ? 1 : 0; } int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) { return joint_copy_helper(cap1, cap2, result, 1); } int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) { return joint_copy_helper(cap1, cap2, result, 0); } struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype) { struct ao2_iterator it; struct ast_format_cap *result = ast_format_cap_alloc_nolock(); struct ast_format *tmp; if (!result) { return NULL; } /* for each format in cap1, see if that format is * compatible with cap2. If so copy it to the result */ it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) { /* copy format */ ast_format_cap_add(result, tmp); } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); if (ao2_container_count(result->formats)) { return result; } result = ast_format_cap_destroy(result); return NULL; } int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type) { struct ao2_iterator it; struct ast_format *tmp; it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (AST_FORMAT_GET_TYPE(tmp->id) == type) { ao2_ref(tmp, -1); ao2_iterator_destroy(&it); return 1; } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return 0; } void ast_format_cap_iter_start(struct ast_format_cap *cap) { if (!cap->nolock) { ao2_lock(cap->formats); } cap->it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); } void ast_format_cap_iter_end(struct ast_format_cap *cap) { ao2_iterator_destroy(&cap->it); if (!cap->nolock) { ao2_unlock(cap->formats); } } int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format) { struct ast_format *tmp = ao2_iterator_next(&cap->it); if (!tmp) { return -1; } ast_format_copy(format, tmp); ao2_ref(tmp, -1); return 0; } char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) { int x; unsigned len; char *start, *end = buf; struct ast_format tmp_fmt; size_t f_len; const struct ast_format_list *f_list = ast_format_list_get(&f_len); if (!size) { f_list = ast_format_list_destroy(f_list); return buf; } snprintf(end, size, "("); len = strlen(end); end += len; size -= len; start = end; for (x = 0; x < f_len; x++) { ast_format_copy(&tmp_fmt, &f_list[x].format); if (ast_format_cap_iscompatible(cap, &tmp_fmt)) { snprintf(end, size, "%s|", f_list[x].name); len = strlen(end); end += len; size -= len; } } if (start == end) { ast_copy_string(start, "nothing)", size); } else if (size > 1) { *(end - 1) = ')'; } f_list = ast_format_list_destroy(f_list); return buf; } uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap) { uint64_t res = 0; struct ao2_iterator it; struct ast_format *tmp; it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { res |= ast_format_to_old_bitfield(tmp); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return res; }