Asterisk - The Open Source Telephony Project  GIT-master-0190e70
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  <support_level>core</support_level>
31  <depend>dahdi</depend>
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"
51 #include "asterisk/linkedlists.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 
87 static struct channel_usage {
88  int total;
89  int encoders;
90  int decoders;
91 } channels;
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  */
105 static uint64_t bitfield_dahdi2ast(unsigned dahdi)
106 {
107  uint64_t ast;
108 
109  switch (dahdi) {
110  case DAHDI_FORMAT_G723_1:
111  ast = AST_FORMAT_G723;
112  break;
113  case DAHDI_FORMAT_GSM:
114  ast = AST_FORMAT_GSM;
115  break;
116  case DAHDI_FORMAT_ULAW:
117  ast = AST_FORMAT_ULAW;
118  break;
119  case DAHDI_FORMAT_ALAW:
120  ast = AST_FORMAT_ALAW;
121  break;
122  case DAHDI_FORMAT_G726:
123  ast = AST_FORMAT_G726_AAL2;
124  break;
125  case DAHDI_FORMAT_ADPCM:
126  ast = AST_FORMAT_ADPCM;
127  break;
129  ast = AST_FORMAT_SLIN;
130  break;
131  case DAHDI_FORMAT_LPC10:
132  ast = AST_FORMAT_LPC10;
133  break;
134  case DAHDI_FORMAT_G729A:
135  ast = AST_FORMAT_G729;
136  break;
137  case DAHDI_FORMAT_SPEEX:
138  ast = AST_FORMAT_SPEEX;
139  break;
140  case DAHDI_FORMAT_ILBC:
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  */
161 static 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) {
222  case DAHDI_FORMAT_G723_1:
223  codec = &dahdi_g723_1;
224  break;
225  case DAHDI_FORMAT_GSM:
226  codec = &dahdi_gsm;
227  break;
228  case DAHDI_FORMAT_ULAW:
229  codec = &dahdi_ulaw;
230  break;
231  case DAHDI_FORMAT_ALAW:
232  codec = &dahdi_alaw;
233  break;
234  case DAHDI_FORMAT_G726:
235  codec = &dahdi_g726;
236  break;
237  case DAHDI_FORMAT_ADPCM:
238  codec = &dahdi_adpcm;
239  break;
241  codec = &dahdi_slinear;
242  break;
243  case DAHDI_FORMAT_LPC10:
244  codec = &dahdi_lpc10;
245  break;
246  case DAHDI_FORMAT_G729A:
247  codec = &dahdi_g729a;
248  break;
249  case DAHDI_FORMAT_SPEEX:
250  codec = &dahdi_speex;
251  break;
252  case DAHDI_FORMAT_ILBC:
253  codec = &dahdi_ilbc;
254  break;
255  default:
256  codec = NULL;
257  break;
258  }
259 
260  return codec;
261 }
262 
263 static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
264 
265 static struct ast_cli_entry cli[] = {
266  AST_CLI_DEFINE(handle_cli_transcoder_show, "Display DAHDI transcoder utilization.")
267 };
268 
269 struct translator {
270  struct ast_translator t;
271  uint32_t src_dahdi_fmt;
272  uint32_t dst_dahdi_fmt;
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 */
295 static 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. */
311 static 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 
331 static 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 
359 static 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 
372 static 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 
417 static 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 
425 static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
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 
476 static 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);
493  dahdip->samples_written_to_hardware += f->samples;
494  pvt->samples += f->samples;
495  pvt->datalen = 0;
496  return -1;
497 }
498 
499 static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
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 
521  if (dahdip->samples_written_to_hardware >= ULAW_SAMPLES) {
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 
562 static void dahdi_destroy(struct ast_trans_pvt *pvt)
563 {
564  struct codec_dahdi_pvt *dahdip = pvt->pvt;
565 
566  switch (dahdip->fmts.dstfmt) {
567  case DAHDI_FORMAT_G729A:
568  case DAHDI_FORMAT_G723_1:
570  break;
571  default:
573  break;
574  }
575 
576  close(dahdip->fd);
577 }
578 
580 {
581  switch (format) {
582  case DAHDI_FORMAT_G723_1:
583  return ast_format_g723;
584  case DAHDI_FORMAT_GSM:
585  return ast_format_gsm;
586  case DAHDI_FORMAT_ULAW:
587  return ast_format_ulaw;
588  case DAHDI_FORMAT_ALAW:
589  return ast_format_alaw;
590  case DAHDI_FORMAT_G726:
591  return ast_format_g726;
592  case DAHDI_FORMAT_ADPCM:
593  return ast_format_adpcm;
595  return ast_format_slin;
596  case DAHDI_FORMAT_LPC10:
597  return ast_format_lpc10;
598  case DAHDI_FORMAT_G729A:
599  return ast_format_g729;
600  case DAHDI_FORMAT_SPEEX:
601  return ast_format_speex;
602  case DAHDI_FORMAT_ILBC:
603  return ast_format_ilbc;
604  }
605 
606  /* This will never be reached */
607  ast_assert(0);
608  return NULL;
609 }
610 
611 static 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 
627  ast_assert(pvt->f.subclass.format == NULL);
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 
632 retry:
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) {
668  case DAHDI_FORMAT_G729A:
670  break;
671  case DAHDI_FORMAT_G723_1:
673  break;
674  default:
676  break;
677  }
678 
679  return 0;
680 }
681 
682 static 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 
689 static 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 
701 static 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. */
707 static 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;
733  if (is_encoder(src_dahdi_fmt)) {
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 
757 static 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. */
770 static 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 
785 static 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 
807 static 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;
828  info.dstfmts &= ~(DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW);
829  }
830  if (info.srcfmts & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW)) {
831  info.srcfmts |= DAHDI_FORMAT_SLINEAR;
832  info.srcfmts &= ~(DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW);
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 
848 static int reload(void)
849 {
851 }
852 
853 static int unload_module(void)
854 {
857 
858  return 0;
859 }
860 
861 static int load_module(void)
862 {
866 }
867 
868 AST_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,
873 );
static const struct ast_codec * get_dahdi_codec(uint32_t dahdi_fmt)
Definition: codec_dahdi.c:161
struct dahdi_transcoder_formats fmts
Definition: codec_dahdi.c:285
int datalen
actual space used in outbuf
Definition: translate.h:218
struct ast_format * ast_format_g726
Built-in cached g726 format.
Definition: format_cache.c:116
static int register_translator(uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
Definition: codec_dahdi.c:707
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
struct ast_format * ast_format_g723
Built-in cached g723.1 format.
Definition: format_cache.c:151
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
Asterisk locking-related definitions:
const char * name
Name for this codec.
Definition: codec.h:46
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int dahdi_translate(struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
Definition: codec_dahdi.c:611
int(* newpvt)(struct ast_trans_pvt *)
Definition: translate.h:151
static struct ast_frame * dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:425
Descriptor of a translator.
Definition: translate.h:137
short int16_t
Definition: db.h:59
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
union ast_trans_pvt::@321 outbuf
uint8_t ulaw_buffer[1024]
Definition: codec_dahdi.c:291
Support for translation of data formats. translate.c.
struct ast_frame f
Definition: translate.h:215
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
union ast_frame::@257 data
static void build_translators(uint32_t dstfmts, uint32_t srcfmts)
Definition: codec_dahdi.c:785
#define DAHDI_FORMAT_G723_1
Definition: codec_dahdi.c:64
Definition: cli.h:152
Definition of a media format.
Definition: format.c:43
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void unregister_translators(void)
Definition: codec_dahdi.c:757
static struct ast_frame * fakesrc_sample(void)
Definition: codec_dahdi.c:689
#define ast_assert(a)
Definition: utils.h:650
static int dahdi_new(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:682
#define NULL
Definition: resample.c:96
void * pvt
Definition: translate.h:219
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define DAHDI_FORMAT_LPC10
Definition: codec_dahdi.c:78
uint32_t dst_dahdi_fmt
Definition: codec_dahdi.c:272
#define ast_verb(level,...)
Definition: logger.h:455
static int find_transcoders(void)
Definition: codec_dahdi.c:807
#define G729_SAMPLES
Definition: codec_dahdi.c:58
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:755
struct ast_frame_subclass subclass
int16_t * i16
Definition: translate.h:223
Utility functions.
struct ast_translator t
Definition: codec_dahdi.c:270
unsigned int softslin
Definition: codec_dahdi.c:286
static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
Definition: codec_dahdi.c:359
#define ao2_bump(obj)
Definition: astobj2.h:491
struct ast_format * ast_format_lpc10
Built-in cached ilbc format.
Definition: format_cache.c:131
uint16_t required_samples
Definition: codec_dahdi.c:288
static int load_module(void)
Definition: codec_dahdi.c:861
Configuration File Parser.
#define DAHDI_FORMAT_SPEEX
Definition: codec_dahdi.c:82
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:949
static void dahdi_wait_for_packet(int fd)
Definition: codec_dahdi.c:417
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
u-Law to Signed linear conversion
#define ULAW_SAMPLES
Definition: codec_dahdi.c:59
General Asterisk PBX channel definitions.
static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_dahdi.c:476
const int fd
Definition: cli.h:159
#define DAHDI_FORMAT_G729A
Definition: codec_dahdi.c:80
#define AST_MULAW(a)
Definition: ulaw.h:85
#define DAHDI_FORMAT_ULAW
Definition: codec_dahdi.c:68
#define BUFFER_SIZE
Definition: codec_dahdi.c:55
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:257
struct ast_format * ast_format_gsm
Built-in cached gsm format.
Definition: format_cache.c:101
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:1327
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Definition: codec.c:378
static struct ast_format * dahdi_format_to_cached(int format)
Definition: codec_dahdi.c:579
A set of macros to manage forward-linked lists.
static struct channel_usage channels
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define DAHDI_FORMAT_SLINEAR
Definition: codec_dahdi.c:76
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
Definition: translate.h:182
#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:290
static struct ast_cli_entry cli[]
Definition: codec_dahdi.c:265
void(* destroy)(struct ast_trans_pvt *pvt)
Definition: translate.h:166
the list of translators
Definition: codec_dahdi.c:281
struct ast_codec dst_codec
Definition: translate.h:140
#define LOG_ERROR
Definition: logger.h:285
static int unload_module(void)
Definition: codec_dahdi.c:853
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
Media Format Bitfield Compatibility API.
#define CLI_SHOWUSAGE
Definition: cli.h:45
struct ast_format * ast_format_speex
Built-in cached speex format.
Definition: format_cache.c:136
int errno
static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_dahdi.c:372
struct ast_codec src_codec
Definition: translate.h:139
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define container_of(ptr, type, member)
Definition: codec_dahdi.c:277
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define DAHDI_FORMAT_G726
Definition: codec_dahdi.c:72
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
struct ast_frame *(* sample)(void)
Definition: translate.h:170
#define G723_SAMPLES
Definition: codec_dahdi.c:57
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static bool is_encoder(uint32_t src_dahdi_fmt)
Definition: codec_dahdi.c:701
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define DAHDI_FORMAT_ALAW
Definition: codec_dahdi.c:70
uint16_t samples_in_buffer
Definition: codec_dahdi.c:289
static int ulawtolin(struct ast_trans_pvt *pvt, int samples)
Definition: codec_dahdi.c:295
static void dahdi_destroy(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:562
Standard Command Line Interface.
#define DAHDI_FORMAT_ADPCM
Definition: codec_dahdi.c:74
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct ast_frame *(* frameout)(struct ast_trans_pvt *pvt)
Definition: translate.h:158
Data structure associated with a single frame of data.
struct ast_format * ast_format_adpcm
Built-in cached adpcm format.
Definition: format_cache.c:106
#define DAHDI_FORMAT_ILBC
Definition: codec_dahdi.c:84
static int reload(void)
Definition: codec_dahdi.c:848
static struct ast_frame * dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
Definition: codec_dahdi.c:499
struct ast_translator * t
Definition: translate.h:214
Definition: search.h:40
enum ast_frame_type frametype
struct ast_format * ast_format_g729
Built-in cached g729 format.
Definition: format_cache.c:156
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static bool is_already_registered(uint32_t dstfmt, uint32_t srcfmt)
Definition: codec_dahdi.c:770
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static int lintoulaw(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_dahdi.c:311
static char * handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: codec_dahdi.c:331
#define DAHDI_FORMAT_GSM
Definition: codec_dahdi.c:66
uint16_t samples_written_to_hardware
Definition: codec_dahdi.c:290
Represents a media codec within Asterisk.
Definition: codec.h:42
#define AST_LIN2MU(a)
Definition: ulaw.h:49
unsigned int fake
Definition: codec_dahdi.c:287
char name[80]
Definition: translate.h:138
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
Definition: translate.h:154
uint32_t src_dahdi_fmt
Definition: codec_dahdi.c:271
struct ast_format * ast_format_ilbc
Built-in cached ilbc format.
Definition: format_cache.c:126
static struct test_val a
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