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