Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
codec_dahdi.c File Reference

Translate between various formats natively through DAHDI transcoding. More...

#include "asterisk.h"
#include <stdbool.h>
#include <poll.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <dahdi/user.h>
#include "asterisk/lock.h"
#include "asterisk/translate.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/ulaw.h"
#include "asterisk/format_compatibility.h"
Include dependency graph for codec_dahdi.c:

Go to the source code of this file.

Data Structures

struct  channel_usage
 
struct  codec_dahdi_pvt
 
struct  translator
 
struct  translators
 the list of translators More...
 

Macros

#define BUFFER_SIZE   8000
 
#define container_of(ptr, type, member)    ((type *)((char *)(ptr) - offsetof(type, member)))
 
#define DAHDI_FORMAT_ADPCM   (1 << 5)
 
#define DAHDI_FORMAT_ALAW   (1 << 3)
 
#define DAHDI_FORMAT_G723_1   (1 << 0)
 
#define DAHDI_FORMAT_G726   (1 << 4)
 
#define DAHDI_FORMAT_G729A   (1 << 8)
 
#define DAHDI_FORMAT_GSM   (1 << 1)
 
#define DAHDI_FORMAT_ILBC   (1 << 10)
 
#define DAHDI_FORMAT_LPC10   (1 << 7)
 
#define DAHDI_FORMAT_SLINEAR   (1 << 6)
 
#define DAHDI_FORMAT_SPEEX   (1 << 9)
 
#define DAHDI_FORMAT_ULAW   (1 << 2)
 
#define G723_SAMPLES   240
 
#define G729_SAMPLES   160
 
#define ULAW_SAMPLES   160
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void build_translators (uint32_t dstfmts, uint32_t srcfmts)
 
static int dahdi_decoder_framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
 
static struct ast_framedahdi_decoder_frameout (struct ast_trans_pvt *pvt)
 
static void dahdi_destroy (struct ast_trans_pvt *pvt)
 
static int dahdi_encoder_framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
 
static struct ast_framedahdi_encoder_frameout (struct ast_trans_pvt *pvt)
 
static struct ast_formatdahdi_format_to_cached (int format)
 
static int dahdi_new (struct ast_trans_pvt *pvt)
 
