It is possible for framein to get called and no channel be available, so do a check...
[asterisk/asterisk.git] / codecs / codec_zap.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Zaptel native transcoding support
5  *
6  * Copyright (C) 1999 - 2006, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  * Kevin P. Fleming <kpfleming@digium.com>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21
22 /*! \file
23  *
24  * \brief Translate between various formats natively through Zaptel transcoding
25  *
26  * \ingroup codecs
27  */
28
29 /*** MODULEINFO
30         <depend>zaptel_transcode</depend>
31         <depend>zaptel</depend>
32  ***/
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include <fcntl.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <netinet/in.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <sys/ioctl.h>
45 #include <errno.h>
46 #include <sys/mman.h>
47 #include <zaptel/zaptel.h>
48
49 #include "asterisk/lock.h"
50 #include "asterisk/translate.h"
51 #include "asterisk/config.h"
52 #include "asterisk/options.h"
53 #include "asterisk/module.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/channel.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/linkedlists.h"
59
60 #define BUFFER_SAMPLES  8000
61
62 static unsigned int global_useplc = 0;
63 static int cardsmode = 0;
64
65 static int totalchannels = 0;
66 static int complexinuse = 0;
67 static int simpleinuse = 0;
68 AST_MUTEX_DEFINE_STATIC(channelcount);
69
70
71 static const char show_transcoder_usage[] =
72 "Usage: show transcoder\n"
73 "       Displays transcoder utilization.\n";
74
75 static int show_transcoder(int fd, int argc, char *argv[]);
76
77 static struct ast_cli_entry transcoder_cli[] = {
78         { { "show", "transcoder", NULL},
79         show_transcoder, "Displays transcoder utilization.",
80         show_transcoder_usage }
81 };
82
83 struct format_map {
84         unsigned int map[32][32];
85 };
86
87 static struct format_map global_format_map = { { { 0 } } };
88
89 struct translator {
90         struct ast_translator t;
91         AST_LIST_ENTRY(translator) entry;
92 };
93
94 static AST_LIST_HEAD_STATIC(zap_translators, translator);
95
96 struct pvt {
97         int fd;
98         int fake;
99         int inuse;
100 #ifdef DEBUG_TRANSCODE
101         int totalms;
102         int lasttotalms;
103 #endif
104         struct zt_transcode_header *hdr;
105         struct ast_frame f;
106 };
107
108 static void activate_translator(int simple);
109 static void deactivate_translator(int simple);
110
111
112 static int show_transcoder(int fd, int argc, char *argv[])
113 {
114         ast_mutex_lock(&channelcount);
115         if (!totalchannels) { 
116                 ast_cli(fd, "No transcoder card registered\n");
117                 ast_mutex_unlock(&channelcount);
118                 return RESULT_SUCCESS;
119         }
120         if(!cardsmode)             
121                 ast_cli(fd, "%d/%d encoders/decoders of %d channels (G.729a / G.723.1 5.3 kbps) are in use.\n",complexinuse, simpleinuse, totalchannels);
122         else if (cardsmode == 1)
123                 ast_cli(fd, "%d/%d encoders/decoders of %d channels (G.729a) are in use.\n",complexinuse, simpleinuse, totalchannels);
124         else if (cardsmode == 2)
125                 ast_cli(fd, "%d/%d encoders/decoders of %d channels (G.723.1 5.3 kbps) are in use.\n",complexinuse, simpleinuse, totalchannels);
126
127         ast_mutex_unlock(&channelcount);
128         return RESULT_SUCCESS;
129 }
130
131 static int zap_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
132 {
133         struct pvt *ztp = pvt->pvt;
134         struct zt_transcode_header *hdr = ztp->hdr;
135
136         if (!f->subclass) {
137                 /* Fake a return frame for calculation purposes */
138                 ztp->fake = 2;
139                 pvt->samples = f->samples;
140                 return 0;
141         }
142         if(!ztp->inuse) {
143                 ast_mutex_lock(&channelcount);
144                 if(pvt->t->dstfmt == 8 || pvt->t->dstfmt == 0 ) {
145                         if (complexinuse == totalchannels) {
146                                 ast_mutex_unlock(&channelcount);
147                                 return -1;
148                         }
149                         complexinuse++;
150                         if(complexinuse == totalchannels)
151                                 deactivate_translator(0);
152                 } else {
153                         if (simpleinuse == totalchannels) {
154                                 ast_mutex_unlock(&channelcount);
155                                 return -1;
156                         }
157                         simpleinuse++;
158                         if(simpleinuse == totalchannels)
159                                 deactivate_translator(1);
160                 }
161                 ast_mutex_unlock(&channelcount);
162                 ztp->inuse = 1;
163         }
164         if (!hdr->srclen)
165                 /* Copy at front of buffer */
166                 hdr->srcoffset = 0;
167
168         if (hdr->srclen + f->datalen > sizeof(hdr->srcdata)) {
169                 ast_log(LOG_WARNING, "Out of space for codec translation!\n");
170                 return -1;
171         }
172
173         if (hdr->srclen + f->datalen + hdr->srcoffset > sizeof(hdr->srcdata)) {
174                 /* Very unlikely */
175                 memmove(hdr->srcdata, hdr->srcdata + hdr->srcoffset, hdr->srclen);
176                 hdr->srcoffset = 0;
177         }
178
179         memcpy(hdr->srcdata + hdr->srcoffset + hdr->srclen, f->data, f->datalen);
180         hdr->srclen += f->datalen;
181         pvt->samples += f->samples;
182
183         return -1;
184 }
185
186 static struct ast_frame *zap_frameout(struct ast_trans_pvt *pvt)
187 {
188         struct pvt *ztp = pvt->pvt;
189         struct zt_transcode_header *hdr = ztp->hdr;
190         unsigned int x;
191
192         if (ztp->fake == 2) {
193                 ztp->fake = 1;
194                 ztp->f.frametype = AST_FRAME_VOICE;
195                 ztp->f.subclass = 0;
196                 ztp->f.samples = 240;
197                 ztp->f.data = NULL;
198                 ztp->f.offset = 0;
199                 ztp->f.datalen = 0;
200                 ztp->f.mallocd = 0;
201                 pvt->samples = 0;
202         } else if (ztp->fake == 1) {
203                 return NULL;
204         } else {
205                 if (hdr->dstlen) {
206 #ifdef DEBUG_TRANSCODE
207                         ztp->totalms += hdr->dstsamples;
208                         if ((ztp->totalms - ztp->lasttotalms) > 8000) {
209                                 ast_verbose("Whee %p, %d (%d to %d)\n", ztp, hdr->dstlen, ztp->lasttotalms, ztp->totalms);
210                                 ztp->lasttotalms = ztp->totalms;
211                         }
212 #endif
213                         ztp->f.frametype = AST_FRAME_VOICE;
214                         ztp->f.subclass = hdr->dstfmt;
215                         ztp->f.samples = hdr->dstsamples;
216                         ztp->f.data = hdr->dstdata + hdr->dstoffset;
217                         ztp->f.offset = hdr->dstoffset;
218                         ztp->f.datalen = hdr->dstlen;
219                         ztp->f.mallocd = 0;
220                         pvt->samples -= ztp->f.samples;
221                         hdr->dstlen = 0;
222                         
223                 } else {
224                         if (hdr->srclen) {
225                                 hdr->dstoffset = AST_FRIENDLY_OFFSET;
226                                 x = ZT_TCOP_TRANSCODE;
227                                 if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
228                                         ast_log(LOG_WARNING, "Failed to transcode: %s\n", strerror(errno));
229                         }
230                         return NULL;
231                 }
232         }
233
234         return &ztp->f;
235 }
236
237 static void zap_destroy(struct ast_trans_pvt *pvt)
238 {
239         struct pvt *ztp = pvt->pvt;
240         unsigned int x;
241
242         x = ZT_TCOP_RELEASE;
243         if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
244                 ast_log(LOG_WARNING, "Failed to release transcoder channel: %s\n", strerror(errno));
245                                 
246         munmap(ztp->hdr, sizeof(*ztp->hdr));
247         if(ztp->inuse) {
248                 ast_mutex_lock(&channelcount);
249                 if(pvt->t->dstfmt == 8 || pvt->t->dstfmt == 0) {
250                         if(complexinuse == totalchannels)
251                                 activate_translator(0);
252                         complexinuse--;
253                 } else {
254                         if(simpleinuse == totalchannels)
255                                 activate_translator(1);
256                         simpleinuse--;
257                 }
258                 ast_mutex_unlock(&channelcount);
259         }
260         close(ztp->fd);
261 }
262
263 static int zap_translate(struct ast_trans_pvt *pvt, int dest, int source)
264 {
265         /* Request translation through zap if possible */
266         int fd;
267         unsigned int x = ZT_TCOP_RESET;
268         struct pvt *ztp = pvt->pvt;
269         struct zt_transcode_header *hdr;
270         int flags;
271         
272         if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
273                 return -1;
274         flags = fcntl(fd, F_GETFL);
275         if (flags > - 1) {
276                 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
277                         ast_log(LOG_WARNING, "Could not set non-block mode!\n");
278         }
279         
280
281         if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
282                 ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
283                 close(fd);
284
285                 return -1;
286         }
287
288         if (hdr->magic != ZT_TRANSCODE_MAGIC) {
289                 ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
290                 munmap(hdr, sizeof(*hdr));
291                 close(fd);
292
293                 return -1;
294         }
295         
296         hdr->srcfmt = (1 << source);
297         hdr->dstfmt = (1 << dest);
298         if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
299                 ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
300                 munmap(hdr, sizeof(*hdr));
301                 close(fd);
302
303                 return -1;
304         }
305
306         ztp = pvt->pvt;
307         ztp->fd = fd;
308         ztp->hdr = hdr;
309
310         return 0;
311 }
312
313 static int zap_new(struct ast_trans_pvt *pvt)
314 {
315         return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt);
316 }
317
318 static struct ast_frame *fakesrc_sample(void)
319 {
320         /* Don't bother really trying to test hardware ones. */
321         static struct ast_frame f = {
322                 .frametype = AST_FRAME_VOICE,
323                 .samples = 240,
324                 .src = __PRETTY_FUNCTION__
325         };
326
327         return &f;
328 }
329
330 static int register_translator(int dst, int src)
331 {
332         struct translator *zt;
333         int res;
334
335         if (!(zt = ast_calloc(1, sizeof(*zt))))
336                 return -1;
337         if (!((cardsmode  == 1 && (dst == 8 || src == 8)) || (cardsmode == 2 && (dst == 0 || src == 0)) || (cardsmode == 0)))
338                 return -1;
339         snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", 
340                  ast_getformatname((1 << src)), ast_getformatname((1 << dst)));
341         zt->t.srcfmt = (1 << src);
342         zt->t.dstfmt = (1 << dst);
343         zt->t.newpvt = zap_new;
344         zt->t.framein = zap_framein;
345         zt->t.frameout = zap_frameout;
346         zt->t.destroy = zap_destroy;
347         zt->t.sample = fakesrc_sample;
348         zt->t.useplc = global_useplc;
349         zt->t.buf_size = BUFFER_SAMPLES * 2;
350         zt->t.desc_size = sizeof(struct pvt);
351         if ((res = ast_register_translator(&zt->t))) {
352                 free(zt);
353                 return -1;
354         }
355
356         AST_LIST_LOCK(&zap_translators);
357         AST_LIST_INSERT_HEAD(&zap_translators, zt, entry);
358         AST_LIST_UNLOCK(&zap_translators);
359
360         global_format_map.map[dst][src] = 1;
361
362         return res;
363 }
364
365 static void drop_translator(int dst, int src)
366 {
367         struct translator *cur;
368
369         AST_LIST_LOCK(&zap_translators);
370         AST_LIST_TRAVERSE_SAFE_BEGIN(&zap_translators, cur, entry) {
371                 if (cur->t.srcfmt != src)
372                         continue;
373
374                 if (cur->t.dstfmt != dst)
375                         continue;
376
377                 AST_LIST_REMOVE_CURRENT(&zap_translators, entry);
378                 ast_unregister_translator(&cur->t);
379                 free(cur);
380                 global_format_map.map[dst][src] = 0;
381                 break;
382         }
383         AST_LIST_TRAVERSE_SAFE_END;
384         AST_LIST_UNLOCK(&zap_translators);
385 }
386
387 static void unregister_translators(void)
388 {
389         struct translator *cur;
390
391         AST_LIST_LOCK(&zap_translators);
392         while ((cur = AST_LIST_REMOVE_HEAD(&zap_translators, entry))) {
393                 ast_unregister_translator(&cur->t);
394                 free(cur);
395         }
396         AST_LIST_UNLOCK(&zap_translators);
397 }
398
399
400 static void activate_translator(int simple)
401 {
402         struct translator *cur;
403
404         AST_LIST_LOCK(&zap_translators);
405         AST_LIST_TRAVERSE_SAFE_BEGIN(&zap_translators, cur, entry) {
406                 if(!simple) {
407                         if (cur->t.dstfmt == 0 || cur->t.dstfmt == 8) {
408                                 ast_translator_activate(&cur->t);
409                         }
410                 } else {
411                         if(cur->t.dstfmt == 2 || cur->t.dstfmt == 3) {
412                                 ast_translator_activate(&cur->t);
413                         }
414                 }
415         }
416         AST_LIST_TRAVERSE_SAFE_END;
417         AST_LIST_UNLOCK(&zap_translators);
418 }
419
420
421 static void deactivate_translator(int simple)
422 {
423         struct translator *cur;
424
425         AST_LIST_LOCK(&zap_translators);
426         AST_LIST_TRAVERSE_SAFE_BEGIN(&zap_translators, cur, entry) {
427                 if(!simple) {
428                         if (cur->t.dstfmt == 0 || cur->t.dstfmt == 8) {
429                                 ast_translator_deactivate(&cur->t);
430                         }
431                 } else {
432                         if(cur->t.dstfmt == 2 || cur->t.dstfmt == 3) {
433                                 ast_translator_deactivate(&cur->t);
434                         }
435                 }
436         }
437         AST_LIST_TRAVERSE_SAFE_END;
438         AST_LIST_UNLOCK(&zap_translators);
439 }
440
441 static void parse_config(void)
442 {
443         struct ast_variable *var;
444         struct ast_config *cfg = ast_config_load("codecs.conf");
445         cardsmode = 0;
446
447         if (!cfg)
448                 return;
449
450         for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
451                if (!strcasecmp(var->name, "genericplc")) {
452                        global_useplc = ast_true(var->value);
453                        if (option_verbose > 2)
454                                ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n",
455                                            global_useplc ? "" : "not ");
456                }
457         }
458         for (var = ast_variable_browse(cfg, "transcoder_card"); var; var = var->next) {
459                 if (!strcasecmp(var->name, "mode")) {
460                         if(strstr(var->value, "g729"))
461                                 cardsmode = 1;
462                         else if(strstr(var->value, "g723"))
463                                 cardsmode = 2;
464                         else if(strstr(var->value, "mixed"))
465                                 cardsmode = 0;
466                 }
467         }
468
469         ast_config_destroy(cfg);
470 }
471
472 static int build_translators(struct format_map *map, unsigned int dstfmts, unsigned int srcfmts)
473 {
474         unsigned int src, dst;
475
476         for (src = 0; src < 32; src++) {
477                 for (dst = 0; dst < 32; dst++) {
478                         if (!(srcfmts & (1 << src)))
479                                 continue;
480
481                         if (!(dstfmts & (1 << dst)))
482                                 continue;
483
484                         if (global_format_map.map[dst][src])
485                                 continue;
486
487                         if (!register_translator(dst, src))
488                                 map->map[dst][src] = 1;
489                         else
490                                 return 0;
491                 }
492         }
493         return 1;
494 }
495
496 static int find_transcoders(void)
497 {
498         struct zt_transcode_info info = { 0, };
499         struct format_map map = { { { 0 } } };
500         int fd, res;
501         unsigned int x, y;
502
503         info.op = ZT_TCOP_GETINFO;
504         if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) {
505                 ast_log(LOG_NOTICE, "No Zaptel transcoder support!\n");
506                 return 0;
507         }
508         for (info.tcnum = 0; !(res = ioctl(fd, ZT_TRANSCODE_OP, &info)); info.tcnum++) {
509                 if (option_verbose > 1)
510                         ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name);
511
512                 if(build_translators(&map, info.dstfmts, info.srcfmts)) {
513                         ast_mutex_lock(&channelcount);
514                         totalchannels += info.numchannels;
515                         ast_mutex_unlock(&channelcount);
516                 }
517         }
518         close(fd);
519
520         if (!info.tcnum && (option_verbose > 1))
521                 ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n");
522
523         for (x = 0; x < 32; x++) {
524                 for (y = 0; y < 32; y++) {
525                         if (!map.map[x][y] && global_format_map.map[x][y])
526                                 drop_translator(x, y);
527                 }
528         }
529         ast_mutex_lock(&channelcount);
530         totalchannels = totalchannels/2;
531         ast_mutex_unlock(&channelcount);
532         return 0;
533 }
534
535 static int reload(void)
536 {
537         struct translator *cur;
538
539         parse_config();
540         find_transcoders();
541
542         AST_LIST_LOCK(&zap_translators);
543         AST_LIST_TRAVERSE(&zap_translators, cur, entry)
544                 cur->t.useplc = global_useplc;
545         AST_LIST_UNLOCK(&zap_translators);
546
547         return 0;
548 }
549
550 static int unload_module(void)
551 {
552         unregister_translators();
553         ast_cli_unregister_multiple(transcoder_cli, sizeof(transcoder_cli) / sizeof(struct ast_cli_entry));
554         return 0;
555 }
556
557 static int load_module(void)
558 {
559         ast_mutex_init(&channelcount);
560         parse_config();
561
562         find_transcoders();
563         ast_cli_register_multiple(transcoder_cli, sizeof(transcoder_cli) / sizeof(struct ast_cli_entry));
564         return 0;
565 }
566
567 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Generic Zaptel Transcoder Codec Translator",
568                 .load = load_module,
569                 .unload = unload_module,
570                 .reload = reload,
571                );