Asterisk - The Open Source Telephony Project GIT-master-f3e88d3
codec_dahdi.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * DAHDI native transcoding support
5 *
6 * Copyright (C) 1999 - 2008, 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 DAHDI transcoding
25 *
26 * \ingroup codecs
27 */
28
29/*** MODULEINFO
30 <depend>dahdi</depend>
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35#include <stdbool.h>
36
37#include <poll.h>
38#include <fcntl.h>
39#include <netinet/in.h>
40#include <sys/ioctl.h>
41#include <sys/mman.h>
42#include <dahdi/user.h>
43
44#include "asterisk/lock.h"
45#include "asterisk/translate.h"
46#include "asterisk/config.h"
47#include "asterisk/module.h"
48#include "asterisk/cli.h"
49#include "asterisk/channel.h"
50#include "asterisk/utils.h"
52#include "asterisk/ulaw.h"
54
55#define BUFFER_SIZE 8000
56
57#define G723_SAMPLES 240
58#define G729_SAMPLES 160
59#define ULAW_SAMPLES 160
60
61/* Defines from DAHDI. */
62#ifndef DAHDI_FORMAT_MAX_AUDIO
63/*! G.723.1 compression */
64#define DAHDI_FORMAT_G723_1 (1 << 0)
65/*! GSM compression */
66#define DAHDI_FORMAT_GSM (1 << 1)
67/*! Raw mu-law data (G.711) */
68#define DAHDI_FORMAT_ULAW (1 << 2)
69/*! Raw A-law data (G.711) */
70#define DAHDI_FORMAT_ALAW (1 << 3)
71/*! ADPCM (G.726, 32kbps) */
72#define DAHDI_FORMAT_G726 (1 << 4)
73/*! ADPCM (IMA) */
74#define DAHDI_FORMAT_ADPCM (1 << 5)
75/*! Raw 16-bit Signed Linear (8000 Hz) PCM */
76#define DAHDI_FORMAT_SLINEAR (1 << 6)
77/*! LPC10, 180 samples/frame */
78#define DAHDI_FORMAT_LPC10 (1 << 7)
79/*! G.729A audio */
80#define DAHDI_FORMAT_G729A (1 << 8)
81/*! SpeeX Free Compression */
82#define DAHDI_FORMAT_SPEEX (1 << 9)
83/*! iLBC Free Compression */
84#define DAHDI_FORMAT_ILBC (1 << 10)
85#endif
86
87static struct channel_usage {
88 int total;
92
93#if defined(NOT_NEEDED)
94/*!
95 * \internal
96 * \brief Convert DAHDI format bitfield to old Asterisk format bitfield.
97 * \since 13.0.0
98 *
99 * \param dahdi Bitfield from DAHDI to convert.
100 *
101 * \note They should be the same values but they don't have to be.
102 *
103 * \return Old Asterisk bitfield equivalent.
104 */
105static uint64_t bitfield_dahdi2ast(unsigned dahdi)
106{
107 uint64_t ast;
108
109 switch (dahdi) {
111 ast = AST_FORMAT_G723;
112 break;
113 case DAHDI_FORMAT_GSM:
114 ast = AST_FORMAT_GSM;
115 break;
117 ast = AST_FORMAT_ULAW;
118 break;
120 ast = AST_FORMAT_ALAW;
121 break;
124 break;
126 ast = AST_FORMAT_ADPCM;
127 break;
129 ast = AST_FORMAT_SLIN;
130 break;
132 ast = AST_FORMAT_LPC10;
133 break;
135 ast = AST_FORMAT_G729;
136 break;
138 ast = AST_FORMAT_SPEEX;
139 break;
141 ast = AST_FORMAT_ILBC;
142 break;
143 default:
144 ast = 0;
145 break;
146 }
147
148 return ast;
149}
150#endif /* defined(NOT_NEEDED) */
151
152/*!
153 * \internal
154 * \brief Get the ast_codec by DAHDI format.
155 * \since 13.0.0
156 *
157 * \param dahdi_fmt DAHDI specific codec identifier.
158 *
159 * \return Specified codec if exists otherwise NULL.
160 */
161static const struct ast_codec *get_dahdi_codec(uint32_t dahdi_fmt)
162{
163 const struct ast_codec *codec;
164
165 static const struct ast_codec dahdi_g723_1 = {
166 .name = "g723",
167 .type = AST_MEDIA_TYPE_AUDIO,
168 .sample_rate = 8000,
169 };
170 static const struct ast_codec dahdi_gsm = {
171 .name = "gsm",
172 .type = AST_MEDIA_TYPE_AUDIO,
173 .sample_rate = 8000,
174 };
175 static const struct ast_codec dahdi_ulaw = {
176 .name = "ulaw",
177 .type = AST_MEDIA_TYPE_AUDIO,
178 .sample_rate = 8000,
179 };
180 static const struct ast_codec dahdi_alaw = {
181 .name = "alaw",
182 .type = AST_MEDIA_TYPE_AUDIO,
183 .sample_rate = 8000,
184 };
185 static const struct ast_codec dahdi_g726 = {
186 .name = "g726",
187 .type = AST_MEDIA_TYPE_AUDIO,
188 .sample_rate = 8000,
189 };
190 static const struct ast_codec dahdi_adpcm = {
191 .name = "adpcm",
192 .type = AST_MEDIA_TYPE_AUDIO,
193 .sample_rate = 8000,
194 };
195 static const struct ast_codec dahdi_slinear = {
196 .name = "slin",
197 .type = AST_MEDIA_TYPE_AUDIO,
198 .sample_rate = 8000,
199 };
200 static const struct ast_codec dahdi_lpc10 = {
201 .name = "lpc10",
202 .type = AST_MEDIA_TYPE_AUDIO,
203 .sample_rate = 8000,
204 };
205 static const struct ast_codec dahdi_g729a = {
206 .name = "g729",
207 .type = AST_MEDIA_TYPE_AUDIO,
208 .sample_rate = 8000,
209 };
210 static const struct ast_codec dahdi_speex = {
211 .name = "speex",
212 .type = AST_MEDIA_TYPE_AUDIO,
213 .sample_rate = 8000,
214 };
215 static const struct ast_codec dahdi_ilbc = {
216 .name = "ilbc",
217 .type = AST_MEDIA_TYPE_AUDIO,
218 .sample_rate = 8000,
219 };
220
221 switch (dahdi_fmt) {
223 codec = &dahdi_g723_1;
224 break;
225 case DAHDI_FORMAT_GSM:
226 codec = &dahdi_gsm;
227 break;
229 codec = &dahdi_ulaw;
230 break;
232 codec = &dahdi_alaw;
233 break;
235 codec = &dahdi_g726;
236 break;
238 codec = &dahdi_adpcm;
239 break;
241 codec = &dahdi_slinear;
242 break;
244 codec = &dahdi_lpc10;
245 break;
247 codec = &dahdi_g729a;
248 break;
250 codec = &dahdi_speex;
251 break;
253 codec = &dahdi_ilbc;
254 break;
255 default:
256 codec = NULL;
257 break;
258 }
259
260 return codec;
261}
262
263static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
264
265static struct ast_cli_entry cli[] = {
266 AST_CLI_DEFINE(handle_cli_transcoder_show, "Display DAHDI transcoder utilization.")
267};
268
274};
275
276#ifndef container_of
277#define container_of(ptr, type, member) \
278 ((type *)((char *)(ptr) - offsetof(type, member)))
279#endif
280
282
284 int fd;
285 struct dahdi_transcoder_formats fmts;
286 unsigned int softslin:1;
287 unsigned int fake:2;
291 uint8_t ulaw_buffer[1024];
292};
293
294/* Only used by a decoder */
295static int ulawtolin(struct ast_trans_pvt *pvt, int samples)
296{
297 struct codec_dahdi_pvt *dahdip = pvt->pvt;
298 int i = samples;
299 uint8_t *src = &dahdip->ulaw_buffer[0];
300 int16_t *dst = pvt->outbuf.i16 + pvt->datalen;
301
302 /* convert and copy in outbuf */
303 while (i--) {
304 *dst++ = AST_MULAW(*src++);
305 }
306
307 return 0;
308}
309
310/* Only used by an encoder. */
311static int lintoulaw(struct ast_trans_pvt *pvt, struct ast_frame *f)
312{
313 struct codec_dahdi_pvt *dahdip = pvt->pvt;
314 int i = f->samples;
315 uint8_t *dst = &dahdip->ulaw_buffer[dahdip->samples_in_buffer];
316 int16_t *src = f->data.ptr;
317
318 if (dahdip->samples_in_buffer + i > sizeof(dahdip->ulaw_buffer)) {
319 ast_log(LOG_ERROR, "Out of buffer space!\n");
320 return -i;
321 }
322
323 while (i--) {
324 *dst++ = AST_LIN2MU(*src++);
325 }
326
327 dahdip->samples_in_buffer += f->samples;
328 return 0;
329}
330
331static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
332{
333 struct channel_usage copy;
334
335 switch (cmd) {
336 case CLI_INIT:
337 e->command = "transcoder show";
338 e->usage =
339 "Usage: transcoder show\n"
340 " Displays channel utilization of DAHDI transcoder(s).\n";
341 return NULL;
342 case CLI_GENERATE:
343 return NULL;
344 }
345
346 if (a->argc != 2)
347 return CLI_SHOWUSAGE;
348
349 copy = channels;
350
351 if (copy.total == 0)
352 ast_cli(a->fd, "No DAHDI transcoders found.\n");
353 else
354 ast_cli(a->fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total);
355
356 return CLI_SUCCESS;
357}
358
359static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
360{
361 int res;
362 if (!count) return;
363 res = write(dahdip->fd, buffer, count);
364 if (-1 == res) {
365 ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno));
366 }
367 if (count != res) {
368 ast_log(LOG_ERROR, "Requested write of %zd bytes, but only wrote %d bytes.\n", count, res);
369 }
370}
371
372static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
373{
374 struct codec_dahdi_pvt *dahdip = pvt->pvt;
375
376 if (!f->subclass.format) {
377 /* We're just faking a return for calculation purposes. */
378 dahdip->fake = 2;
379 pvt->samples = f->samples;
380 return 0;
381 }
382
383 /* Buffer up the packets and send them to the hardware if we
384 * have enough samples set up. */
385 if (dahdip->softslin) {
386 if (lintoulaw(pvt, f)) {
387 return -1;
388 }
389 } else {
390 /* NOTE: If softslin support is not needed, and the sample
391 * size is equal to the required sample size, we wouldn't
392 * need this copy operation. But at the time this was
393 * written, only softslin is supported. */
394 if (dahdip->samples_in_buffer + f->samples > sizeof(dahdip->ulaw_buffer)) {
395 ast_log(LOG_ERROR, "Out of buffer space.\n");
396 return -1;
397 }
398 memcpy(&dahdip->ulaw_buffer[dahdip->samples_in_buffer], f->data.ptr, f->samples);
399 dahdip->samples_in_buffer += f->samples;
400 }
401
402 while (dahdip->samples_in_buffer >= dahdip->required_samples) {
403 dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples);
405 dahdip->samples_in_buffer -= dahdip->required_samples;
406 if (dahdip->samples_in_buffer) {
407 /* Shift any remaining bytes down. */
408 memmove(dahdip->ulaw_buffer, &dahdip->ulaw_buffer[dahdip->required_samples],
409 dahdip->samples_in_buffer);
410 }
411 }
412 pvt->samples += f->samples;
413 pvt->datalen = 0;
414 return -1;
415}
416
417static void dahdi_wait_for_packet(int fd)
418{
419 struct pollfd p = {0};
420 p.fd = fd;
421 p.events = POLLIN;
422 poll(&p, 1, 10);
423}
424
426{
427 struct codec_dahdi_pvt *dahdip = pvt->pvt;
428 int res;
429
430 if (2 == dahdip->fake) {
431 struct ast_frame frm = {
433 .samples = dahdip->required_samples,
434 .src = pvt->t->name,
435 };
436
437 dahdip->fake = 1;
438 pvt->samples = 0;
439
440 return ast_frisolate(&frm);
441 } else if (1 == dahdip->fake) {
442 dahdip->fake = 0;
443 return NULL;
444 }
445
446 if (dahdip->samples_written_to_hardware >= dahdip->required_samples) {
447 dahdi_wait_for_packet(dahdip->fd);
448 }
449
450 res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
451 if (-1 == res) {
452 if (EWOULDBLOCK == errno) {
453 /* Nothing waiting... */
454 return NULL;
455 } else {
456 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
457 return NULL;
458 }
459 } else {
460 pvt->f.datalen = res;
461 pvt->f.samples = ast_codec_samples_count(&pvt->f);
462
464 (dahdip->samples_written_to_hardware >= pvt->f.samples) ?
465 dahdip->samples_written_to_hardware - pvt->f.samples : 0;
466
467 pvt->samples = 0;
468 pvt->datalen = 0;
469 return ast_frisolate(&pvt->f);
470 }
471
472 /* Shouldn't get here... */
473 return NULL;
474}
475
476static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
477{
478 struct codec_dahdi_pvt *dahdip = pvt->pvt;
479
480 if (!f->subclass.format) {
481 /* We're just faking a return for calculation purposes. */
482 dahdip->fake = 2;
483 pvt->samples = f->samples;
484 return 0;
485 }
486
487 if (!f->datalen) {
488 if (f->samples != dahdip->required_samples) {
489 ast_log(LOG_ERROR, "%d != %d %d\n", f->samples, dahdip->required_samples, f->datalen);
490 }
491 }
492 dahdi_write_frame(dahdip, f->data.ptr, f->datalen);
494 pvt->samples += f->samples;
495 pvt->datalen = 0;
496 return -1;
497}
498
500{
501 int res;
502 struct codec_dahdi_pvt *dahdip = pvt->pvt;
503
504 if (2 == dahdip->fake) {
505 struct ast_frame frm = {
507 .samples = dahdip->required_samples,
508 .src = pvt->t->name,
509 };
510
511 dahdip->fake = 1;
512 pvt->samples = 0;
513
514 return ast_frisolate(&frm);
515 } else if (1 == dahdip->fake) {
516 pvt->samples = 0;
517 dahdip->fake = 0;
518 return NULL;
519 }
520
522 dahdi_wait_for_packet(dahdip->fd);
523 }
524
525 /* Let's check to see if there is a new frame for us.... */
526 if (dahdip->softslin) {
527 res = read(dahdip->fd, dahdip->ulaw_buffer, sizeof(dahdip->ulaw_buffer));
528 } else {
529 res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
530 }
531
532 if (-1 == res) {
533 if (EWOULDBLOCK == errno) {
534 /* Nothing waiting... */
535 return NULL;
536 } else {
537 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
538 return NULL;
539 }
540 } else {
541 if (dahdip->softslin) {
542 ulawtolin(pvt, res);
543 pvt->f.datalen = res * 2;
544 } else {
545 pvt->f.datalen = res;
546 }
547 pvt->datalen = 0;
548 pvt->f.samples = res;
549 pvt->samples = 0;
551 (dahdip->samples_written_to_hardware >= res) ?
552 dahdip->samples_written_to_hardware - res : 0;
553
554 return ast_frisolate(&pvt->f);
555 }
556
557 /* Shouldn't get here... */
558 return NULL;
559}
560
561
562static void dahdi_destroy(struct ast_trans_pvt *pvt)
563{
564 struct codec_dahdi_pvt *dahdip = pvt->pvt;
565
566 switch (dahdip->fmts.dstfmt) {
570 break;
571 default:
573 break;
574 }
575
576 close(dahdip->fd);
577}
578
579static struct ast_format *dahdi_format_to_cached(int format)
580{
581 switch (format) {
583 return ast_format_g723;
584 case DAHDI_FORMAT_GSM:
585 return ast_format_gsm;
587 return ast_format_ulaw;
589 return ast_format_alaw;
591 return ast_format_g726;
593 return ast_format_adpcm;
595 return ast_format_slin;
597 return ast_format_lpc10;
599 return ast_format_g729;
601 return ast_format_speex;
603 return ast_format_ilbc;
604 }
605
606 /* This will never be reached */
607 ast_assert(0);
608 return NULL;
609}
610
611static int dahdi_translate(struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
612{
613 /* Request translation through zap if possible */
614 int fd;
615 struct codec_dahdi_pvt *dahdip = pvt->pvt;
616 int tried_once = 0;
617 const char *dev_filename = "/dev/dahdi/transcode";
618
619 if ((fd = open(dev_filename, O_RDWR)) < 0) {
620 ast_log(LOG_ERROR, "Failed to open %s: %s\n", dev_filename, strerror(errno));
621 return -1;
622 }
623
624 dahdip->fmts.srcfmt = src_dahdi_fmt;
625 dahdip->fmts.dstfmt = dst_dahdi_fmt;
626
628 pvt->f.subclass.format = ao2_bump(dahdi_format_to_cached(dahdip->fmts.dstfmt));
629
630 ast_debug(1, "Opening transcoder channel from %s to %s.\n", pvt->t->src_codec.name, pvt->t->dst_codec.name);
631
632retry:
633 if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) {
634 if ((ENODEV == errno) && !tried_once) {
635 /* We requested to translate to/from an unsupported
636 * format. Most likely this is because signed linear
637 * was not supported by any hardware devices even
638 * though this module always registers signed linear
639 * support. In this case we'll retry, requesting
640 * support for ULAW instead of signed linear and then
641 * we'll just convert from ulaw to signed linear in
642 * software. */
643 if (dahdip->fmts.srcfmt == DAHDI_FORMAT_SLINEAR) {
644 ast_debug(1, "Using soft_slin support on source\n");
645 dahdip->softslin = 1;
646 dahdip->fmts.srcfmt = DAHDI_FORMAT_ULAW;
647 } else if (dahdip->fmts.dstfmt == DAHDI_FORMAT_SLINEAR) {
648 ast_debug(1, "Using soft_slin support on destination\n");
649 dahdip->softslin = 1;
650 dahdip->fmts.dstfmt = DAHDI_FORMAT_ULAW;
651 }
652 tried_once = 1;
653 goto retry;
654 }
655 ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno));
656 close(fd);
657
658 return -1;
659 }
660
661 ast_fd_set_flags(fd, O_NONBLOCK);
662
663 dahdip->fd = fd;
664
665 dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (DAHDI_FORMAT_G723_1)) ? G723_SAMPLES : G729_SAMPLES;
666
667 switch (dahdip->fmts.dstfmt) {
670 break;
673 break;
674 default:
676 break;
677 }
678
679 return 0;
680}
681
682static int dahdi_new(struct ast_trans_pvt *pvt)
683{
684 struct translator *zt = container_of(pvt->t, struct translator, t);
685
686 return dahdi_translate(pvt, zt->dst_dahdi_fmt, zt->src_dahdi_fmt);
687}
688
689static struct ast_frame *fakesrc_sample(void)
690{
691 /* Don't bother really trying to test hardware ones. */
692 static struct ast_frame f = {
694 .samples = 160,
695 .src = __PRETTY_FUNCTION__
696 };
697
698 return &f;
699}
700
701static bool is_encoder(uint32_t src_dahdi_fmt)
702{
703 return ((src_dahdi_fmt & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW | DAHDI_FORMAT_SLINEAR)) > 0);
704}
705
706/* Must be called with the translators list locked. */
707static int register_translator(uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
708{
709 const struct ast_codec *dst_codec;
710 const struct ast_codec *src_codec;
711 struct translator *zt;
712 int res;
713
714 dst_codec = get_dahdi_codec(dst_dahdi_fmt);
715 src_codec = get_dahdi_codec(src_dahdi_fmt);
716 if (!dst_codec || !src_codec) {
717 return -1;
718 }
719
720 if (!(zt = ast_calloc(1, sizeof(*zt)))) {
721 return -1;
722 }
723
726
727 snprintf(zt->t.name, sizeof(zt->t.name), "dahdi_%s_to_%s",
728 src_codec->name, dst_codec->name);
729
730 memcpy(&zt->t.src_codec, src_codec, sizeof(*src_codec));
731 memcpy(&zt->t.dst_codec, dst_codec, sizeof(*dst_codec));
732 zt->t.buf_size = BUFFER_SIZE;
736 } else {
739 }
740 zt->t.destroy = dahdi_destroy;
741 zt->t.buffer_samples = 0;
742 zt->t.newpvt = dahdi_new;
743 zt->t.sample = fakesrc_sample;
744 zt->t.native_plc = 0;
745
746 zt->t.desc_size = sizeof(struct codec_dahdi_pvt);
747 if ((res = ast_register_translator(&zt->t))) {
748 ast_free(zt);
749 return -1;
750 }
751
753
754 return res;
755}
756
757static void unregister_translators(void)
758{
759 struct translator *cur;
760
762 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) {
764 ast_free(cur);
765 }
767}
768
769/* Must be called with the translators list locked. */
770static bool is_already_registered(uint32_t dstfmt, uint32_t srcfmt)
771{
772 bool res = false;
773 const struct translator *zt;
774
776 if ((zt->src_dahdi_fmt == srcfmt) && (zt->dst_dahdi_fmt == dstfmt)) {
777 res = true;
778 break;
779 }
780 }
781
782 return res;
783}
784
785static void build_translators(uint32_t dstfmts, uint32_t srcfmts)
786{
787 uint32_t srcfmt;
788 uint32_t dstfmt;
789
791
792 for (srcfmt = 1; srcfmt != 0; srcfmt <<= 1) {
793 for (dstfmt = 1; dstfmt != 0; dstfmt <<= 1) {
794 if (!(dstfmts & dstfmt) || !(srcfmts & srcfmt)) {
795 continue;
796 }
797 if (is_already_registered(dstfmt, srcfmt)) {
798 continue;
799 }
800 register_translator(dstfmt, srcfmt);
801 }
802 }
803
805}
806
807static int find_transcoders(void)
808{
809 struct dahdi_transcoder_info info = { 0, };
810 int fd;
811
812 if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) {
813 ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno));
814 return 0;
815 }
816
817 for (info.tcnum = 0; !ioctl(fd, DAHDI_TC_GETINFO, &info); info.tcnum++) {
818 ast_verb(2, "Found transcoder '%s'.\n", info.name);
819
820 /* Complex codecs need to support signed linear. If the
821 * hardware transcoder does not natively support signed linear
822 * format, we will emulate it in software directly in this
823 * module. Also, do not allow direct ulaw/alaw to complex
824 * codec translation, since that will prevent the generic PLC
825 * functions from working. */
826 if (info.dstfmts & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW)) {
827 info.dstfmts |= DAHDI_FORMAT_SLINEAR;
829 }
830 if (info.srcfmts & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW)) {
831 info.srcfmts |= DAHDI_FORMAT_SLINEAR;
833 }
834
835 build_translators(info.dstfmts, info.srcfmts);
836 ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2);
837 }
838
839 close(fd);
840
841 if (!info.tcnum) {
842 ast_verb(2, "No hardware transcoders found.\n");
843 }
844
845 return 0;
846}
847
848static int reload(void)
849{
851}
852
853static int unload_module(void)
854{
857
858 return 0;
859}
860
861static int load_module(void)
862{
866}
867
868AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Generic DAHDI Transcoder Codec Translator",
869 .support_level = AST_MODULE_SUPPORT_CORE,
870 .load = load_module,
871 .unload = unload_module,
872 .reload = reload,
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
General Asterisk PBX channel definitions.
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Definition: codec.c:379
static int dahdi_new(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:682
static int register_translator(uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
Definition: codec_dahdi.c:707
#define ULAW_SAMPLES
Definition: codec_dahdi.c:59
static struct ast_frame * dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:425
static struct channel_usage channels
static char * handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: codec_dahdi.c:331
static int lintoulaw(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_dahdi.c:311
#define DAHDI_FORMAT_GSM
Definition: codec_dahdi.c:66
#define DAHDI_FORMAT_SPEEX
Definition: codec_dahdi.c:82
#define DAHDI_FORMAT_SLINEAR
Definition: codec_dahdi.c:76
static struct ast_frame * dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:499
static int ulawtolin(struct ast_trans_pvt *pvt, int samples)
Definition: codec_dahdi.c:295
static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_dahdi.c:476
#define BUFFER_SIZE
Definition: codec_dahdi.c:55
static bool is_encoder(uint32_t src_dahdi_fmt)
Definition: codec_dahdi.c:701
#define DAHDI_FORMAT_ULAW
Definition: codec_dahdi.c:68
#define G723_SAMPLES
Definition: codec_dahdi.c:57
static bool is_already_registered(uint32_t dstfmt, uint32_t srcfmt)
Definition: codec_dahdi.c:770
static void build_translators(uint32_t dstfmts, uint32_t srcfmts)
Definition: codec_dahdi.c:785
#define DAHDI_FORMAT_ADPCM
Definition: codec_dahdi.c:74
#define DAHDI_FORMAT_G729A
Definition: codec_dahdi.c:80
#define DAHDI_FORMAT_LPC10
Definition: codec_dahdi.c:78
static const struct ast_codec * get_dahdi_codec(uint32_t dahdi_fmt)
Definition: codec_dahdi.c:161
static void dahdi_wait_for_packet(int fd)
Definition: codec_dahdi.c:417
static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
Definition: codec_dahdi.c:359
static struct ast_cli_entry cli[]
Definition: codec_dahdi.c:265
static int load_module(void)
Definition: codec_dahdi.c:861
#define DAHDI_FORMAT_ILBC
Definition: codec_dahdi.c:84
#define DAHDI_FORMAT_G723_1
Definition: codec_dahdi.c:64
static int unload_module(void)
Definition: codec_dahdi.c:853
static int reload(void)
Definition: codec_dahdi.c:848
static struct ast_frame * fakesrc_sample(void)
Definition: codec_dahdi.c:689
static void dahdi_destroy(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:562
static int find_transcoders(void)
Definition: codec_dahdi.c:807
#define DAHDI_FORMAT_ALAW
Definition: codec_dahdi.c:70
#define DAHDI_FORMAT_G726
Definition: codec_dahdi.c:72
#define G729_SAMPLES
Definition: codec_dahdi.c:58
static void unregister_translators(void)
Definition: codec_dahdi.c:757
static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_dahdi.c:372
static struct ast_format * dahdi_format_to_cached(int format)
Definition: codec_dahdi.c:579
#define container_of(ptr, type, member)
Definition: codec_dahdi.c:277
static int dahdi_translate(struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
Definition: codec_dahdi.c:611
short int16_t
Definition: db.h:59
struct ast_format * ast_format_adpcm
Built-in cached adpcm format.
Definition: format_cache.c:101
struct ast_format * ast_format_gsm
Built-in cached gsm format.
Definition: format_cache.c:96
struct ast_format * ast_format_speex
Built-in cached speex format.
Definition: format_cache.c:131
struct ast_format * ast_format_ilbc
Built-in cached ilbc format.
Definition: format_cache.c:121
struct ast_format * ast_format_g726
Built-in cached g726 format.
Definition: format_cache.c:111
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_lpc10
Built-in cached ilbc format.
Definition: format_cache.c:126
struct ast_format * ast_format_g723
Built-in cached g723.1 format.
Definition: format_cache.c:146
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct ast_format * ast_format_g729
Built-in cached g729 format.
Definition: format_cache.c:151
Configuration File Parser.
Media Format Bitfield Compatibility API.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
@ AST_FRAME_VOICE
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:291
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Asterisk locking-related definitions:
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
int errno
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:329
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
#define NULL
Definition: resample.c:96
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
const char * name
Name for this codec.
Definition: codec.h:46
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
union ast_frame::@226 data
enum ast_frame_type frametype
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
struct ast_frame f
Definition: translate.h:215
void * pvt
Definition: translate.h:219
struct ast_translator * t
Definition: translate.h:214
int datalen
actual space used in outbuf
Definition: translate.h:218
union ast_trans_pvt::@287 outbuf
int16_t * i16
Definition: translate.h:223
Descriptor of a translator.
Definition: translate.h:137
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
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_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 dahdi_transcoder_formats fmts
Definition: codec_dahdi.c:285
unsigned int fake
Definition: codec_dahdi.c:287
uint8_t ulaw_buffer[1024]
Definition: codec_dahdi.c:291
unsigned int softslin
Definition: codec_dahdi.c:286
uint16_t required_samples
Definition: codec_dahdi.c:288
uint16_t samples_written_to_hardware
Definition: codec_dahdi.c:290
uint16_t samples_in_buffer
Definition: codec_dahdi.c:289
Definition: search.h:40
uint32_t dst_dahdi_fmt
Definition: codec_dahdi.c:272
uint32_t src_dahdi_fmt
Definition: codec_dahdi.c:271
struct ast_translator t
Definition: codec_dahdi.c:270
struct translator::@145 entry
the list of translators
Definition: codec_dahdi.c:281
static struct test_val a
Support for translation of data formats. translate.c.
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:258
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given translator.
Definition: translate.c:1350
u-Law to Signed linear conversion
#define AST_MULAW(a)
Definition: ulaw.h:85
#define AST_LIN2MU(a)
Definition: ulaw.h:49
Utility functions.
#define ast_assert(a)
Definition: utils.h:739
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1039
#define ARRAY_LEN(a)
Definition: utils.h:666