static int dahdi_translate (struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
 
static void dahdi_wait_for_packet (int fd)
 
static void dahdi_write_frame (struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
 
static struct ast_framefakesrc_sample (void)
 
static int find_transcoders (void)
 
static const struct ast_codecget_dahdi_codec (uint32_t dahdi_fmt)
 
static char * handle_cli_transcoder_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static bool is_already_registered (uint32_t dstfmt, uint32_t srcfmt)
 
static bool is_encoder (uint32_t src_dahdi_fmt)
 
static int lintoulaw (struct ast_trans_pvt *pvt, struct ast_frame *f)
 
static int load_module (void)
 
static int register_translator (uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
 
static int reload (void)
 
static int ulawtolin (struct ast_trans_pvt *pvt, int samples)
 
static int unload_module (void)
 
static void unregister_translators (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Generic DAHDI Transcoder Codec Translator" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct channel_usage channels
 
static struct ast_cli_entry cli []
 
static struct translators translators = AST_LIST_HEAD_INIT_VALUE
 

Detailed Description

Translate between various formats natively through DAHDI transcoding.

Definition in file codec_dahdi.c.

Macro Definition Documentation

◆ BUFFER_SIZE

#define BUFFER_SIZE   8000

Definition at line 55 of file codec_dahdi.c.

◆ container_of

#define container_of (   ptr,
  type,
  member 
)     ((type *)((char *)(ptr) - offsetof(type, member)))

Definition at line 277 of file codec_dahdi.c.

283 {
284 int fd;
285 struct dahdi_transcoder_formats fmts;
286 unsigned int softslin:1;
287 unsigned int fake:2;
288 uint16_t required_samples;
289 uint16_t samples_in_buffer;
290 uint16_t samples_written_to_hardware;
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
425static 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
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
499static 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
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,
873);
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#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
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
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
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)
static int register_translator(uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
#define ULAW_SAMPLES
Definition codec_dahdi.c:59
static struct ast_frame * dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
static struct channel_usage channels
static char * handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#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)
static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
#define BUFFER_SIZE
Definition codec_dahdi.c:55
static bool is_encoder(uint32_t src_dahdi_fmt)
#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)
static void build_translators(uint32_t dstfmts, uint32_t srcfmts)
#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)
static void dahdi_wait_for_packet(int fd)
static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
static struct ast_cli_entry cli[]
static int load_module(void)
#define DAHDI_FORMAT_ILBC
Definition codec_dahdi.c:84
#define DAHDI_FORMAT_G723_1
Definition codec_dahdi.c:64
static int unload_module(void)
static int reload(void)
static struct ast_frame * fakesrc_sample(void)
static void dahdi_destroy(struct ast_trans_pvt *pvt)
static int find_transcoders(void)
#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)
static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_format * dahdi_format_to_cached(int format)
#define container_of(ptr, type, member)
static int dahdi_translate(struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
static struct ast_translator lintoulaw
The complete translator for LinToulaw.
Definition codec_ulaw.c:104
static struct ast_translator ulawtolin
The complete translator for ulawToLin.
Definition codec_ulaw.c:81
struct ast_format * ast_format_adpcm
Built-in cached adpcm format.
struct ast_format * ast_format_gsm
Built-in cached gsm format.
struct ast_format * ast_format_speex
Built-in cached speex format.
struct ast_format * ast_format_ilbc
Built-in cached ilbc format.
struct ast_format * ast_format_g726
Built-in cached g726 format.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
struct ast_format * ast_format_lpc10
Built-in cached ilbc format.
struct ast_format * ast_format_g723
Built-in cached g723.1 format.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
struct ast_format * ast_format_alaw
Built-in cached alaw format.
struct ast_format * ast_format_g729
Built-in cached g729 format.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#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.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
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:764
int errno
@ 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
#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
enum ast_frame_type frametype
union ast_frame::@239 data
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition translate.h:213
union ast_trans_pvt::@308 outbuf
struct ast_frame f
Definition translate.h:215
struct ast_translator * t
Definition translate.h:214
int datalen
actual space used in outbuf
Definition translate.h:218
int16_t * i16
Definition translate.h:223
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
unsigned int fake
uint8_t ulaw_buffer[1024]
unsigned int softslin
uint16_t required_samples
uint16_t samples_written_to_hardware
uint16_t samples_in_buffer
struct translator::@154 entry
uint32_t dst_dahdi_fmt
uint32_t src_dahdi_fmt
struct ast_translator t
the list of translators
static struct test_val a
#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
#define AST_MULAW(a)
Definition ulaw.h:85
#define AST_LIN2MU(a)
Definition ulaw.h:49
#define ast_assert(a)
Definition utils.h:779
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition utils.h:1079
#define ARRAY_LEN(a)
Definition utils.h:706

◆ DAHDI_FORMAT_ADPCM

#define DAHDI_FORMAT_ADPCM   (1 << 5)

ADPCM (IMA)

Definition at line 74 of file codec_dahdi.c.

◆ DAHDI_FORMAT_ALAW

#define DAHDI_FORMAT_ALAW   (1 << 3)

Raw A-law data (G.711)

Definition at line 70 of file codec_dahdi.c.

◆ DAHDI_FORMAT_G723_1

#define DAHDI_FORMAT_G723_1   (1 << 0)

G.723.1 compression

Definition at line 64 of file codec_dahdi.c.

◆ DAHDI_FORMAT_G726

#define DAHDI_FORMAT_G726   (1 << 4)

ADPCM (G.726, 32kbps)

Definition at line 72 of file codec_dahdi.c.

◆ DAHDI_FORMAT_G729A

#define DAHDI_FORMAT_G729A   (1 << 8)

G.729A audio

Definition at line 80 of file codec_dahdi.c.

◆ DAHDI_FORMAT_GSM

#define DAHDI_FORMAT_GSM   (1 << 1)

GSM compression

Definition at line 66 of file codec_dahdi.c.

◆ DAHDI_FORMAT_ILBC

#define DAHDI_FORMAT_ILBC   (1 << 10)

iLBC Free Compression

Definition at line 84 of file codec_dahdi.c.

◆ DAHDI_FORMAT_LPC10

#define DAHDI_FORMAT_LPC10   (1 << 7)

LPC10, 180 samples/frame

Definition at line 78 of file codec_dahdi.c.

◆ DAHDI_FORMAT_SLINEAR

#define DAHDI_FORMAT_SLINEAR   (1 << 6)

Raw 16-bit Signed Linear (8000 Hz) PCM

Definition at line 76 of file codec_dahdi.c.

◆ DAHDI_FORMAT_SPEEX

#define DAHDI_FORMAT_SPEEX   (1 << 9)

SpeeX Free Compression

Definition at line 82 of file codec_dahdi.c.

◆ DAHDI_FORMAT_ULAW

#define DAHDI_FORMAT_ULAW   (1 << 2)

Raw mu-law data (G.711)

Definition at line 68 of file codec_dahdi.c.

◆ G723_SAMPLES

#define G723_SAMPLES   240

Definition at line 57 of file codec_dahdi.c.

◆ G729_SAMPLES

#define G729_SAMPLES   160

Definition at line 58 of file codec_dahdi.c.

◆ ULAW_SAMPLES

#define ULAW_SAMPLES   160

Definition at line 59 of file codec_dahdi.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 873 of file codec_dahdi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 873 of file codec_dahdi.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 873 of file codec_dahdi.c.

◆ build_translators()

static void build_translators ( uint32_t  dstfmts,
uint32_t  srcfmts 
)
static

Definition at line 785 of file codec_dahdi.c.

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}

References AST_LIST_LOCK, AST_LIST_UNLOCK, is_already_registered(), and register_translator().

Referenced by find_transcoders().

◆ dahdi_decoder_framein()

static int dahdi_decoder_framein ( struct ast_trans_pvt pvt,
struct ast_frame f 
)
static

Definition at line 476 of file codec_dahdi.c.

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}

References ast_log, dahdi_write_frame(), ast_frame::data, ast_frame::datalen, ast_trans_pvt::datalen, codec_dahdi_pvt::fake, ast_frame_subclass::format, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, and ast_frame::subclass.

Referenced by register_translator().

◆ dahdi_decoder_frameout()

static struct ast_frame * dahdi_decoder_frameout ( struct ast_trans_pvt pvt)
static

Definition at line 499 of file codec_dahdi.c.

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}

References AST_FRAME_VOICE, ast_frisolate, ast_log, ast_translator::buf_size, ast_trans_pvt::c, dahdi_wait_for_packet(), ast_frame::datalen, ast_trans_pvt::datalen, errno, ast_trans_pvt::f, codec_dahdi_pvt::fake, codec_dahdi_pvt::fd, ast_frame::frametype, LOG_ERROR, ast_translator::name, NULL, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, codec_dahdi_pvt::softslin, ast_trans_pvt::t, codec_dahdi_pvt::ulaw_buffer, ULAW_SAMPLES, and ulawtolin.

Referenced by register_translator().

◆ dahdi_destroy()

static void dahdi_destroy ( struct ast_trans_pvt pvt)
static

Definition at line 562 of file codec_dahdi.c.

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}

