#include "asterisk/frame.h"
#include "asterisk/plc.h"
#include "asterisk/linkedlists.h"
Go to the source code of this file.
Data Structures | |
struct | ast_trans_pvt |
Default structure for translators, with the basic fields and buffers, all allocated as part of the same chunk of memory. The buffer is preceded by AST_FRIENDLY_OFFSET bytes in front of the user portion. 'buf' points right after this space. More... | |
struct | ast_translator |
Descriptor of a translator. Name, callbacks, and various options related to run-time operation (size of buffers, auxiliary descriptors, etc). More... | |
Defines | |
#define | ast_register_translator(t) __ast_register_translator(t, ast_module_info->self) |
#define | MAX_FORMAT 32 |
Functions | |
int | __ast_register_translator (struct ast_translator *t, struct ast_module *module) |
Register a translator This registers a codec translator with asterisk. | |
struct ast_frame * | ast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples) |
generic frameout function | |
struct ast_frame * | ast_translate (struct ast_trans_pvt *tr, struct ast_frame *f, int consume) |
translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed | |
unsigned int | ast_translate_available_formats (unsigned int dest, unsigned int src) |
Mask off unavailable formats from a format bitmask. | |
unsigned int | ast_translate_path_steps (unsigned int dest, unsigned int src) |
Returns the number of steps required to convert from 'src' to 'dest'. | |
void | ast_translator_activate (struct ast_translator *t) |
Activate a previously deactivated translator. | |
int | ast_translator_best_choice (int *dsts, int *srcs) |
Chooses the best translation path. | |
struct ast_trans_pvt * | ast_translator_build_path (int dest, int source) |
Builds a translator path Build a path (possibly NULL) from source to dest. | |
void | ast_translator_deactivate (struct ast_translator *t) |
Deactivate a translator. | |
void | ast_translator_free_path (struct ast_trans_pvt *tr) |
Frees a translator path Frees the given translator path structure. | |
int | ast_unregister_translator (struct ast_translator *t) |
Unregister a translator Unregisters the given tranlator. |
Definition in file translate.h.
#define ast_register_translator | ( | t | ) | __ast_register_translator(t, ast_module_info->self) |
#define MAX_FORMAT 32 |
Definition at line 27 of file translate.h.
Referenced by __ast_register_translator(), ast_translator_best_choice(), and rebuild_matrix().
int __ast_register_translator | ( | struct ast_translator * | t, | |
struct ast_module * | mod | |||
) |
Register a translator This registers a codec translator with asterisk.
t | populated ast_translator structure | |
module | handle to the module that owns this translator |
Definition at line 649 of file translate.c.
References ast_translator::active, ast_cli_register_multiple(), AST_FORMAT_SLINEAR, ast_getformatname(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), ast_translator::buf_size, ast_translator::buffer_samples, calc_cost(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, ast_translator::frameout, LOG_WARNING, MAX_FORMAT, ast_translator::module, ast_translator::name, option_verbose, ast_translator::plc_samples, powerof(), rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.
00650 { 00651 static int added_cli = 0; 00652 struct ast_translator *u; 00653 00654 if (!mod) { 00655 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00656 return -1; 00657 } 00658 00659 if (!t->buf_size) { 00660 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00661 return -1; 00662 } 00663 00664 t->module = mod; 00665 00666 t->srcfmt = powerof(t->srcfmt); 00667 t->dstfmt = powerof(t->dstfmt); 00668 t->active = 1; 00669 00670 if (t->plc_samples) { 00671 if (t->buffer_samples < t->plc_samples) { 00672 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00673 t->plc_samples, t->buffer_samples); 00674 return -1; 00675 } 00676 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00677 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00678 t->plc_samples, t->dstfmt); 00679 } 00680 if (t->srcfmt >= MAX_FORMAT) { 00681 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00682 return -1; 00683 } 00684 00685 if (t->dstfmt >= MAX_FORMAT) { 00686 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00687 return -1; 00688 } 00689 00690 if (t->buf_size) { 00691 /* 00692 * Align buf_size properly, rounding up to the machine-specific 00693 * alignment for pointers. 00694 */ 00695 struct _test_align { void *a, *b; } p; 00696 int align = (char *)&p.b - (char *)&p.a; 00697 00698 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00699 } 00700 00701 if (t->frameout == NULL) 00702 t->frameout = default_frameout; 00703 00704 calc_cost(t, 1); 00705 00706 if (option_verbose > 1) { 00707 char tmp[80]; 00708 00709 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00710 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00711 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00712 } 00713 00714 if (!added_cli) { 00715 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00716 added_cli++; 00717 } 00718 00719 AST_LIST_LOCK(&translators); 00720 00721 /* find any existing translators that provide this same srcfmt/dstfmt, 00722 and put this one in order based on cost */ 00723 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00724 if ((u->srcfmt == t->srcfmt) && 00725 (u->dstfmt == t->dstfmt) && 00726 (u->cost > t->cost)) { 00727 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00728 t = NULL; 00729 } 00730 } 00731 AST_LIST_TRAVERSE_SAFE_END; 00732 00733 /* if no existing translator was found for this format combination, 00734 add it to the beginning of the list */ 00735 if (t) 00736 AST_LIST_INSERT_HEAD(&translators, t, list); 00737 00738 rebuild_matrix(0); 00739 00740 AST_LIST_UNLOCK(&translators); 00741 00742 return 0; 00743 }
struct ast_frame* ast_trans_frameout | ( | struct ast_trans_pvt * | pvt, | |
int | datalen, | |||
int | samples | |||
) | [read] |
generic frameout function
Definition at line 209 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, ast_translator::dstfmt, ast_trans_pvt::f, f, ast_frame::frametype, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_trans_pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.
00211 { 00212 struct ast_frame *f = &pvt->f; 00213 00214 if (samples) 00215 f->samples = samples; 00216 else { 00217 if (pvt->samples == 0) 00218 return NULL; 00219 f->samples = pvt->samples; 00220 pvt->samples = 0; 00221 } 00222 if (datalen) 00223 f->datalen = datalen; 00224 else { 00225 f->datalen = pvt->datalen; 00226 pvt->datalen = 0; 00227 } 00228 00229 f->frametype = AST_FRAME_VOICE; 00230 f->subclass = 1 << (pvt->t->dstfmt); 00231 f->mallocd = 0; 00232 f->offset = AST_FRIENDLY_OFFSET; 00233 f->src = pvt->t->name; 00234 f->data = pvt->outbuf; 00235 return f; 00236 }
struct ast_frame* ast_translate | ( | struct ast_trans_pvt * | path, | |
struct ast_frame * | f, | |||
int | consume | |||
) | [read] |
translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed
tr | translator structure to use for translation | |
f | frame to translate | |
consume | Whether or not to free the original frame |
Definition at line 295 of file translate.c.
References AST_FRAME_CNG, ast_frfree(), ast_tvadd(), ast_tvsub(), ast_frame::delivery, framein(), ast_frame::frametype, ast_frame::has_timing_info, ast_frame::len, len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, and ast_frame::ts.
00296 { 00297 struct ast_trans_pvt *p = path; 00298 struct ast_frame *out = f; 00299 struct timeval delivery; 00300 int has_timing_info; 00301 long ts; 00302 long len; 00303 int seqno; 00304 00305 has_timing_info = f->has_timing_info; 00306 ts = f->ts; 00307 len = f->len; 00308 seqno = f->seqno; 00309 00310 /* XXX hmmm... check this below */ 00311 if (!ast_tvzero(f->delivery)) { 00312 if (!ast_tvzero(path->nextin)) { 00313 /* Make sure this is in line with what we were expecting */ 00314 if (!ast_tveq(path->nextin, f->delivery)) { 00315 /* The time has changed between what we expected and this 00316 most recent time on the new packet. If we have a 00317 valid prediction adjust our output time appropriately */ 00318 if (!ast_tvzero(path->nextout)) { 00319 path->nextout = ast_tvadd(path->nextout, 00320 ast_tvsub(f->delivery, path->nextin)); 00321 } 00322 path->nextin = f->delivery; 00323 } 00324 } else { 00325 /* This is our first pass. Make sure the timing looks good */ 00326 path->nextin = f->delivery; 00327 path->nextout = f->delivery; 00328 } 00329 /* Predict next incoming sample */ 00330 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000)); 00331 } 00332 delivery = f->delivery; 00333 for ( ; out && p ; p = p->next) { 00334 framein(p, out); 00335 out = p->t->frameout(p); 00336 } 00337 if (consume) 00338 ast_frfree(f); 00339 if (out == NULL) 00340 return NULL; 00341 /* we have a frame, play with times */ 00342 if (!ast_tvzero(delivery)) { 00343 /* Regenerate prediction after a discontinuity */ 00344 if (ast_tvzero(path->nextout)) 00345 path->nextout = ast_tvnow(); 00346 00347 /* Use next predicted outgoing timestamp */ 00348 out->delivery = path->nextout; 00349 00350 /* Predict next outgoing timestamp from samples in this 00351 frame. */ 00352 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000)); 00353 } else { 00354 out->delivery = ast_tv(0, 0); 00355 out->has_timing_info = has_timing_info; 00356 if (has_timing_info) { 00357 out->ts = ts; 00358 out->len = len; 00359 out->seqno = seqno; 00360 } 00361 } 00362 /* Invalidate prediction if we're entering a silence period */ 00363 if (out->frametype == AST_FRAME_CNG) 00364 path->nextout = ast_tv(0, 0); 00365 return out; 00366 }
unsigned int ast_translate_available_formats | ( | unsigned int | dest, | |
unsigned int | src | |||
) |
Mask off unavailable formats from a format bitmask.
dest | possible destination formats | |
src | source formats |
Note that only a single audio format and a single video format can be present in 'src', or the function will produce unexpected results.
Definition at line 854 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_MAX_AUDIO, AST_FORMAT_MAX_VIDEO, AST_FORMAT_VIDEO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, powerof(), and tr_matrix.
00855 { 00856 unsigned int res = dest; 00857 unsigned int x; 00858 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00859 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00860 00861 /* if we don't have a source format, we just have to try all 00862 possible destination formats */ 00863 if (!src) 00864 return dest; 00865 00866 /* If we have a source audio format, get its format index */ 00867 if (src_audio) 00868 src_audio = powerof(src_audio); 00869 00870 /* If we have a source video format, get its format index */ 00871 if (src_video) 00872 src_video = powerof(src_video); 00873 00874 AST_LIST_LOCK(&translators); 00875 00876 /* For a given source audio format, traverse the list of 00877 known audio formats to determine whether there exists 00878 a translation path from the source format to the 00879 destination format. */ 00880 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00881 /* if this is not a desired format, nothing to do */ 00882 if (!dest & x) 00883 continue; 00884 00885 /* if the source is supplying this format, then 00886 we can leave it in the result */ 00887 if (src & x) 00888 continue; 00889 00890 /* if we don't have a translation path from the src 00891 to this format, remove it from the result */ 00892 if (!tr_matrix[src_audio][powerof(x)].step) { 00893 res &= ~x; 00894 continue; 00895 } 00896 00897 /* now check the opposite direction */ 00898 if (!tr_matrix[powerof(x)][src_audio].step) 00899 res &= ~x; 00900 } 00901 00902 /* For a given source video format, traverse the list of 00903 known video formats to determine whether there exists 00904 a translation path from the source format to the 00905 destination format. */ 00906 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00907 /* if this is not a desired format, nothing to do */ 00908 if (!dest & x) 00909 continue; 00910 00911 /* if the source is supplying this format, then 00912 we can leave it in the result */ 00913 if (src & x) 00914 continue; 00915 00916 /* if we don't have a translation path from the src 00917 to this format, remove it from the result */ 00918 if (!tr_matrix[src_video][powerof(x)].step) { 00919 res &= ~x; 00920 continue; 00921 } 00922 00923 /* now check the opposite direction */ 00924 if (!tr_matrix[powerof(x)][src_video].step) 00925 res &= ~x; 00926 } 00927 00928 AST_LIST_UNLOCK(&translators); 00929 00930 return res; 00931 }
unsigned int ast_translate_path_steps | ( | unsigned int | dest, | |
unsigned int | src | |||
) |
Returns the number of steps required to convert from 'src' to 'dest'.
dest | destination format | |
src | source format |
Definition at line 836 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix.
00837 { 00838 unsigned int res = -1; 00839 00840 /* convert bitwise format numbers into array indices */ 00841 src = powerof(src); 00842 dest = powerof(dest); 00843 00844 AST_LIST_LOCK(&translators); 00845 00846 if (tr_matrix[src][dest].step) 00847 res = tr_matrix[src][dest].multistep + 1; 00848 00849 AST_LIST_UNLOCK(&translators); 00850 00851 return res; 00852 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Definition at line 772 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00773 { 00774 AST_LIST_LOCK(&translators); 00775 t->active = 1; 00776 rebuild_matrix(0); 00777 AST_LIST_UNLOCK(&translators); 00778 }
int ast_translator_best_choice | ( | int * | dst, | |
int * | srcs | |||
) |
Chooses the best translation path.
Given a list of sources, and a designed destination format, which should I choose?
Definition at line 789 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_FORMAT, translator_path::multistep, and tr_matrix.
00790 { 00791 int x,y; 00792 int best = -1; 00793 int bestdst = 0; 00794 int cur, cursrc; 00795 int besttime = INT_MAX; 00796 int beststeps = INT_MAX; 00797 int common = (*dst) & (*srcs); /* are there common formats ? */ 00798 00799 if (common) { /* yes, pick one and return */ 00800 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00801 if (cur & common) /* guaranteed to find one */ 00802 break; 00803 } 00804 /* We are done, this is a common format to both. */ 00805 *srcs = *dst = cur; 00806 return 0; 00807 } else { /* No, we will need to translate */ 00808 AST_LIST_LOCK(&translators); 00809 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00810 if (! (cur & *dst)) 00811 continue; 00812 for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) { 00813 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00814 tr_matrix[x][y].cost > besttime) 00815 continue; /* not existing or no better */ 00816 if (tr_matrix[x][y].cost < besttime || 00817 tr_matrix[x][y].multistep < beststeps) { 00818 /* better than what we have so far */ 00819 best = cursrc; 00820 bestdst = cur; 00821 besttime = tr_matrix[x][y].cost; 00822 beststeps = tr_matrix[x][y].multistep; 00823 } 00824 } 00825 } 00826 AST_LIST_UNLOCK(&translators); 00827 if (best > -1) { 00828 *srcs = best; 00829 *dst = bestdst; 00830 best = 0; 00831 } 00832 return best; 00833 } 00834 }
struct ast_trans_pvt* ast_translator_build_path | ( | int | dest, | |
int | source | |||
) | [read] |
Builds a translator path Build a path (possibly NULL) from source to dest.
dest | destination format | |
source | source format |
Definition at line 255 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_translator_free_path(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, ast_trans_pvt::t, t, and tr_matrix.
00256 { 00257 struct ast_trans_pvt *head = NULL, *tail = NULL; 00258 00259 source = powerof(source); 00260 dest = powerof(dest); 00261 00262 AST_LIST_LOCK(&translators); 00263 00264 while (source != dest) { 00265 struct ast_trans_pvt *cur; 00266 struct ast_translator *t = tr_matrix[source][dest].step; 00267 if (!t) { 00268 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00269 ast_getformatname(source), ast_getformatname(dest)); 00270 AST_LIST_UNLOCK(&translators); 00271 return NULL; 00272 } 00273 if (!(cur = newpvt(t))) { 00274 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00275 if (head) 00276 ast_translator_free_path(head); 00277 AST_LIST_UNLOCK(&translators); 00278 return NULL; 00279 } 00280 if (!head) 00281 head = cur; 00282 else 00283 tail->next = cur; 00284 tail = cur; 00285 cur->nextin = cur->nextout = ast_tv(0, 0); 00286 /* Keep going if this isn't the final destination */ 00287 source = cur->t->dstfmt; 00288 } 00289 00290 AST_LIST_UNLOCK(&translators); 00291 return head; 00292 }
void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
t | translator to deactivate |
Definition at line 780 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00781 { 00782 AST_LIST_LOCK(&translators); 00783 t->active = 0; 00784 rebuild_matrix(0); 00785 AST_LIST_UNLOCK(&translators); 00786 }
void ast_translator_free_path | ( | struct ast_trans_pvt * | tr | ) |
Frees a translator path Frees the given translator path structure.
tr | translator path to get rid of |
Definition at line 245 of file translate.c.
References destroy(), and ast_trans_pvt::next.
00246 { 00247 struct ast_trans_pvt *pn = p; 00248 while ( (p = pn) ) { 00249 pn = p->next; 00250 destroy(p); 00251 } 00252 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
Unregister a translator Unregisters the given tranlator.
t | translator to unregister |
Definition at line 746 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::name, option_verbose, rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.
00747 { 00748 char tmp[80]; 00749 struct ast_translator *u; 00750 int found = 0; 00751 00752 AST_LIST_LOCK(&translators); 00753 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00754 if (u == t) { 00755 AST_LIST_REMOVE_CURRENT(&translators, list); 00756 if (option_verbose > 1) 00757 ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt)); 00758 found = 1; 00759 break; 00760 } 00761 } 00762 AST_LIST_TRAVERSE_SAFE_END; 00763 00764 if (found) 00765 rebuild_matrix(0); 00766 00767 AST_LIST_UNLOCK(&translators); 00768 00769 return (u ? 0 : -1); 00770 }