~davewalker/ubuntu/maverick/asterisk/lp_705014

« back to all changes in this revision

Viewing changes to translate.c

  • Committer: Bazaar Package Importer
  • Author(s): Kilian Krause
  • Date: 2005-03-09 22:09:05 UTC
  • mto: (1.2.1 upstream) (8.2.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20050309220905-9afy6hcpw96xbr6j
Tags: upstream-1.0.6
ImportĀ upstreamĀ versionĀ 1.0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <sys/time.h>
26
26
#include <unistd.h>
27
27
#include <stdlib.h>
28
 
#include <pthread.h>
29
28
#include <string.h>
30
29
#include <stdio.h>
31
30
 
 
31
#define MAX_RECALC 200 /* max sample recalc */
 
32
 
32
33
/* This could all be done more efficiently *IF* we chained packets together
33
34
   by default, but it would also complicate virtually every application. */
34
35
   
35
 
static ast_mutex_t list_lock = AST_MUTEX_INITIALIZER;
 
36
AST_MUTEX_DEFINE_STATIC(list_lock);
36
37
static struct ast_translator *list = NULL;
37
38
 
38
39
struct ast_translator_dir {
55
56
        struct ast_translator *step;
56
57
        struct ast_translator_pvt *state;
57
58
        struct ast_trans_pvt *next;
 
59
        struct timeval nextin;
 
60
        struct timeval nextout;
58
61
};
59
62
 
60
63
 
99
102
                                
100
103
                        if (tmp) {
101
104
                                tmp->next = NULL;
 
105
                                tmp->nextin.tv_sec = 0;
 
106
                                tmp->nextin.tv_usec = 0;
 
107
                                tmp->nextout.tv_sec = 0;
 
108
                                tmp->nextout.tv_usec = 0;
102
109
                                tmp->step = tr_matrix[source][dest].step;
103
 
                                tmp->state = tmp->step->new();
 
110
                                tmp->state = tmp->step->newpvt();
104
111
                                if (!tmp->state) {
105
112
                                        ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
106
113
                                        free(tmp);
131
138
{
132
139
        struct ast_trans_pvt *p;
133
140
        struct ast_frame *out;
 
141
        struct timeval delivery;
134
142
        p = path;
135
143
        /* Feed the first frame into the first translator */
136
144
        p->step->framein(p->state, f);
 
145
        if (f->delivery.tv_sec || f->delivery.tv_usec) {
 
146
                if (path->nextin.tv_sec || path->nextin.tv_usec) {
 
147
                        /* Make sure this is in line with what we were expecting */
 
148
                        if ((path->nextin.tv_sec != f->delivery.tv_sec) ||
 
149
                            (path->nextin.tv_usec != f->delivery.tv_usec)) {
 
150
                                /* The time has changed between what we expected and this
 
151
                                   most recent time on the new packet.  Adjust our output
 
152
                                   time appropriately */
 
153
                                long sdiff;
 
154
                                long udiff;
 
155
                                sdiff = f->delivery.tv_sec - path->nextin.tv_sec;
 
156
                                udiff = f->delivery.tv_usec - path->nextin.tv_usec;
 
157
                                path->nextin.tv_sec = f->delivery.tv_sec;
 
158
                                path->nextin.tv_usec = f->delivery.tv_usec;
 
159
                                path->nextout.tv_sec += sdiff;
 
160
                                path->nextout.tv_usec += udiff;
 
161
                                if (path->nextout.tv_usec < 0) {
 
162
                                        path->nextout.tv_usec += 1000000;
 
163
                                        path->nextout.tv_sec--;
 
164
                                } else if (path->nextout.tv_usec >= 1000000) {
 
165
                                        path->nextout.tv_usec -= 1000000;
 
166
                                        path->nextout.tv_sec++;
 
167
                                }
 
168
                        }
 
169
                } else {
 
170
                        /* This is our first pass.  Make sure the timing looks good */
 
171
                        path->nextin.tv_sec = f->delivery.tv_sec;
 
172
                        path->nextin.tv_usec = f->delivery.tv_usec;
 
173
                        path->nextout.tv_sec = f->delivery.tv_sec;
 
174
                        path->nextout.tv_usec = f->delivery.tv_usec;
 
175
                }
 
176
                /* Predict next incoming sample */
 
177
                path->nextin.tv_sec += (f->samples / 8000);
 
178
                path->nextin.tv_usec += ((f->samples % 8000) * 125);
 
179
                if (path->nextin.tv_usec >= 1000000) {
 
180
                        path->nextin.tv_usec -= 1000000;
 
181
                        path->nextin.tv_sec++;
 
182
                }
 
183
        }
 
184
        delivery.tv_sec = f->delivery.tv_sec;
 
185
        delivery.tv_usec = f->delivery.tv_usec;
137
186
        if (consume)
138
187
                ast_frfree(f);
139
188
        while(p) {
145
194
                   return this frame  */
146
195
                if (p->next) 
147
196
                        p->next->step->framein(p->next->state, out);
148
 
                else
 
197
                else {
 
198
                        if (delivery.tv_sec || delivery.tv_usec) {
 
199
                                /* Use next predicted outgoing timestamp */
 
200
                                out->delivery.tv_sec = path->nextout.tv_sec;
 
201
                                out->delivery.tv_usec = path->nextout.tv_usec;
 
202
                                
 
203
                                /* Predict next outgoing timestamp from samples in this
 
204
                                   frame. */
 
205
                                path->nextout.tv_sec += (out->samples / 8000);
 
206
                                path->nextout.tv_usec += ((out->samples % 8000) * 125);
 
207
                                if (path->nextout.tv_usec >= 1000000) {
 
208
                                        path->nextout.tv_sec++;
 
209
                                        path->nextout.tv_usec -= 1000000;
 
210
                                }
 
211
                        } else {
 
212
                                out->delivery.tv_sec = 0;
 
213
                                out->delivery.tv_usec = 0;
 
214
                        }
149
215
                        return out;
 
216
                }
150
217
                p = p->next;
151
218
        }
152
219
        ast_log(LOG_WARNING, "I should never get here...\n");
153
220
        return NULL;
154
221
}
155
222
 
156
 
static void rebuild_matrix(void)
 
223
 
 
224
static void calc_cost(struct ast_translator *t,int samples)
 
225
{
 
226
        int sofar=0;
 
227
        struct ast_translator_pvt *pvt;
 
228
        struct ast_frame *f, *out;
 
229
        struct timeval start, finish;
 
230
        int cost;
 
231
        if(!samples)
 
232
          samples = 1;
 
233
        
 
234
        /* If they don't make samples, give them a terrible score */
 
235
        if (!t->sample) {
 
236
                ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
 
237
                t->cost = 99999;
 
238
                return;
 
239
        }
 
240
        pvt = t->newpvt();
 
241
        if (!pvt) {
 
242
                ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
 
243
                t->cost = 99999;
 
244
                return;
 
245
        }
 
246
        gettimeofday(&start, NULL);
 
247
        /* Call the encoder until we've processed one second of time */
 
248
        while(sofar < samples * 8000) {
 
249
                f = t->sample();
 
250
                if (!f) {
 
251
                        ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
 
252
                        t->destroy(pvt);
 
253
                        t->cost = 99999;
 
254
                        return;
 
255
                }
 
256
                t->framein(pvt, f);
 
257
                ast_frfree(f);
 
258
                while((out = t->frameout(pvt))) {
 
259
                        sofar += out->samples;
 
260
                        ast_frfree(out);
 
261
                }
 
262
        }
 
263
        gettimeofday(&finish, NULL);
 
264
        t->destroy(pvt);
 
265
        cost = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000;
 
266
        t->cost = cost / samples;
 
267
        if (!t->cost)
 
268
                t->cost = 1;
 
269
}
 
270
 
 
271
static void rebuild_matrix(int samples)
157
272
{
158
273
        struct ast_translator *t;
159
274
        int changed;
164
279
        bzero(tr_matrix, sizeof(tr_matrix));
165
280
        t = list;
166
281
        while(t) {
 
282
          if(samples)
 
283
            calc_cost(t,samples);
 
284
          
167
285
                if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
168
286
                     tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
169
287
                        tr_matrix[t->srcfmt][t->dstfmt].step = t;
201
319
        } while (changed);
202
320
}
203
321
 
204
 
static void calc_cost(struct ast_translator *t)
205
 
{
206
 
        int sofar=0;
207
 
        struct ast_translator_pvt *pvt;
208
 
        struct ast_frame *f, *out;
209
 
        struct timeval start, finish;
210
 
        int cost;
211
 
        /* If they don't make samples, give them a terrible score */
212
 
        if (!t->sample) {
213
 
                ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
214
 
                t->cost = 99999;
215
 
                return;
216
 
        }
217
 
        pvt = t->new();
218
 
        if (!pvt) {
219
 
                ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
220
 
                t->cost = 99999;
221
 
                return;
222
 
        }
223
 
        gettimeofday(&start, NULL);
224
 
        /* Call the encoder until we've processed one second of time */
225
 
        while(sofar < 8000) {
226
 
                f = t->sample();
227
 
                if (!f) {
228
 
                        ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
229
 
                        t->destroy(pvt);
230
 
                        t->cost = 99999;
231
 
                        return;
232
 
                }
233
 
                t->framein(pvt, f);
234
 
                ast_frfree(f);
235
 
                while((out = t->frameout(pvt))) {
236
 
                        sofar += out->samples;
237
 
                        ast_frfree(out);
238
 
                }
239
 
        }
240
 
        gettimeofday(&finish, NULL);
241
 
        t->destroy(pvt);
242
 
        cost = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000;
243
 
        t->cost = cost;
244
 
        if (!t->cost)
245
 
                t->cost = 1;
246
 
}
 
322
 
 
323
 
 
324
 
247
325
 
248
326
static int show_translation(int fd, int argc, char *argv[])
249
327
{
250
328
#define SHOW_TRANS 11
251
 
        int x,y;
 
329
        int x, y, z;
252
330
        char line[80];
253
 
        if (argc != 2) 
 
331
        if (argc > 4) 
254
332
                return RESULT_SHOWUSAGE;
 
333
 
 
334
        if (argv[2] && !strcasecmp(argv[2],"recalc")) {
 
335
                z = argv[3] ? atoi(argv[3]) : 1;
 
336
 
 
337
                if (z <= 0) {
 
338
                        ast_cli(fd,"         C'mon let's be serious here... defaulting to 1.\n");
 
339
                        z = 1;
 
340
                }
 
341
 
 
342
                if (z > MAX_RECALC) {
 
343
                        ast_cli(fd,"         Maximum limit of recalc exceeded by %d, truncating value to %d\n",z-MAX_RECALC,MAX_RECALC);
 
344
                        z = MAX_RECALC;
 
345
                }
 
346
                ast_cli(fd,"         Recalculating Codec Translation (number of sample seconds: %d)\n\n",z);
 
347
                rebuild_matrix(z);
 
348
        }
 
349
 
255
350
        ast_cli(fd, "         Translation times between formats (in milliseconds)\n");
256
351
        ast_cli(fd, "          Source Format (Rows) Destination Format(Columns)\n\n");
257
352
        ast_mutex_lock(&list_lock);
258
353
        for (x=-1;x<SHOW_TRANS; x++) {
259
 
                strcpy(line, " ");
 
354
                /* next 2 lines run faster than using strcpy() */
 
355
                line[0] = ' ';
 
356
                line[1] = '\0';
260
357
                for (y=-1;y<SHOW_TRANS;y++) {
261
358
                        if (x >= 0 && y >= 0 && tr_matrix[x][y].step)
262
359
                                snprintf(line + strlen(line), sizeof(line) - strlen(line), " %5d", tr_matrix[x][y].cost >= 99999 ? tr_matrix[x][y].cost-99999 : tr_matrix[x][y].cost);
264
361
                                if (((x == -1 && y >= 0) || (y == -1 && x >= 0))) {
265
362
                                        snprintf(line + strlen(line), sizeof(line) - strlen(line), 
266
363
                                                " %5s", ast_getformatname(1<<(x+y+1)) );
267
 
                                } else if (x != -1 && y != -1 ) {
 
364
                                } else if (x != -1 && y != -1) {
268
365
                                        snprintf(line + strlen(line), sizeof(line) - strlen(line), "     -");
269
366
                                } else {
270
367
                                        snprintf(line + strlen(line), sizeof(line) - strlen(line), "      ");
280
377
static int added_cli = 0;
281
378
 
282
379
static char show_trans_usage[] =
283
 
"Usage: show translation\n"
 
380
"Usage: show translation [recalc] [<recalc seconds>]\n"
284
381
"       Displays known codec translators and the cost associated\n"
285
 
"with each conversion.\n";
 
382
"with each conversion.  if the arguement 'recalc' is supplied along\n"
 
383
"with optional number of seconds to test a new test will be performed\n"
 
384
"as the chart is being displayed.\n";
286
385
 
287
386
static struct ast_cli_entry show_trans =
288
387
{ { "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage };
296
395
                ast_log(LOG_WARNING, "Format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
297
396
                return -1;
298
397
        }
299
 
        calc_cost(t);
 
398
        calc_cost(t,1);
300
399
        if (option_verbose > 1)
301
400
                ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
302
401
        ast_mutex_lock(&list_lock);
306
405
        }
307
406
        t->next = list;
308
407
        list = t;
309
 
        rebuild_matrix();
 
408
        rebuild_matrix(0);
310
409
        ast_mutex_unlock(&list_lock);
311
410
        return 0;
312
411
}
313
412
 
314
413
int ast_unregister_translator(struct ast_translator *t)
315
414
{
 
415
        char tmp[80];
316
416
        struct ast_translator *u, *ul = NULL;
317
417
        ast_mutex_lock(&list_lock);
318
418
        u = list;
322
422
                                ul->next = u->next;
323
423
                        else
324
424
                                list = u->next;
 
425
                        if (option_verbose > 1)
 
426
                                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));
325
427
                        break;
326
428
                }
327
429
                ul = u;
328
430
                u = u->next;
329
431
        }
330
 
        rebuild_matrix();
 
432
        rebuild_matrix(0);
331
433
        ast_mutex_unlock(&list_lock);
332
434
        return (u ? 0 : -1);
333
435
}