References ast_atomic_fetchadd_int(), channels, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G729A, channel_usage::decoders, channel_usage::encoders, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, and ast_trans_pvt::pvt.

Referenced by register_translator().

◆ dahdi_encoder_framein()

static int dahdi_encoder_framein ( struct ast_trans_pvt pvt,
struct ast_frame f 
)
static

Definition at line 372 of file codec_dahdi.c.

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}

References ast_log, dahdi_write_frame(), ast_frame::data, ast_trans_pvt::datalen, codec_dahdi_pvt::fake, ast_frame_subclass::format, lintoulaw, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_in_buffer, codec_dahdi_pvt::samples_written_to_hardware, codec_dahdi_pvt::softslin, ast_frame::subclass, and codec_dahdi_pvt::ulaw_buffer.

Referenced by register_translator().

◆ dahdi_encoder_frameout()

static struct ast_frame * dahdi_encoder_frameout ( struct ast_trans_pvt pvt)
static

Definition at line 425 of file codec_dahdi.c.

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}

References ast_codec_samples_count(), AST_FRAME_VOICE, ast_frisolate, ast_log, ast_translator::buf_size, ast_trans_pvt::c, dahdi_wait_for_packet(), ast_frame::datalen, ast_trans_pvt::datalen, errno, ast_trans_pvt::f, codec_dahdi_pvt::fake, codec_dahdi_pvt::fd, ast_frame::frametype, LOG_ERROR, ast_translator::name, NULL, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, and ast_trans_pvt::t.

