Asterisk - The Open Source Telephony Project GIT-master-590b490
Loading...
Searching...
No Matches
translate.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2006, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Translate via the use of pseudo channels
22 *
23 * \author Mark Spencer <markster@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include <sys/time.h>
33#include <sys/resource.h>
34#include <math.h>
35
36#include "asterisk/lock.h"
37#include "asterisk/channel.h"
38#include "asterisk/translate.h"
39#include "asterisk/module.h"
40#include "asterisk/frame.h"
41#include "asterisk/sched.h"
42#include "asterisk/cli.h"
43#include "asterisk/term.h"
44#include "asterisk/format.h"
46
47/*
48 * Sample type selection for codec matrix cost computation.
49 */
51 SAMPLE_TYPE_CODEC = 0, /*!< Default: take samples defined by codec */
52 SAMPLE_TYPE_SINE, /*!< Default: 1kHz sine wave */
53 SAMPLE_TYPE_SILENCE, /*!< All-zero frames */
54 SAMPLE_TYPE_NOISE, /*!< White noise via LCG PRNG */
55 SAMPLE_TYPE_SPEECH, /*!< Synthetic speech-like signal */
56};
57
59
60/*! Simple LCG state for reproducible pseudo-random noise */
61static uint32_t lcg_state = 0xdeadbeef;
62static uint32_t lcg_rand(void)
63{
64 lcg_state = lcg_state * 1664525u + 1013904223u;
65 return lcg_state;
66}
67
68/*!
69 * \brief Fill a buffer with samples of the selected type.
70 * \param buf Output sample buffer (int16_t)
71 * \param samples Number of samples to generate
72 * \param offset Running sample offset (for continuous sample types)
73 */
74static void generate_samples(int16_t *buf, int samples, int offset)
75{
76 int i;
77 switch (current_sample_type) {
79 memset(buf, 0, samples * sizeof(int16_t));
80 break;
82 for (i = 0; i < samples; i++) {
83 buf[i] = (int16_t)(lcg_rand() & 0xFFFF);
84 }
85 break;
87 /* Synthetic speech approximation: mix of two sine waves
88 * (fundamental ~200Hz + harmonic ~800Hz) with slow AM envelope,
89 * loosely inspired by ITU-T P.50 artificial voice. */
90 for (i = 0; i < samples; i++) {
91 double t = (double)(offset + i) / 8000.0;
92 double sig = 0.6 * sin(2.0 * M_PI * 200.0 * t)
93 + 0.4 * sin(2.0 * M_PI * 800.0 * t);
94 /* Slow AM at 4Hz to simulate syllable rhythm */
95 sig *= 0.5 * (1.0 + sin(2.0 * M_PI * 4.0 * t));
96 buf[i] = (int16_t)(sig * 16000.0);
97 }
98 break;
100 default:
101 /* pure 1kHz sine wave */
102 for (i = 0; i < samples; i++) {
103 buf[i] = (int16_t)(sin(2.0 * M_PI * 1000.0 *
104 (double)(offset + i) / 8000.0) * 16000.0);
105 }
106 break;
107 }
108}
109
110/*! max sample recalc */
111#define MAX_RECALC 1000
112
113/*! \brief the list of translators */
115
117 struct ast_translator *step; /*!< Next step translator */
118 uint32_t table_cost; /*!< Complete table cost to destination */
119 uint32_t comp_cost; /*!< Complete table cost to destination */
120 uint8_t multistep; /*!< Multiple conversions required for this translation */
121};
122
123/*!
124 * \brief a matrix that, for any pair of supported formats,
125 * indicates the total cost of translation and the first step.
126 * The full path can be reconstructed iterating on the matrix
127 * until step->dstfmt == desired_format.
128 *
129 * Array indexes are 'src' and 'dest', in that order.
130 *
131 * Note: the lock in the 'translators' list is also used to protect
132 * this structure.
133 */
134static struct translator_path **__matrix;
135
136/*!
137 * \brief table for converting index to format values.
138 *
139 * \note this table is protected by the table_lock.
140 */
141static unsigned int *__indextable;
142
143/*! protects the __indextable for resizing */
145
146/* index size starts at this*/
147#define INIT_INDEX 32
148/* index size grows by this as necessary */
149#define GROW_INDEX 16
150
151/*! the current largest index used by the __matrix and __indextable arrays*/
152static int cur_max_index;
153/*! the largest index that can be used in either the __indextable or __matrix before resize must occur */
154static int index_size;
155
156static void matrix_rebuild(int samples);
157
158/*!
159 * \internal
160 * \brief converts codec id to index value.
161 */
162static int codec_to_index(unsigned int id)
163{
164 int x;
165
167 for (x = 0; x < cur_max_index; x++) {
168 if (__indextable[x] == id) {
169 /* format already exists in index2format table */
171 return x;
172 }
173 }
175 return -1; /* not found */
176}
177
178/*!
179 * \internal
180 * \brief converts codec to index value.
181 */
182static int codec2index(struct ast_codec *codec)
183{
184 return codec_to_index(codec->id);
185}
186
187/*!
188 * \internal
189 * \brief converts format to codec index value.
190 */
191static int format2index(struct ast_format *format)
192{
194}
195
196/*!
197 * \internal
198 * \brief add a new codec to the matrix and index table structures.
199 *
200 * \note it is perfectly safe to call this on codecs already indexed.
201 *
202 * \retval 0 success
203 * \retval -1 matrix and index table need to be resized
204 */
205static int add_codec2index(struct ast_codec *codec)
206{
207 if (codec2index(codec) != -1) {
208 /* format is already already indexed */
209 return 0;
210 }
211
213 if (cur_max_index == (index_size)) {
215 return -1; /* hit max length */
216 }
217 __indextable[cur_max_index] = codec->id;
220
221 return 0;
222}
223
224/*!
225 * \internal
226 * \brief converts index value back to codec
227 */
228static struct ast_codec *index2codec(int index)
229{
230 struct ast_codec *codec;
231
232 if (index >= cur_max_index) {
233 return 0;
234 }
236 codec = ast_codec_get_by_id(__indextable[index]);
238
239 return codec;
240}
241
242/*!
243 * \internal
244 * \brief resize both the matrix and index table so they can represent
245 * more translators
246 *
247 * \note _NO_ locks can be held prior to calling this function
248 *
249 * \retval 0 success
250 * \retval -1 failure. Old matrix and index table can still be used though
251 */
252static int matrix_resize(int init)
253{
254 struct translator_path **tmp_matrix = NULL;
255 unsigned int *tmp_table = NULL;
256 int old_index;
257 int x;
258
261
262 old_index = index_size;
263 if (init) {
265 } else {
267 }
268
269 /* make new 2d array of translator_path structures */
270 if (!(tmp_matrix = ast_calloc(1, sizeof(struct translator_path *) * (index_size)))) {
271 goto resize_cleanup;
272 }
273
274 for (x = 0; x < index_size; x++) {
275 if (!(tmp_matrix[x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) {
276 goto resize_cleanup;
277 }
278 }
279
280 /* make new index table */
281 if (!(tmp_table = ast_calloc(1, sizeof(unsigned int) * index_size))) {
282 goto resize_cleanup;
283 }
284
285 /* if everything went well this far, free the old and use the new */
286 if (!init) {
287 for (x = 0; x < old_index; x++) {
288 ast_free(__matrix[x]);
289 }
291
292 memcpy(tmp_table, __indextable, sizeof(unsigned int) * old_index);
294 }
295
296 /* now copy them over */
297 __matrix = tmp_matrix;
298 __indextable = tmp_table;
299
303
304 return 0;
305
306resize_cleanup:
309 if (tmp_matrix) {
310 for (x = 0; x < index_size; x++) {
311 ast_free(tmp_matrix[x]);
312 }
313 ast_free(tmp_matrix);
314 }
315 ast_free(tmp_table);
316
317 return -1;
318}
319
320/*!
321 * \internal
322 * \brief reinitialize the __matrix during matrix rebuild
323 *
324 * \note must be protected by the translators list lock
325 */
326static void matrix_clear(void)
327{
328 int x;
329 for (x = 0; x < index_size; x++) {
330 memset(__matrix[x], '\0', sizeof(struct translator_path) * (index_size));
331 }
332}
333
334/*!
335 * \internal
336 * \brief get a matrix entry
337 *
338 * \note This function must be protected by the translators list lock
339 */
340static struct translator_path *matrix_get(unsigned int x, unsigned int y)
341{
342 return __matrix[x] + y;
343}
344
345/*
346 * wrappers around the translator routines.
347 */
348
349static void destroy(struct ast_trans_pvt *pvt)
350{
351 struct ast_translator *t = pvt->t;
352
353 if (t->destroy) {
354 t->destroy(pvt);
355 }
357 if (pvt->explicit_dst) {
358 ao2_ref(pvt->explicit_dst, -1);
359 pvt->explicit_dst = NULL;
360 }
361 ast_free(pvt);
362 ast_module_unref(t->module);
363}
364
365/*!
366 * \brief Allocate the descriptor, required outbuf space,
367 * and possibly desc.
368 */
370{
371 struct ast_trans_pvt *pvt;
372 int len;
373 char *ofs;
374
375 /*
376 * compute the required size adding private descriptor,
377 * buffer, AST_FRIENDLY_OFFSET.
378 */
379 len = sizeof(*pvt) + t->desc_size;
380 if (t->buf_size)
382 pvt = ast_calloc(1, len);
383 if (!pvt) {
384 return NULL;
385 }
386 pvt->t = t;
387 ofs = (char *)(pvt + 1); /* pointer to data space */
388 if (t->desc_size) { /* first comes the descriptor */
389 pvt->pvt = ofs;
390 ofs += t->desc_size;
391 }
392 if (t->buf_size) {/* finally buffer and header */
393 pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
394 }
395 /*
396 * If the format has an attribute module, explicit_dst includes the (joined)
397 * result of the SDP negotiation. For example with the Opus Codec, the format
398 * knows whether both parties want to do forward-error correction (FEC).
399 */
400 pvt->explicit_dst = ao2_bump(explicit_dst);
401
402 ast_module_ref(t->module);
403
404 /* call local init routine, if present */
405 if (t->newpvt && t->newpvt(pvt)) {
406 ast_free(pvt);
407 ast_module_unref(t->module);
408 return NULL;
409 }
410
411 /* Setup normal static translation frame. */
412 pvt->f.frametype = AST_FRAME_VOICE;
413 pvt->f.mallocd = 0;
414 pvt->f.offset = AST_FRIENDLY_OFFSET;
415 pvt->f.src = pvt->t->name;
416 pvt->f.data.ptr = pvt->outbuf.c;
417
418 /*
419 * If the translator has not provided a format
420 * A) use the joined one,
421 * B) use the cached one, or
422 * C) create one.
423 */
424 if (!pvt->f.subclass.format) {
425 pvt->f.subclass.format = ao2_bump(pvt->explicit_dst);
426
427 if (!pvt->f.subclass.format && !ast_strlen_zero(pvt->t->format)) {
428 pvt->f.subclass.format = ast_format_cache_get(pvt->t->format);
429 }
430
431 if (!pvt->f.subclass.format) {
432 struct ast_codec *codec = ast_codec_get(t->dst_codec.name,
434 if (!codec) {
435 ast_log(LOG_ERROR, "Unable to get destination codec\n");
436 destroy(pvt);
437 return NULL;
438 }
439 pvt->f.subclass.format = ast_format_create(codec);
440 ao2_ref(codec, -1);
441 }
442
443 if (!pvt->f.subclass.format) {
444 ast_log(LOG_ERROR, "Unable to create format\n");
445 destroy(pvt);
446 return NULL;
447 }
448 }
449
450 return pvt;
451}
452
453/*! \brief framein wrapper, deals with bound checks. */
454static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
455{
456 /* Copy the last in jb timing info to the pvt */
458 pvt->f.ts = f->ts;
459 pvt->f.len = f->len;
460 pvt->f.seqno = f->seqno;
461
462 if (f->samples == 0) {
463 /* Do not log empty audio frame */
464 if (!f->src || strcasecmp(f->src, "ast_prod")) {
465 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
466 }
467 }
468 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
469 int src_srate = pvt->t->src_codec.sample_rate;
470 int dst_srate = pvt->t->dst_codec.sample_rate;
471
472 ast_assert(src_srate > 0);
473
474 if (f->datalen == 0) { /* perform native PLC if available */
475 /* If the codec has native PLC, then do that */
476 if (!pvt->t->native_plc)
477 return 0;
478 }
479
480 if (pvt->samples + (f->samples * dst_srate / src_srate) > pvt->t->buffer_samples) {
481 ast_log(LOG_WARNING, "Out of buffer space\n");
482 return -1;
483 }
484 }
485 /* we require a framein routine, wouldn't know how to do
486 * it otherwise.
487 */
488 return pvt->t->framein(pvt, f);
489}
490
491/*! \brief generic frameout routine.
492 * If samples and datalen are 0, take whatever is in pvt
493 * and reset them, otherwise take the values in the caller and
494 * leave alone the pvt values.
495 */
497 int datalen, int samples)
498{
499 struct ast_frame *f = &pvt->f;
500
501 if (samples) {
502 f->samples = samples;
503 } else {
504 if (pvt->samples == 0) {
505 return NULL;
506 }
507 f->samples = pvt->samples;
508 pvt->samples = 0;
509 }
510 if (datalen) {
511 f->datalen = datalen;
512 f->data.ptr = pvt->outbuf.c;
513 } else {
514 f->datalen = pvt->datalen;
515 if (!f->datalen) {
516 f->data.ptr = NULL;
517 } else {
518 f->data.ptr = pvt->outbuf.c;
519 }
520 pvt->datalen = 0;
521 }
522
523 return ast_frisolate(f);
524}
525
526static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
527{
528 return ast_trans_frameout(pvt, 0, 0);
529}
530
531/* end of callback wrappers and helpers */
532
534{
535 struct ast_trans_pvt *pn = p;
536 while ( (p = pn) ) {
537 pn = p->next;
538 destroy(p);
539 }
540}
541
542/*! \brief Build a chain of translators based upon the given source and dest formats */
544{
545 struct ast_trans_pvt *head = NULL, *tail = NULL;
546 int src_index, dst_index;
547
548 src_index = format2index(src);
549 dst_index = format2index(dst);
550
551 if (src_index < 0 || dst_index < 0) {
552 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
553 return NULL;
554 }
555
557
558 while (src_index != dst_index) {
559 struct ast_trans_pvt *cur;
560 struct ast_format *explicit_dst = NULL;
561 struct ast_translator *t = matrix_get(src_index, dst_index)->step;
562 if (!t) {
563 ast_log(LOG_WARNING, "No translator path from %s to %s\n",
567 return NULL;
568 }
570 explicit_dst = dst;
571 }
572 if (!(cur = newpvt(t, explicit_dst))) {
573 ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
577 return NULL;
578 }
579 if (!head) {
580 head = cur;
581 } else {
582 tail->next = cur;
583 }
584 tail = cur;
585 cur->nextin = cur->nextout = ast_tv(0, 0);
586 /* Keep going if this isn't the final destination */
587 src_index = cur->t->dst_fmt_index;
588 }
589
591 return head;
592}
593
595{
596 struct ast_frame res = { AST_FRAME_VOICE };
597
598 /*
599 * If we've gotten here then we should have an interpolated frame that was not handled
600 * by the translation codec. So create an interpolated frame in the appropriate format
601 * that was going to be written. This frame might be handled later by other resources.
602 * For instance, generic plc.
603 *
604 * Note, generic plc is currently only available for the format type 'slin' (8KHz only -
605 * The generic plc code appears to have been based around that). Generic plc is filled
606 * in later on frame write.
607 */
608 if (!ast_opt_generic_plc || f->datalen != 0 ||
610 return NULL;
611 }
612
613 res.subclass.format = ast_format_cache_get_slin_by_rate(8000); /* ref bumped on dup */
614 res.samples = f->samples;
615 res.datalen = 0;
616 res.data.ptr = NULL;
618
619 return ast_frdup(&res);
620}
621
622/*! \brief do the actual translation */
623struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
624{
625 struct ast_trans_pvt *p = path;
626 struct ast_frame *out;
627 struct timeval delivery;
628 int has_timing_info;
629 long ts;
630 long len;
631 int seqno;
632
633 if (f->frametype == AST_FRAME_RTCP) {
634 /* Just pass the feedback to the right callback, if it exists.
635 * This "translation" does nothing so return a null frame. */
636 struct ast_trans_pvt *tp;
637 for (tp = p; tp; tp = tp->next) {
638 if (tp->t->feedback)
639 tp->t->feedback(tp, f);
640 }
641 return &ast_null_frame;
642 }
643
644 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
645 ts = f->ts;
646 len = f->len;
647 seqno = f->seqno;
648
649 if (!ast_tvzero(f->delivery)) {
650 if (!ast_tvzero(path->nextin)) {
651 /* Make sure this is in line with what we were expecting */
652 if (!ast_tveq(path->nextin, f->delivery)) {
653 /* The time has changed between what we expected and this
654 most recent time on the new packet. If we have a
655 valid prediction adjust our output time appropriately */
656 if (!ast_tvzero(path->nextout)) {
657 path->nextout = ast_tvadd(path->nextout,
658 ast_tvsub(f->delivery, path->nextin));
659 }
660 path->nextin = f->delivery;
661 }
662 } else {
663 /* This is our first pass. Make sure the timing looks good */
664 path->nextin = f->delivery;
665 path->nextout = f->delivery;
666 }
667 /* Predict next incoming sample */
668 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
670 }
671 delivery = f->delivery;
672 for (out = f; out && p ; p = p->next) {
673 struct ast_frame *current = out;
674
675 do {
676 framein(p, current);
678 } while (current);
679 if (out != f) {
681 }
682 out = p->t->frameout(p);
683 }
684
685 if (!out) {
687 }
688
689 if (out) {
690 /* we have a frame, play with times */
691 if (!ast_tvzero(delivery)) {
692 struct ast_frame *current = out;
693
694 do {
695 /* Regenerate prediction after a discontinuity */
696 if (ast_tvzero(path->nextout)) {
697 path->nextout = ast_tvnow();
698 }
699
700 /* Use next predicted outgoing timestamp */
701 current->delivery = path->nextout;
702
703 /* Invalidate prediction if we're entering a silence period */
704 if (current->frametype == AST_FRAME_CNG) {
705 path->nextout = ast_tv(0, 0);
706 /* Predict next outgoing timestamp from samples in this
707 frame. */
708 } else {
709 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
710 current->samples, ast_format_get_sample_rate(current->subclass.format)));
711 }
712
714 ast_debug(4, "Sample size different %d vs %d\n", f->samples, current->samples);
716 }
718 } while (current);
719 } else {
720 out->delivery = ast_tv(0, 0);
722 if (has_timing_info) {
723 out->ts = ts;
724 out->len = len;
725 out->seqno = seqno;
726 }
727 /* Invalidate prediction if we're entering a silence period */
728 if (out->frametype == AST_FRAME_CNG) {
729 path->nextout = ast_tv(0, 0);
730 }
731 }
732 }
733 if (consume) {
734 ast_frfree(f);
735 }
736 return out;
737}
738
739/*! Maximum number of pre-encoded frames cached for non-slin benchmark sources */
740#define PRE_ENCODE_POOL_MAX 200
741
742/*!
743 * \internal
744 * \brief Build a translation path from slin (8 kHz) to the source codec of
745 * translator \p t, using the already-populated translation matrix.
746 *
747 * \note Must be called with the translators list locked.
748 *
749 * \retval NULL Source codec is already slin, or no path through the matrix exists.
750 */
752{
753 struct ast_trans_pvt *head = NULL, *tail = NULL;
754 struct ast_codec *slin_codec;
755 int slin_index, dst_index;
756
757 if (!strcmp(t->src_codec.name, "slin")) {
758 return NULL; /* source is already slin, no pre-encoding needed */
759 }
760
761 slin_codec = ast_codec_get("slin", AST_MEDIA_TYPE_AUDIO, 8000);
762 if (!slin_codec) {
763 return NULL;
764 }
765
766 slin_index = codec2index(slin_codec);
767 ao2_ref(slin_codec, -1);
768
769 if (slin_index < 0) {
770 return NULL;
771 }
772
773 dst_index = t->src_fmt_index;
774 if (dst_index < 0 || slin_index == dst_index) {
775 return NULL;
776 }
777
778 while (slin_index != dst_index) {
779 struct ast_trans_pvt *cur;
780 struct ast_translator *step = matrix_get(slin_index, dst_index)->step;
781 if (!step) {
783 return NULL;
784 }
785 cur = newpvt(step, NULL);
786 if (!cur) {
788 return NULL;
789 }
790 if (!head) {
791 head = cur;
792 } else {
793 tail->next = cur;
794 }
795 tail = cur;
796 cur->nextin = cur->nextout = ast_tv(0, 0);
797 slin_index = cur->t->dst_fmt_index;
798 }
799
800 return head;
801}
802
803/*!
804 * \internal
805 * \brief Compute the computational cost of a single translation step.
806 *
807 * \note This function is only used to decide which translation path to
808 * use between two translators with identical src and dst formats. Computational
809 * cost acts only as a tie breaker. This is done so hardware translators
810 * can naturally have precedence over software translators.
811 */
812static void generate_computational_cost(struct ast_translator *t, int seconds)
813{
814 int num_samples = 0;
815 struct ast_trans_pvt *pvt;
816 struct rusage start;
817 struct rusage end;
818 int cost;
819 int out_rate = t->dst_codec.sample_rate;
820 struct ast_frame **pre_pool = NULL;
821 int pre_pool_count = 0;
822 int pre_pool_idx = 0;
823 int use_pre_pool = 0;
824
825 if (!seconds) {
826 seconds = 1;
827 }
828
829 /* If they don't make samples, give them a terrible score */
830 if (!t->sample) {
831 ast_debug(3, "Translator '%s' does not produce sample frames.\n", t->name);
832 t->comp_cost = 999999;
833 return;
834 }
835
836 pvt = newpvt(t, NULL);
837 if (!pvt) {
838 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
839 t->comp_cost = 999999;
840 return;
841 }
842
843 /*
844 * For non-CODEC sample types, pre-generate frames before starting the
845 * timer so sample-generation overhead is excluded from the measurement.
846 *
847 * For slin sources: isolate a fresh copy of each generated frame directly.
848 * For non-slin sources: route the generated slin frames through a
849 * slin->src_codec encoding path first. If no such path exists in the
850 * current matrix, use_pre_pool stays 0 and we fall back to t->sample().
851 */
853 int16_t slin_buf[80];
854 struct ast_frame slin_f;
855 struct ast_trans_pvt *pre_path = NULL;
856 int attempt;
857
858 if (strcmp(t->src_codec.name, "slin")) {
859 pre_path = build_slin_to_src_path(t);
860 }
861
862 if (!strcmp(t->src_codec.name, "slin") || pre_path) {
863 pre_pool = ast_malloc(PRE_ENCODE_POOL_MAX * sizeof(*pre_pool));
864 if (pre_pool) {
865 memset(&slin_f, 0, sizeof(slin_f));
866 slin_f.frametype = AST_FRAME_VOICE;
867 slin_f.datalen = sizeof(slin_buf);
868 slin_f.samples = ARRAY_LEN(slin_buf);
869 slin_f.data.ptr = slin_buf;
870 slin_f.src = __PRETTY_FUNCTION__;
871 slin_f.subclass.format = ast_format_slin;
872
873 for (attempt = 0; pre_pool_count < PRE_ENCODE_POOL_MAX; attempt++) {
874 struct ast_frame *out;
875
876 if (attempt >= PRE_ENCODE_POOL_MAX * 10) {
877 break; /* encoder not producing output; give up */
878 }
879
880 generate_samples(slin_buf, ARRAY_LEN(slin_buf),
881 attempt * (int)ARRAY_LEN(slin_buf));
882
883 if (pre_path) {
884 /* non-slin: encode through the pre_path chain */
885 struct ast_trans_pvt *pp;
886 out = &slin_f;
887 for (pp = pre_path; pp; pp = pp->next) {
888 struct ast_frame *next_out;
889 framein(pp, out);
890 if (out != &slin_f) {
892 }
893 next_out = pp->t->frameout(pp);
894 out = next_out;
895 if (!out) {
896 break;
897 }
898 }
899 } else {
900 /* slin: isolate a standalone copy of the frame */
902 }
903
904 if (out) {
905 pre_pool[pre_pool_count++] = out;
906 }
907 }
908 use_pre_pool = (pre_pool_count > 0);
909 }
910 ast_translator_free_path(pre_path);
911 }
912 }
913
914 getrusage(RUSAGE_SELF, &start);
915
916 /* Call the encoder until we've processed the required number of samples */
917 while (num_samples < seconds * out_rate) {
918 struct ast_frame *f;
919
920 if (use_pre_pool) {
921 /* cycle through the pre-generated frame pool */
922 framein(pvt, pre_pool[pre_pool_idx % pre_pool_count]);
923 pre_pool_idx++;
924 } else {
925 /* default: use the codec's own sample generator */
926 f = t->sample();
927 if (!f) {
928 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
929 destroy(pvt);
930 t->comp_cost = 999999;
931 goto cleanup;
932 }
933 framein(pvt, f);
934 ast_frfree(f);
935 }
936
937 while ((f = t->frameout(pvt))) {
938 num_samples += f->samples;
939 ast_frfree(f);
940 }
941 }
942
943 getrusage(RUSAGE_SELF, &end);
944
945 cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
946 cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
947
948 destroy(pvt);
949
950 t->comp_cost = cost / seconds;
951
952 if (!t->comp_cost) {
953 t->comp_cost = 1;
954 }
955
956cleanup:
957 if (pre_pool) {
958 int i;
959 for (i = 0; i < pre_pool_count; i++) {
960 ast_frfree(pre_pool[i]);
961 }
962 ast_free(pre_pool);
963 }
964}
965
966/*!
967 * \internal
968 *
969 * \brief If no table cost value was pre set by the translator. An attempt is made to
970 * automatically generate that cost value from the cost table based on our src and
971 * dst formats.
972 *
973 * \note This function allows older translators built before the translation cost
974 * changed away from using onely computational time to continue to be registered
975 * correctly. It is expected that translators built after the introduction of this
976 * function will manually assign their own table cost value.
977 *
978 * \note This function is safe to use on any audio formats that used to be defined in the
979 * first 64 bits of the old bit field codec representation.
980 *
981 * \return Table Cost value greater than 0.
982 * \retval 0 on error.
983 */
984static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
985{
986 int src_rate = src->sample_rate;
987 int src_ll = 0;
988 int dst_rate = dst->sample_rate;
989 int dst_ll = 0;
990
991 if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
992 (dst->type != AST_MEDIA_TYPE_AUDIO)) {
993 /* This method of generating table cost is limited to audio.
994 * Translators for media other than audio must manually set their
995 * table cost. */
996 return 0;
997 }
998
999 src_ll = !strcmp(src->name, "slin");
1000 dst_ll = !strcmp(dst->name, "slin");
1001 if (src_ll) {
1002 if (dst_ll && (src_rate == dst_rate)) {
1004 } else if (!dst_ll && (src_rate == dst_rate)) {
1006 } else if (dst_ll && (src_rate < dst_rate)) {
1008 } else if (!dst_ll && (src_rate < dst_rate)) {
1010 } else if (dst_ll && (src_rate > dst_rate)) {
1012 } else if (!dst_ll && (src_rate > dst_rate)) {
1014 } else {
1016 }
1017 } else {
1018 if (dst_ll && (src_rate == dst_rate)) {
1020 } else if (!dst_ll && (src_rate == dst_rate)) {
1022 } else if (dst_ll && (src_rate < dst_rate)) {
1024 } else if (!dst_ll && (src_rate < dst_rate)) {
1026 } else if (dst_ll && (src_rate > dst_rate)) {
1028 } else if (!dst_ll && (src_rate > dst_rate)) {
1030 } else {
1032 }
1033 }
1034}
1035
1036/*!
1037 * \brief rebuild a translation matrix.
1038 * \note This function expects the list of translators to be locked
1039*/
1040static void matrix_rebuild(int samples)
1041{
1042 struct ast_translator *t;
1043 int newtablecost;
1044 int x; /* source format index */
1045 int y; /* intermediate format index */
1046 int z; /* destination format index */
1047
1048 ast_debug(1, "Resetting translation matrix\n");
1049
1050 matrix_clear();
1051
1052 /* first, compute all direct costs */
1054 if (!t->active) {
1055 continue;
1056 }
1057
1058 x = t->src_fmt_index;
1059 z = t->dst_fmt_index;
1060
1061 if (samples) {
1062 generate_computational_cost(t, samples);
1063 }
1064
1065 /* This new translator is the best choice if any of the below are true.
1066 * 1. no translation path is set between x and z yet.
1067 * 2. the new table cost is less.
1068 * 3. the new computational cost is less. Computational cost is only used
1069 * to break a tie between two identical translation paths.
1070 */
1071 if (!matrix_get(x, z)->step ||
1072 (t->table_cost < matrix_get(x, z)->step->table_cost) ||
1073 (t->comp_cost < matrix_get(x, z)->step->comp_cost)) {
1074
1075 matrix_get(x, z)->step = t;
1076 matrix_get(x, z)->table_cost = t->table_cost;
1077 matrix_get(x, z)->comp_cost = t->comp_cost;
1078 }
1079 }
1080
1081 /*
1082 * For each triple x, y, z of distinct formats, check if there is
1083 * a path from x to z through y which is cheaper than what is
1084 * currently known, and in case, update the matrix.
1085 * Repeat until the matrix is stable.
1086 */
1087 for (;;) {
1088 int changed = 0;
1089 for (x = 0; x < cur_max_index; x++) { /* source format */
1090 for (y = 0; y < cur_max_index; y++) { /* intermediate format */
1091 if (x == y) { /* skip ourselves */
1092 continue;
1093 }
1094 for (z = 0; z < cur_max_index; z++) { /* dst format */
1095 if ((z == x || z == y) || /* skip null conversions */
1096 !matrix_get(x, y)->step || /* no path from x to y */
1097 !matrix_get(y, z)->step) { /* no path from y to z */
1098 continue;
1099 }
1100
1101 /* calculate table cost from x->y->z */
1102 newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost;
1103
1104 /* if no step already exists between x and z OR the new cost of using the intermediate
1105 * step is cheaper, use this step. */
1106 if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
1107 matrix_get(x, z)->step = matrix_get(x, y)->step;
1108 matrix_get(x, z)->table_cost = newtablecost;
1109 matrix_get(x, z)->multistep = 1;
1110 changed++;
1111
1112 if (DEBUG_ATLEAST(10)) {
1113 struct ast_codec *x_codec = index2codec(x);
1114 struct ast_codec *y_codec = index2codec(y);
1115 struct ast_codec *z_codec = index2codec(z);
1116
1118 "Discovered %u cost path from %s to %s, via %s\n",
1119 matrix_get(x, z)->table_cost, x_codec->name,
1120 y_codec->name, z_codec->name);
1121
1122 ao2_ref(x_codec, -1);
1123 ao2_ref(y_codec, -1);
1124 ao2_ref(z_codec, -1);
1125 }
1126 }
1127 }
1128 }
1129 }
1130 if (!changed) {
1131 break;
1132 }
1133 }
1134}
1135
1136static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
1137{
1138 if (codec) {
1139 ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
1140 } else {
1141 ast_str_append(buf, 0, "(nothing)");
1142 }
1143}
1144
1145const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
1146{
1147 if (!p || !p->t) {
1148 return "";
1149 }
1150
1153 while (p) {
1154 ast_str_append(str, 0, "->");
1156 p = p->next;
1157 }
1158
1159 return ast_str_buffer(*str);
1160}
1161
1162static char *complete_trans_path_choice(const char *word)
1163{
1164 int i = 1;
1165 int wordlen = strlen(word);
1166 struct ast_codec *codec;
1167
1168 while ((codec = ast_codec_get_by_id(i))) {
1169 ++i;
1170 if (codec->type != AST_MEDIA_TYPE_AUDIO) {
1171 ao2_ref(codec, -1);
1172 continue;
1173 }
1174 if (!strncasecmp(word, codec->name, wordlen)) {
1175 if (ast_cli_completion_add(ast_strdup(codec->name))) {
1176 ao2_ref(codec, -1);
1177 break;
1178 }
1179 }
1180 ao2_ref(codec, -1);
1181 }
1182
1183 return NULL;
1184}
1185
1187{
1188 int time = a->argv[4] ? atoi(a->argv[4]) : 1;
1189
1190 if (time <= 0) {
1191 ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n");
1192 time = 1;
1193 }
1194
1195 if (time > MAX_RECALC) {
1196 ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", time - MAX_RECALC, MAX_RECALC);
1197 time = MAX_RECALC;
1198 }
1199 ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
1201 matrix_rebuild(time);
1203}
1204
1206{
1207 int x, y, i, k, compCost;
1208 int longest = 7; /* slin192 */
1209 int max_codec_index = 0, curlen = 0;
1210 struct ast_str *out = ast_str_create(1024);
1211 struct ast_codec *codec;
1212
1213 /* Get the length of the longest (usable?) codec name,
1214 so we know how wide the left side should be */
1215 for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
1216 ++max_codec_index;
1217 if (codec->type != AST_MEDIA_TYPE_AUDIO) {
1218 continue;
1219 }
1220 curlen = strlen(codec->name);
1221 if (curlen > longest) {
1222 longest = curlen;
1223 }
1224 }
1225
1227 ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
1228 ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
1229
1230 for (i = 0; i <= max_codec_index; i++) {
1231 struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
1232
1233 x = -1;
1234 if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
1235 ao2_ref(row, -1);
1236 continue;
1237 }
1238
1239 if ((i > 0) && (x = codec2index(row)) == -1) {
1240 ao2_ref(row, -1);
1241 continue;
1242 }
1243
1244 ast_str_set(&out, 0, " ");
1245 for (k = 0; k <= max_codec_index; k++) {
1246 int adjust = 0;
1247 struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
1248
1249 y = -1;
1250 if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
1251 ao2_ref(col, -1);
1252 continue;
1253 }
1254
1255 if ((k > 0) && (y = codec2index(col)) == -1) {
1256 ao2_ref(col, -1);
1257 continue;
1258 }
1259
1260 if (k > 0) {
1261 curlen = strlen(col->name);
1262 if (!strcmp(col->name, "slin") ||
1263 !strcmp(col->name, "speex") ||
1264 !strcmp(col->name, "silk")) {
1265 adjust = log10(col->sample_rate / 1000) + 1;
1266 curlen = curlen + adjust;
1267 }
1268 }
1269
1270 if (curlen < 5) {
1271 curlen = 5;
1272 }
1273
1274 if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
1275 /* Actual codec output */
1276 if (a->argv[3] && !strcasecmp(a->argv[3], "comp")) {
1277 compCost = matrix_get(x, y)->comp_cost;
1278 if (compCost == 0 || compCost == 999999) {
1279 ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1280 } else {
1281 ast_str_append(&out, 0, "%*u", curlen + 1, compCost);
1282 }
1283 } else {
1284 ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost / 100));
1285 }
1286 } else if (i == 0 && k > 0) {
1287 /* Top row - use a dynamic size */
1288 if (!strcmp(col->name, "slin") ||
1289 !strcmp(col->name, "speex") ||
1290 !strcmp(col->name, "silk")) {
1291 ast_str_append(&out, 0, "%*s%u", curlen - adjust + 1,
1292 col->name, col->sample_rate / 1000);
1293 } else {
1294 ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
1295 }
1296 } else if (k == 0 && i > 0) {
1297 /* Left column - use a static size. */
1298 if (!strcmp(row->name, "slin") ||
1299 !strcmp(row->name, "speex") ||
1300 !strcmp(row->name, "silk")) {
1301 int adjust_row = log10(row->sample_rate / 1000) + 1;
1302 ast_str_append(&out, 0, "%*s%u", longest - adjust_row,
1303 row->name, row->sample_rate / 1000);
1304 } else {
1305 ast_str_append(&out, 0, "%*s", longest, row->name);
1306 }
1307 } else if (x >= 0 && y >= 0) {
1308 /* Codec not supported */
1309 ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1310 } else {
1311 /* Upper left hand corner */
1312 ast_str_append(&out, 0, "%*s", longest, "");
1313 }
1314 ao2_cleanup(col);
1315 }
1316 ast_str_append(&out, 0, "\n");
1317 ast_cli(a->fd, "%s", ast_str_buffer(out));
1318 ao2_cleanup(row);
1319 }
1320 ast_free(out);
1322 return CLI_SUCCESS;
1323}
1324
1325static char *handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
1326{
1327 int i = 1;
1328 struct ast_str *str = ast_str_alloca(1024);
1329 struct ast_translator *step;
1330 struct ast_codec *dst_codec;
1331 struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
1332
1333 if (!src_codec) {
1334 ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
1335 return CLI_FAILURE;
1336 }
1337
1339 ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1340 codec_name, src_codec->sample_rate);
1341
1342 while ((dst_codec = ast_codec_get_by_id(i))) {
1343 int src, dst;
1344 char src_buffer[64];
1345 char dst_buffer[64];
1346
1347 ++i;
1348 if (src_codec == dst_codec ||
1349 dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
1350 ao2_ref(dst_codec, -1);
1351 continue;
1352 }
1353
1354 dst = codec2index(dst_codec);
1355 src = codec2index(src_codec);
1356
1357 if (src < 0 || dst < 0) {
1358 ast_str_set(&str, 0, "No Translation Path");
1359 } else {
1360 step = matrix_get(src, dst)->step;
1361
1362 if (step) {
1364 while (src != dst) {
1365 src = step->dst_fmt_index;
1366 step = matrix_get(src, dst)->step;
1367 if (!step) {
1368 ast_str_append(&str, 0, "->");
1369 codec_append_name(dst_codec, &str);
1370 break;
1371 }
1372 ast_str_append(&str, 0, "->");
1374 }
1375 }
1376 }
1377
1378 snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
1379 snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
1380 ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
1381 src_buffer, dst_buffer, ast_str_buffer(str));
1383 ao2_ref(dst_codec, -1);
1384 }
1386 ao2_ref(src_codec, -1);
1387 return CLI_SUCCESS;
1388}
1389
1390static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1391{
1392 static const char * const option[] = { "recalc", "paths", "comp", NULL };
1393
1394 switch (cmd) {
1395 case CLI_INIT:
1396 e->command = "core show translation";
1397 e->usage =
1398 "Usage: 'core show translation' can be used in three ways.\n"
1399 " 1. 'core show translation [recalc [<recalc seconds>]\n"
1400 " Displays known codec translators and the cost associated\n"
1401 " with each conversion. If the argument 'recalc' is supplied along\n"
1402 " with optional number of seconds to test a new test will be performed\n"
1403 " as the chart is being displayed.\n"
1404 " 2. 'core show translation paths [codec [sample_rate]]'\n"
1405 " This will display all the translation paths associated with a codec.\n"
1406 " If a codec has multiple sample rates, the sample rate must be\n"
1407 " provided as well.\n"
1408 " 3. 'core show translation comp [<recalc seconds>]'\n"
1409 " Displays known codec translators and the cost associated\n"
1410 " with each conversion. If the argument 'recalc' is supplied along\n"
1411 " with optional number of seconds to test a new test will be performed\n"
1412 " as the chart is being displayed. The resulting numbers in the table\n"
1413 " give the actual computational costs in microseconds.\n";
1414 return NULL;
1415 case CLI_GENERATE:
1416 if (a->pos == 3) {
1417 return ast_cli_complete(a->word, option, -1);
1418 }
1419 if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
1420 return complete_trans_path_choice(a->word);
1421 }
1422 /* BUGBUG - add tab completion for sample rates */
1423 return NULL;
1424 }
1425
1426 if (a->argc > 6)
1427 return CLI_SHOWUSAGE;
1428
1429 if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
1430 return handle_show_translation_path(a, a->argv[4], 0);
1431 } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
1432 unsigned int sample_rate;
1433 if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
1434 ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
1435 return CLI_FAILURE;
1436 }
1437 return handle_show_translation_path(a, a->argv[4], sample_rate);
1438 } else if (a->argv[3] && (!strcasecmp(a->argv[3], option[0]) || !strcasecmp(a->argv[3], option[2]))) { /* recalc and then fall through to show table */
1440 } else if (a->argc > 3) { /* wrong input */
1441 return CLI_SHOWUSAGE;
1442 }
1443
1445}
1446
1448 int cmd, struct ast_cli_args *a)
1449{
1450 static const char * const types[] = { "codec", "sine", "silence", "noise", "speech", NULL };
1451
1452 switch (cmd) {
1453 case CLI_INIT:
1454 e->command = "translate sampletype";
1455 e->usage =
1456 "Usage: translate sampletype [codec|sine|silence|noise|speech]\n"
1457 " Get or set the sample type used for codec matrix cost\n"
1458 " computation. Default is 'codec'.\n"
1459 " codec - samples defined inside codec\n"
1460 " sine - 1kHz sine wave\n"
1461 " silence - All-zero frames\n"
1462 " noise - White noise\n"
1463 " speech - Synthetic speech-like signal (P.50 inspired)\n";
1464 return NULL;
1465 case CLI_GENERATE:
1466 return ast_cli_complete(a->word, types, a->n);
1467 }
1468
1469 if (a->argc == 2) {
1470 /* Query current setting */
1471 const char *names[] = { "codec", "sine", "silence", "noise", "speech" };
1472 ast_cli(a->fd, "Current translate sample type: %s\n",
1473 names[current_sample_type]);
1474 return CLI_SUCCESS;
1475 }
1476
1477 if (a->argc != 3)
1478 return CLI_SHOWUSAGE;
1479
1480 if (!strcasecmp(a->argv[2], "silence")) {
1482 } else if (!strcasecmp(a->argv[2], "noise")) {
1484 } else if (!strcasecmp(a->argv[2], "speech")) {
1486 } else if (!strcasecmp(a->argv[2], "sine")) {
1488 } else if (!strcasecmp(a->argv[2], "codec")) {
1490 } else {
1491 ast_cli(a->fd, "Unknown sample type '%s'. Use: codec, sine, silence, noise, speech\n",
1492 a->argv[2]);
1493 return CLI_SHOWUSAGE;
1494 }
1495
1496 /* Rebuild the matrix with the new sample type */
1497 ast_cli(a->fd, "Sample type set to '%s'. Rebuilding codec matrix...\n", a->argv[2]);
1499 matrix_rebuild(1);
1501
1502 return CLI_SUCCESS;
1503}
1504
1505static struct ast_cli_entry cli_translate[] = {
1506 AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix"),
1507 AST_CLI_DEFINE(handle_cli_translate_sampletype, "Get/set codec matrix sample type"),
1508};
1509
1510/*! \brief register codec translator */
1512{
1513 struct ast_translator *u;
1514 char tmp[80];
1517
1519 if (!src_codec) {
1520 ast_assert(0);
1521 ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
1522 return -1;
1523 }
1524
1526 if (!dst_codec) {
1527 ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
1528 return -1;
1529 }
1530
1532 if (matrix_resize(0)) {
1533 ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n");
1534 return -1;
1535 }
1538 }
1539
1540 if (!mod) {
1541 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
1542 return -1;
1543 }
1544
1545 if (!t->buf_size) {
1546 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
1547 return -1;
1548 }
1550 ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
1551 "Please set table_cost variable on translator.\n", t->name);
1552 return -1;
1553 }
1554
1555 t->module = mod;
1558 t->active = 1;
1559
1560 if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
1561 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index < 0 ? "starting" : "ending");
1562 return -1;
1563 }
1564 if (t->src_fmt_index >= cur_max_index) {
1565 ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
1566 return -1;
1567 }
1568
1569 if (t->dst_fmt_index >= cur_max_index) {
1570 ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
1571 return -1;
1572 }
1573
1574 if (t->buf_size) {
1575 /*
1576 * Align buf_size properly, rounding up to the machine-specific
1577 * alignment for pointers.
1578 */
1579 struct _test_align { void *a, *b; } p;
1580 int align = (char *)&p.b - (char *)&p.a;
1581
1582 t->buf_size = ((t->buf_size + align - 1) / align) * align;
1583 }
1584
1585 if (t->frameout == NULL) {
1587 }
1588
1590
1591 ast_verb(5, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1592 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1594
1596
1597 /* find any existing translators that provide this same srcfmt/dstfmt,
1598 and put this one in order based on computational cost */
1600 if ((u->src_fmt_index == t->src_fmt_index) &&
1601 (u->dst_fmt_index == t->dst_fmt_index) &&
1602 (u->comp_cost > t->comp_cost)) {
1604 t = NULL;
1605 break;
1606 }
1607 }
1609
1610 /* if no existing translator was found for this codec combination,
1611 add it to the beginning of the list */
1612 if (t) {
1614 }
1615
1616 matrix_rebuild(0);
1617
1619
1620 return 0;
1621}
1622
1623/*! \brief unregister codec translator */
1625{
1626 char tmp[80];
1627 struct ast_translator *u;
1628 int found = 0;
1629
1632 if (u == t) {
1634 ast_verb(5, "Unregistered translator '%s' from codec %s to %s\n",
1635 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1636 t->src_codec.name, t->dst_codec.name);
1637 found = 1;
1638 break;
1639 }
1640 }
1642
1643 if (found && !ast_shutting_down()) {
1644 matrix_rebuild(0);
1645 }
1646
1648
1649 return (u ? 0 : -1);
1650}
1651
1659
1667
1668/*! Calculate the absolute difference between sample rate of two formats. */
1669#define format_sample_rate_absdiff(fmt1, fmt2) ({ \
1670 unsigned int rate1 = ast_format_get_sample_rate(fmt1); \
1671 unsigned int rate2 = ast_format_get_sample_rate(fmt2); \
1672 (rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \
1673})
1674
1675/*! \brief Calculate our best translator source format, given costs, and a desired destination */
1677 struct ast_format_cap *src_cap,
1678 struct ast_format **dst_fmt_out,
1679 struct ast_format **src_fmt_out)
1680{
1681 unsigned int besttablecost = INT_MAX;
1682 unsigned int beststeps = INT_MAX;
1683 struct ast_format *fmt;
1684 struct ast_format *dst;
1685 struct ast_format *src;
1686 RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
1687 RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
1688 struct ast_format_cap *joint_cap;
1689 int i;
1690 int j;
1691
1692 if (ast_format_cap_empty(dst_cap) || ast_format_cap_empty(src_cap)) {
1693 ast_log(LOG_ERROR, "Cannot determine best translation path since one capability supports no formats\n");
1694 return -1;
1695 }
1696
1698 if (!joint_cap) {
1699 return -1;
1700 }
1701 ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
1702
1703 for (i = 0; i < ast_format_cap_count(joint_cap); ++i, ao2_cleanup(fmt)) {
1704 fmt = ast_format_cap_get_format(joint_cap, i);
1705 if (!fmt
1707 continue;
1708 }
1709
1710 if (!best
1712 ao2_replace(best, fmt);
1713 }
1714 }
1715 ao2_ref(joint_cap, -1);
1716
1717 if (best) {
1718 ao2_replace(*dst_fmt_out, best);
1719 ao2_replace(*src_fmt_out, best);
1720 return 0;
1721 }
1722
1723 /* need to translate */
1725 for (i = 0; i < ast_format_cap_count(dst_cap); ++i, ao2_cleanup(dst)) {
1726 dst = ast_format_cap_get_format(dst_cap, i);
1727 if (!dst
1729 continue;
1730 }
1731
1732 for (j = 0; j < ast_format_cap_count(src_cap); ++j, ao2_cleanup(src)) {
1733 int x;
1734 int y;
1735
1736 src = ast_format_cap_get_format(src_cap, j);
1737 if (!src
1739 continue;
1740 }
1741
1742 x = format2index(src);
1743 y = format2index(dst);
1744 if (x < 0 || y < 0) {
1745 continue;
1746 }
1747 if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
1748 continue;
1749 }
1750 if (matrix_get(x, y)->table_cost < besttablecost
1751 || matrix_get(x, y)->multistep < beststeps) {
1752 /* better than what we have so far */
1753 ao2_replace(best, src);
1754 ao2_replace(bestdst, dst);
1755 besttablecost = matrix_get(x, y)->table_cost;
1756 beststeps = matrix_get(x, y)->multistep;
1757 } else if (matrix_get(x, y)->table_cost == besttablecost
1758 && matrix_get(x, y)->multistep == beststeps) {
1759 int replace = 0;
1760 unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst);
1761 unsigned int gap_current = format_sample_rate_absdiff(src, dst);
1762
1763 if (gap_current < gap_selected) {
1764 /* better than what we have so far */
1765 replace = 1;
1766 } else if (gap_current == gap_selected) {
1767 int src_quality, best_quality;
1768 struct ast_codec *src_codec, *best_codec;
1769
1770 src_codec = ast_format_get_codec(src);
1771 best_codec = ast_format_get_codec(best);
1772 src_quality = src_codec->quality;
1773 best_quality = best_codec->quality;
1774
1775 ao2_cleanup(src_codec);
1776 ao2_cleanup(best_codec);
1777
1778 /* We have a tie, so choose the format with the higher quality, if they differ. */
1779 if (src_quality > best_quality) {
1780 /* Better than what we had before. */
1781 replace = 1;
1782 ast_debug(2, "Tiebreaker: preferring format %s (%d) to %s (%d)\n", ast_format_get_name(src), src_quality,
1783 ast_format_get_name(best), best_quality);
1784 } else {
1785 /* This isn't necessarily indicative of a problem, but in reality this shouldn't really happen, unless
1786 * there are 2 formats that are basically the same. */
1787 ast_debug(1, "Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1788 ast_format_get_name(src), ast_format_get_name(best), best_quality, ast_format_get_name(best));
1789 }
1790 }
1791 if (replace) {
1792 ao2_replace(best, src);
1793 ao2_replace(bestdst, dst);
1794 besttablecost = matrix_get(x, y)->table_cost;
1795 beststeps = matrix_get(x, y)->multistep;
1796 }
1797 }
1798 }
1799 }
1801
1802 if (!best) {
1803 return -1;
1804 }
1805 ao2_replace(*dst_fmt_out, bestdst);
1806 ao2_replace(*src_fmt_out, best);
1807 return 0;
1808}
1809
1810unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format)
1811{
1812 unsigned int res = -1;
1813 /* convert bitwise format numbers into array indices */
1814 int src = format2index(src_format);
1815 int dest = format2index(dst_format);
1816
1817 if (src < 0 || dest < 0) {
1818 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
1819 return -1;
1820 }
1822
1823 if (matrix_get(src, dest)->step) {
1824 res = matrix_get(src, dest)->multistep + 1;
1825 }
1826
1828
1829 return res;
1830}
1831
1833 struct ast_format_cap *dest, struct ast_format_cap *src,
1834 struct ast_format_cap *result, struct ast_format *src_fmt,
1835 enum ast_media_type type)
1836{
1837 int i;
1838
1839 if (ast_format_get_type(src_fmt) != type) {
1840 return;
1841 }
1842
1843 /* For a given source format, traverse the list of
1844 known formats to determine whether there exists
1845 a translation path from the source format to the
1846 destination format. */
1847 for (i = ast_format_cap_count(result) - 1; 0 <= i; i--) {
1848 int index, src_index;
1850
1851 if (ast_format_get_type(fmt) != type) {
1852 continue;
1853 }
1854
1855 /* if this is not a desired format, nothing to do */
1857 continue;
1858 }
1859
1860 /* if the source is supplying this format, then
1861 we can leave it in the result */
1863 continue;
1864 }
1865
1866 /* if this is a pass-through format, not in the source,
1867 we cannot transcode. Therefore, remove it from the result */
1868 src_index = format2index(src_fmt);
1869 index = format2index(fmt);
1870 if (src_index < 0 || index < 0) {
1872 continue;
1873 }
1874
1875 /* if we don't have a translation path from the src
1876 to this format, remove it from the result */
1877 if (!matrix_get(src_index, index)->step) {
1879 continue;
1880 }
1881
1882 /* now check the opposite direction */
1883 if (!matrix_get(index, src_index)->step) {
1885 }
1886 }
1887
1888}
1889
1891{
1892 struct ast_format *cur_dest, *cur_src;
1893 int index;
1894
1895 for (index = 0; index < ast_format_cap_count(dest); ++index) {
1896 if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
1897 continue;
1898 }
1899
1900 /* We give preference to a joint format structure if possible */
1901 if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
1902 ast_format_cap_append(result, cur_src, 0);
1903 ao2_ref(cur_src, -1);
1904 } else {
1905 /* Otherwise we just use the destination format */
1906 ast_format_cap_append(result, cur_dest, 0);
1907 }
1908 ao2_ref(cur_dest, -1);
1909 }
1910
1911 /* if we don't have a source format, we just have to try all
1912 possible destination formats */
1913 if (!src) {
1914 return;
1915 }
1916
1917 for (index = 0; index < ast_format_cap_count(src); ++index) {
1918 if (!(cur_src = ast_format_cap_get_format(src, index))) {
1919 continue;
1920 }
1921
1923 check_translation_path(dest, src, result,
1924 cur_src, AST_MEDIA_TYPE_AUDIO);
1925 check_translation_path(dest, src, result,
1926 cur_src, AST_MEDIA_TYPE_VIDEO);
1928 ao2_ref(cur_src, -1);
1929 }
1930}
1931
1932static void translate_shutdown(void)
1933{
1934 int x;
1936
1938 for (x = 0; x < index_size; x++) {
1939 ast_free(__matrix[x]);
1940 }
1942 __matrix = NULL;
1947}
1948
1950{
1951 int res = 0;
1953 res = matrix_resize(1);
1956 return res;
1957}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
const char * str
Definition app_jack.c:150
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition clicompat.c:19
int ast_shutting_down(void)
Definition asterisk.c:1889
#define ast_free(a)
Definition astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
#define ast_log
Definition astobj2.c:42
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
static PGresult * result
Definition cel_pgsql.c:84
static const char type[]
General Asterisk PBX channel definitions.
size_t current
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition main/cli.c:2845
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition main/cli.c:1931
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
ast_media_type
Types of media.
Definition codec.h:30
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition codec.h:33
struct ast_codec * ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
Retrieve a codec given a name, type, and sample rate.
Definition codec.c:327
struct ast_codec * ast_codec_get_by_id(int id)
Retrieve a codec given the unique identifier.
Definition codec.c:338
short word
char * end
Definition eagi_proxy.c:73
char buf[BUFSIZE]
Definition eagi_proxy.c:66
Media Format API.
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition format.c:354
unsigned int ast_format_get_codec_id(const struct ast_format *format)
Get the codec identifier associated with a format.
Definition format.c:329
struct ast_codec * ast_format_get_codec(const struct ast_format *format)
Get the codec associated with a format.
Definition format.c:324
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition format.c:379
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
@ AST_FORMAT_CMP_NOT_EQUAL
Definition format.h:38
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition format.c:334
struct ast_format * ast_format_create(struct ast_codec *codec)
Create a new media format.
Definition format.c:196
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition format_cap.c:744
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition format_cap.c:400
int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
Remove format capability from capability structure.
Definition format_cap.c:495
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition format_cap.c:628
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition format_cap.c:581
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition format_cap.c:395
struct ast_format * ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if input ast_format is within the capabilities of the ast_format_cap object then return the comp...
Definition format_cap.c:546
static struct ast_format_def slin_f
Definition format_sln.c:128
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Asterisk internal frame definitions.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frdup(fr)
Copies a frame.
#define ast_frfree(fr)
@ AST_FRFLAG_HAS_TIMING_INFO
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
struct ast_frame ast_null_frame
Definition main/frame.c:79
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_DEBUG
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_HEAD
#define AST_RWLIST_INSERT_BEFORE_CURRENT
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Asterisk locking-related definitions:
#define ast_rwlock_wrlock(a)
Definition lock.h:243
#define ast_rwlock_rdlock(a)
Definition lock.h:242
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition lock.h:231
#define ast_rwlock_destroy(rwlock)
Definition lock.h:240
#define ast_rwlock_unlock(a)
Definition lock.h:241
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
Definition module.h:483
#define ast_module_ref(mod)
Hold a reference to the module.
Definition module.h:457
#define ast_opt_generic_plc
Definition options.h:144
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition res_stasis.c:327
#define NULL
Definition resample.c:96
#define M_PI
Definition resample.c:83
Scheduler Routines (derived from cheops)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
#define ast_str_alloca(init_len)
Definition strings.h:848
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition strings.h:693
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
descriptor for a cli entry.
Definition cli.h:171
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
Represents a media codec within Asterisk.
Definition codec.h:42
unsigned int sample_rate
Sample rate (number of samples carried in a second)
Definition codec.h:52
enum ast_media_type type
Type of media this codec contains.
Definition codec.h:50
unsigned int quality
Format quality, on scale from 0 to 150 (100 is ulaw, the reference). This allows better format to be ...
Definition codec.h:82
const char * name
Name for this codec.
Definition codec.h:46
unsigned int id
Internal unique identifier for this codec, set at registration time (starts at 1)
Definition codec.h:44
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
struct ast_format * format
Definition mod_format.h:48
Definition of a media format.
Definition format.c:43
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype
union ast_frame::@235 data
Structure for rwlock and tracking information.
Definition lock.h:164
Support for dynamic strings.
Definition strings.h:623
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition translate.h:213
struct timeval nextout
Definition translate.h:229
struct ast_frame f
Definition translate.h:215
struct timeval nextin
Definition translate.h:228
struct ast_trans_pvt * next
Definition translate.h:227
struct ast_translator * t
Definition translate.h:214
union ast_trans_pvt::@304 outbuf
struct ast_format * explicit_dst
Definition translate.h:237
int datalen
actual space used in outbuf
Definition translate.h:218
Descriptor of a translator.
Definition translate.h:137
struct ast_module *int active
Definition translate.h:187
void(* destroy)(struct ast_trans_pvt *pvt)
Definition translate.h:166
char name[80]
Definition translate.h:138
struct ast_frame *(* sample)(void)
Definition translate.h:170
void(* feedback)(struct ast_trans_pvt *pvt, struct ast_frame *feedback)
Definition translate.h:162
int buffer_samples
size of outbuf, in samples. Leave it 0 if you want the framein callback deal with the frame....
Definition translate.h:177
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
Definition translate.h:182
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
Definition translate.h:154
struct ast_codec src_codec
Definition translate.h:139
struct ast_translator::@303 list
struct ast_frame *(* frameout)(struct ast_trans_pvt *pvt)
Definition translate.h:158
int(* newpvt)(struct ast_trans_pvt *)
Definition translate.h:151
struct ast_codec dst_codec
Definition translate.h:140
struct ast_translator * step
Definition translate.c:117
uint32_t table_cost
Definition translate.c:118
uint8_t multistep
Definition translate.c:120
uint32_t comp_cost
Definition translate.c:119
the list of translators
Handy terminal functions for vt* terms.
#define COLOR_MAGENTA
Definition term.h:60
#define COLOR_BLACK
Definition term.h:50
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition term.c:235
static struct test_val b
static struct test_val a
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition time.h:282
int ast_tveq(struct timeval _a, struct timeval _b)
Returns true if the two struct timeval arguments are equal.
Definition time.h:147
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition time.h:117
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition extconf.c:2280
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition extconf.c:2295
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition time.h:235
static char * handle_show_translation_table(struct ast_cli_args *a)
Definition translate.c:1205
unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format)
Returns the number of steps required to convert from 'src' to 'dest'.
Definition translate.c:1810
static int cur_max_index
Definition translate.c:152
#define format_sample_rate_absdiff(fmt1, fmt2)
Definition translate.c:1669
sample_type
Definition translate.c:50
@ SAMPLE_TYPE_NOISE
Definition translate.c:54
@ SAMPLE_TYPE_SINE
Definition translate.c:52
@ SAMPLE_TYPE_CODEC
Definition translate.c:51
@ SAMPLE_TYPE_SILENCE
Definition translate.c:53
@ SAMPLE_TYPE_SPEECH
Definition translate.c:55
static void check_translation_path(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result, struct ast_format *src_fmt, enum ast_media_type type)
Definition translate.c:1832
void ast_translator_activate(struct ast_translator *t)
Activate a previously deactivated translator.
Definition translate.c:1652
static uint32_t lcg_rand(void)
Definition translate.c:62
static void handle_cli_recalc(struct ast_cli_args *a)
Definition translate.c:1186
static int add_codec2index(struct ast_codec *codec)
Definition translate.c:205
static int codec_to_index(unsigned int id)
Definition translate.c:162
static struct ast_frame * default_frameout(struct ast_trans_pvt *pvt)
Definition translate.c:526
void ast_translator_free_path(struct ast_trans_pvt *p)
Frees a translator path Frees the given translator path structure.
Definition translate.c:533
static ast_rwlock_t tablelock
Definition translate.c:144
static void matrix_rebuild(int samples)
rebuild a translation matrix.
Definition translate.c:1040
int ast_unregister_translator(struct ast_translator *t)
unregister codec translator
Definition translate.c:1624
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them,...
Definition translate.c:496
#define INIT_INDEX
Definition translate.c:147
static void matrix_clear(void)
Definition translate.c:326
void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
Find available formats.
Definition translate.c:1890
static int matrix_resize(int init)
Definition translate.c:252
static int index_size
Definition translate.c:154
void ast_translator_deactivate(struct ast_translator *t)
Deactivate a translator.
Definition translate.c:1660
static unsigned int * __indextable
table for converting index to format values.
Definition translate.c:141
int ast_translator_best_choice(struct ast_format_cap *dst_cap, struct ast_format_cap *src_cap, struct ast_format **dst_fmt_out, struct ast_format **src_fmt_out)
Calculate our best translator source format, given costs, and a desired destination.
Definition translate.c:1676
const char * ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
Definition translate.c:1145
static struct ast_trans_pvt * build_slin_to_src_path(const struct ast_translator *t)
Definition translate.c:751
static struct ast_trans_pvt * newpvt(struct ast_translator *t, struct ast_format *explicit_dst)
Allocate the descriptor, required outbuf space, and possibly desc.
Definition translate.c:369
struct ast_frame * ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
do the actual translation
Definition translate.c:623
#define PRE_ENCODE_POOL_MAX
Definition translate.c:740
static enum sample_type current_sample_type
Definition translate.c:58
static struct translator_path ** __matrix
a matrix that, for any pair of supported formats, indicates the total cost of translation and the fir...
Definition translate.c:134
static void generate_samples(int16_t *buf, int samples, int offset)
Fill a buffer with samples of the selected type.
Definition translate.c:74
static char * handle_cli_translate_sampletype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition translate.c:1447
static int codec2index(struct ast_codec *codec)
Definition translate.c:182
static struct translator_path * matrix_get(unsigned int x, unsigned int y)
Definition translate.c:340
static void translate_shutdown(void)
Definition translate.c:1932
static void generate_computational_cost(struct ast_translator *t, int seconds)
Definition translate.c:812
int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
register codec translator
Definition translate.c:1511
static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
Definition translate.c:1136
#define MAX_RECALC
Definition translate.c:111
static char * handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
Definition translate.c:1325
static struct ast_cli_entry cli_translate[]
Definition translate.c:1505
static void destroy(struct ast_trans_pvt *pvt)
Definition translate.c:349
static uint32_t lcg_state
Definition translate.c:61
static struct ast_frame * generate_interpolated_slin(struct ast_trans_pvt *p, struct ast_frame *f)
Definition translate.c:594
static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
Definition translate.c:984
static struct ast_codec * index2codec(int index)
Definition translate.c:228
static char * complete_trans_path_choice(const char *word)
Definition translate.c:1162
static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
framein wrapper, deals with bound checks.
Definition translate.c:454
static int format2index(struct ast_format *format)
Definition translate.c:191
#define GROW_INDEX
Definition translate.c:149
static char * handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition translate.c:1390
struct ast_trans_pvt * ast_translator_build_path(struct ast_format *dst, struct ast_format *src)
Build a chain of translators based upon the given source and dest formats.
Definition translate.c:543
int ast_translate_init(void)
Initialize the translation matrix and index to format conversion table.
Definition translate.c:1949
Support for translation of data formats. translate.c.
@ AST_TRANS_COST_LY_LY_DOWNSAMP
Definition translate.h:100
@ AST_TRANS_COST_LL_LL_DOWNSAMP
Definition translate.h:76
@ AST_TRANS_COST_LY_LY_ORIGSAMP
Definition translate.h:90
@ AST_TRANS_COST_LL_LL_UPSAMP
Definition translate.h:71
@ AST_TRANS_COST_LY_LL_ORIGSAMP
Definition translate.h:88
@ AST_TRANS_COST_LL_UNKNOWN
Definition translate.h:83
@ AST_TRANS_COST_LY_LL_DOWNSAMP
Definition translate.h:98
@ AST_TRANS_COST_LL_LY_DOWNSAMP
Definition translate.h:78
@ AST_TRANS_COST_LL_LY_ORIGSAMP
Definition translate.h:68
@ AST_TRANS_COST_LY_UNKNOWN
Definition translate.h:105
@ AST_TRANS_COST_LL_LY_UPSAMP
Definition translate.h:73
@ AST_TRANS_COST_LY_LY_UPSAMP
Definition translate.h:95
@ AST_TRANS_COST_LY_LL_UPSAMP
Definition translate.h:93
@ AST_TRANS_COST_LL_LL_ORIGSAMP
Definition translate.h:66
FILE * out
Definition utils/frame.c:33
#define ast_test_flag(p, flag)
Definition utils.h:64
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981
#define ast_assert(a)
Definition utils.h:779
#define ast_set2_flag(p, value, flag)
Definition utils.h:95
#define ast_clear_flag(p, flag)
Definition utils.h:78
#define ARRAY_LEN(a)
Definition utils.h:706
#define ast_copy_flags(dest, src, flagz)
Definition utils.h:85