示例#1
0
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);
}
示例#3
0
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);
}
示例#4
0
/*! \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;
}
示例#5
0
/*! \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;
}
示例#6
0
/*! \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;
}
示例#8
0
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;
}
示例#9
0
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);
}
示例#10
0
/*! \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;
}
示例#11
0
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);
}
示例#12
0
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;
}
示例#13
0
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;
}
示例#14
0
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;
	}
}
示例#15
0
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;
}