Referenced by register_translator().

◆ dahdi_format_to_cached()

static struct ast_format * dahdi_format_to_cached ( int  format)
static

◆ dahdi_new()

static int dahdi_new ( struct ast_trans_pvt pvt)
static

Definition at line 682 of file codec_dahdi.c.

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}

References container_of, dahdi_translate(), translator::dst_dahdi_fmt, translator::src_dahdi_fmt, translator::t, and ast_trans_pvt::t.

Referenced by register_translator().

◆ dahdi_translate()

static int dahdi_translate ( struct ast_trans_pvt pvt,
uint32_t  dst_dahdi_fmt,
uint32_t  src_dahdi_fmt 
)
static

Definition at line 611 of file codec_dahdi.c.

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}

References ao2_bump, ast_assert, ast_atomic_fetchadd_int(), ast_debug, ast_fd_set_flags, ast_log, channels, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G729A, DAHDI_FORMAT_SLINEAR, dahdi_format_to_cached(), DAHDI_FORMAT_ULAW, channel_usage::decoders, ast_translator::dst_codec, channel_usage::encoders, errno, ast_trans_pvt::f, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, ast_frame_subclass::format, G723_SAMPLES, G729_SAMPLES, LOG_ERROR, ast_codec::name, NULL, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, codec_dahdi_pvt::softslin, ast_translator::src_codec, ast_frame::subclass, and ast_trans_pvt::t.

Referenced by dahdi_new().

◆ dahdi_wait_for_packet()

static void dahdi_wait_for_packet ( int  fd)
static

Definition at line 417 of file codec_dahdi.c.

418{
419 struct pollfd p = {0};
420 p.fd = fd;
421 p.events = POLLIN;
422 poll(&p, 1, 10);
423}

Referenced by dahdi_decoder_frameout(), and dahdi_encoder_frameout().

◆ dahdi_write_frame()

static void dahdi_write_frame ( struct codec_dahdi_pvt dahdip,
const uint8_t *  buffer,
const ssize_t  count 
)
static

Definition at line 359 of file codec_dahdi.c.

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}

References ast_log, errno, codec_dahdi_pvt::fd, and LOG_ERROR.

Referenced by dahdi_decoder_framein(), and dahdi_encoder_framein().

◆ fakesrc_sample()

static struct ast_frame * fakesrc_sample ( void  )
static

Definition at line 689 of file codec_dahdi.c.

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}

References AST_FRAME_VOICE, and ast_frame::frametype.

Referenced by register_translator().

◆ find_transcoders()

static int find_transcoders ( void  )
static

Definition at line 807 of file codec_dahdi.c.

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}

References ast_atomic_fetchadd_int(), ast_log, ast_verb, build_translators(), channels, DAHDI_FORMAT_ALAW, DAHDI_FORMAT_SLINEAR, DAHDI_FORMAT_ULAW, errno, LOG_ERROR, and channel_usage::total.

Referenced by load_module().

◆ get_dahdi_codec()

static const struct ast_codec * get_dahdi_codec ( uint32_t  dahdi_fmt)
static

Definition at line 161 of file codec_dahdi.c.

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}
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32

References AST_MEDIA_TYPE_AUDIO, DAHDI_FORMAT_ADPCM, DAHDI_FORMAT_ALAW, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G726, DAHDI_FORMAT_G729A, DAHDI_FORMAT_GSM, DAHDI_FORMAT_ILBC, DAHDI_FORMAT_LPC10, DAHDI_FORMAT_SLINEAR, DAHDI_FORMAT_SPEEX, DAHDI_FORMAT_ULAW, ast_codec::name, and NULL.

Referenced by register_translator().

◆ handle_cli_transcoder_show()

static char * handle_cli_transcoder_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 331 of file codec_dahdi.c.

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}

References a, ast_cli(), channels, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, copy(), NULL, and ast_cli_entry::usage.

