00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 384163 $");
00031
00032 #include "asterisk/_private.h"
00033 #include "asterisk/frame.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/utils.h"
00036
00037 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00038 {
00039 size_t f_len;
00040 const struct ast_format_list *f_list = ast_format_list_get(&f_len);
00041 int x, differential = (int) 'A', mem;
00042 char *from, *to;
00043
00044
00045
00046 if (right) {
00047 from = pref->order;
00048 to = buf;
00049 mem = size;
00050 } else {
00051 to = pref->order;
00052 from = buf;
00053 mem = AST_CODEC_PREF_SIZE;
00054 }
00055
00056 memset(to, 0, mem);
00057 for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
00058 if (!from[x]) {
00059 break;
00060 }
00061 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00062 if (!right && to[x] && (to[x] < f_len)) {
00063 ast_format_copy(&pref->formats[x], &f_list[to[x]-1].format);
00064 }
00065 }
00066 ast_format_list_destroy(f_list);
00067 }
00068
00069 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00070 {
00071 int x;
00072 struct ast_format format;
00073 size_t total_len, slen;
00074 const char *formatname;
00075
00076 memset(buf, 0, size);
00077 total_len = size;
00078 buf[0] = '(';
00079 total_len--;
00080 for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
00081 if (total_len <= 0)
00082 break;
00083 if (!(ast_codec_pref_index(pref, x, &format)))
00084 break;
00085 if ((formatname = ast_getformatname(&format))) {
00086 slen = strlen(formatname);
00087 if (slen > total_len)
00088 break;
00089 strncat(buf, formatname, total_len - 1);
00090 total_len -= slen;
00091 }
00092 if (total_len && x < AST_CODEC_PREF_SIZE - 1 && ast_codec_pref_index(pref, x + 1, &format)) {
00093 strncat(buf, "|", total_len - 1);
00094 total_len--;
00095 }
00096 }
00097 if (total_len) {
00098 strncat(buf, ")", total_len - 1);
00099 total_len--;
00100 }
00101
00102 return size - total_len;
00103 }
00104
00105 struct ast_format *ast_codec_pref_index(struct ast_codec_pref *pref, int idx, struct ast_format *result)
00106 {
00107 if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->formats[idx].id) {
00108 ast_format_copy(result, &pref->formats[idx]);
00109 } else {
00110 ast_format_clear(result);
00111 return NULL;
00112 }
00113
00114 return result;
00115 }
00116
00117
00118 void ast_codec_pref_remove(struct ast_codec_pref *pref, struct ast_format *format)
00119 {
00120 struct ast_codec_pref oldorder;
00121 int x, y = 0;
00122 size_t f_len = 0;
00123 const struct ast_format_list *f_list;
00124
00125 if (!pref->order[0]) {
00126 return;
00127 }
00128
00129 f_list = ast_format_list_get(&f_len);
00130 memcpy(&oldorder, pref, sizeof(oldorder));
00131 memset(pref, 0, sizeof(*pref));
00132
00133 for (x = 0; x < f_len; x++) {
00134 if (!oldorder.order[x]) {
00135 break;
00136 }
00137 if (ast_format_cmp(&f_list[oldorder.order[x]-1].format, format) == AST_FORMAT_CMP_NOT_EQUAL) {
00138 pref->order[y] = oldorder.order[x];
00139 ast_format_copy(&pref->formats[y], &oldorder.formats[x]);
00140 pref->framing[y++] = oldorder.framing[x];
00141 }
00142 }
00143 ast_format_list_destroy(f_list);
00144 }
00145
00146
00147 int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format)
00148 {
00149 int x, newindex = 0;
00150 size_t f_len = 0;
00151 const struct ast_format_list *f_list = ast_format_list_get(&f_len);
00152
00153 ast_codec_pref_remove(pref, format);
00154
00155 for (x = 0; x < f_len; x++) {
00156 if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
00157 newindex = x + 1;
00158 break;
00159 }
00160 }
00161
00162 if (newindex) {
00163 for (x = 0; x < f_len; x++) {
00164 if (!pref->order[x]) {
00165 pref->order[x] = newindex;
00166 ast_format_copy(&pref->formats[x], format);
00167 break;
00168 }
00169 }
00170 }
00171
00172 ast_format_list_destroy(f_list);
00173 return x;
00174 }
00175
00176
00177 void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing)
00178 {
00179 int x, newindex = 0;
00180 size_t f_len = 0;
00181 const struct ast_format_list *f_list = ast_format_list_get(&f_len);
00182
00183
00184 for (x = 0; x < f_len; x++) {
00185 if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
00186 newindex = x + 1;
00187 break;
00188 }
00189 }
00190
00191 if (!newindex) {
00192 ast_format_list_destroy(f_list);
00193 return;
00194 }
00195
00196
00197 for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
00198 if (!pref->order[x] || pref->order[x] == newindex)
00199 break;
00200 }
00201
00202
00203 if (x == AST_CODEC_PREF_SIZE) {
00204 --x;
00205 }
00206
00207 if (only_if_existing && !pref->order[x]) {
00208 ast_format_list_destroy(f_list);
00209 return;
00210 }
00211
00212
00213
00214 for (; x > 0; x--) {
00215 pref->order[x] = pref->order[x - 1];
00216 pref->framing[x] = pref->framing[x - 1];
00217 ast_format_copy(&pref->formats[x], &pref->formats[x - 1]);
00218 }
00219
00220
00221 pref->order[0] = newindex;
00222 pref->framing[0] = 0;
00223 ast_format_copy(&pref->formats[0], format);
00224 ast_format_list_destroy(f_list);
00225 }
00226
00227
00228 int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems)
00229 {
00230 int x, idx = -1;
00231 size_t f_len = 0;
00232 const struct ast_format_list *f_list = ast_format_list_get(&f_len);
00233
00234 for (x = 0; x < f_len; x++) {
00235 if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
00236 idx = x;
00237 break;
00238 }
00239 }
00240
00241 if (idx < 0) {
00242 ast_format_list_destroy(f_list);
00243 return -1;
00244 }
00245
00246
00247 if (!framems)
00248 framems = f_list[idx].def_ms;
00249
00250 if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms)
00251 framems -= framems % f_list[idx].inc_ms;
00252
00253 if (framems < f_list[idx].min_ms)
00254 framems = f_list[idx].min_ms;
00255
00256 if (framems > f_list[idx].max_ms)
00257 framems = f_list[idx].max_ms;
00258
00259 for (x = 0; x < f_len; x++) {
00260 if (pref->order[x] == (idx + 1)) {
00261 pref->framing[x] = framems;
00262 break;
00263 }
00264 }
00265
00266 ast_format_list_destroy(f_list);
00267 return x;
00268 }
00269
00270
00271 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format)
00272 {
00273 int x, idx = -1, framems = 0;
00274 struct ast_format_list fmt = { { 0, }, };
00275 size_t f_len = 0;
00276 const struct ast_format_list *f_list = ast_format_list_get(&f_len);
00277
00278 for (x = 0; x < f_len; x++) {
00279 if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
00280 fmt = f_list[x];
00281 idx = x;
00282 break;
00283 }
00284 }
00285
00286 if (idx < 0) {
00287 ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format));
00288 ast_format_list_destroy(f_list);
00289 return fmt;
00290 }
00291
00292 for (x = 0; x < f_len; x++) {
00293 if (pref->order[x] == (idx + 1)) {
00294 framems = pref->framing[x];
00295 break;
00296 }
00297 }
00298
00299
00300 if (!framems)
00301 framems = f_list[idx].def_ms;
00302
00303 if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms)
00304 framems -= framems % f_list[idx].inc_ms;
00305
00306 if (framems < f_list[idx].min_ms)
00307 framems = f_list[idx].min_ms;
00308
00309 if (framems > f_list[idx].max_ms)
00310 framems = f_list[idx].max_ms;
00311
00312 fmt.cur_ms = framems;
00313 ast_format_list_destroy(f_list);
00314 return fmt;
00315 }
00316
00317
00318 struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result)
00319 {
00320 int x, slot, found = 0;
00321 size_t f_len = 0;
00322 const struct ast_format_list *f_list = ast_format_list_get(&f_len);
00323
00324 for (x = 0; x < f_len; x++) {
00325 slot = pref->order[x];
00326
00327 if (!slot)
00328 break;
00329 if (ast_format_cap_get_compatible_format(cap, &f_list[slot-1].format, result)) {
00330 found = 1;
00331 break;
00332 }
00333 }
00334 ast_format_list_destroy(f_list);
00335 if (found && (AST_FORMAT_GET_TYPE(result->id) == AST_FORMAT_TYPE_AUDIO)) {
00336 return result;
00337 }
00338 ast_format_clear(result);
00339 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
00340
00341 return find_best ? ast_best_codec(cap, result) : NULL;
00342 }
00343
00344