◆ is_already_registered()

static bool is_already_registered ( uint32_t  dstfmt,
uint32_t  srcfmt 
)
static

Definition at line 770 of file codec_dahdi.c.

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}

References AST_LIST_TRAVERSE, translator::dst_dahdi_fmt, translator::entry, and translator::src_dahdi_fmt.

Referenced by build_translators().

◆ is_encoder()

static bool is_encoder ( uint32_t  src_dahdi_fmt)
static

Definition at line 701 of file codec_dahdi.c.

702{
703 return ((src_dahdi_fmt & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW | DAHDI_FORMAT_SLINEAR)) > 0);
704}

References DAHDI_FORMAT_ALAW, DAHDI_FORMAT_SLINEAR, and DAHDI_FORMAT_ULAW.

Referenced by register_translator().

◆ lintoulaw()

static int lintoulaw ( struct ast_trans_pvt pvt,
struct ast_frame f 
)
static

Definition at line 311 of file codec_dahdi.c.

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}

References AST_LIN2MU, ast_log, ast_frame::data, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, ast_frame::samples, codec_dahdi_pvt::samples_in_buffer, and codec_dahdi_pvt::ulaw_buffer.

◆ load_module()

static int load_module ( void  )
static

◆ register_translator()

static int register_translator ( uint32_t  dst_dahdi_fmt,
uint32_t  src_dahdi_fmt 
)
static

Definition at line 707 of file codec_dahdi.c.

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}

References ast_calloc, ast_free, AST_LIST_INSERT_HEAD, ast_register_translator, ast_translator::buf_size, ast_translator::buffer_samples, BUFFER_SIZE, dahdi_decoder_framein(), dahdi_decoder_frameout(), dahdi_destroy(), dahdi_encoder_framein(), dahdi_encoder_frameout(), dahdi_new(), ast_translator::desc_size, ast_translator::destroy, ast_translator::dst_codec, translator::dst_dahdi_fmt, fakesrc_sample(), ast_translator::framein, ast_translator::frameout, get_dahdi_codec(), is_encoder(), ast_codec::name, ast_translator::name, ast_translator::native_plc, ast_translator::newpvt, ast_translator::sample, ast_translator::src_codec, translator::src_dahdi_fmt, and translator::t.

Referenced by build_translators().

◆ reload()

static int reload ( void  )
static

Definition at line 848 of file codec_dahdi.c.

849{
851}

References AST_MODULE_LOAD_SUCCESS.

◆ ulawtolin()

static int ulawtolin ( struct ast_trans_pvt pvt,
int  samples 
)
static

Definition at line 295 of file codec_dahdi.c.

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}

References AST_MULAW, ast_trans_pvt::datalen, ast_trans_pvt::i16, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, and codec_dahdi_pvt::ulaw_buffer.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 853 of file codec_dahdi.c.

854{
857
858 return 0;
859}

References ARRAY_LEN, ast_cli_unregister_multiple(), cli, and unregister_translators().

◆ unregister_translators()

static void unregister_translators ( void  )
static

Definition at line 757 of file codec_dahdi.c.

758{
759 struct translator *cur;
760
762 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) {
764 ast_free(cur);
765 }
767}

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_unregister_translator(), translator::entry, and translator::t.

Referenced by unload_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Generic DAHDI Transcoder Codec Translator" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, }
static

Definition at line 873 of file codec_dahdi.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 873 of file codec_dahdi.c.

◆ channels

struct channel_usage channels
static

◆ cli

struct ast_cli_entry cli[]
static
Initial value:
= {
{ .handler = handle_cli_transcoder_show , .summary = "Display DAHDI transcoder utilization." ,}
}

Definition at line 265 of file codec_dahdi.c.

265 {
266 AST_CLI_DEFINE(handle_cli_transcoder_show, "Display DAHDI transcoder utilization.")
267};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by cli_complete_subscription_callid(), cli_complete_subscription_common(), cli_list_subscriptions_detail(), cli_list_subscriptions_inout(), cli_show_subscription_common(), cli_show_subscription_inout(), cli_show_subscriptions_detail(), cli_show_subscriptions_inout(), load_module(), and unload_module().

◆ translators