39 #include <netinet/in.h>
40 #include <sys/ioctl.h>
42 #include <dahdi/user.h>
55 #define BUFFER_SIZE 8000
57 #define G723_SAMPLES 240
58 #define G729_SAMPLES 160
59 #define ULAW_SAMPLES 160
62 #ifndef DAHDI_FORMAT_MAX_AUDIO
64 #define DAHDI_FORMAT_G723_1 (1 << 0)
66 #define DAHDI_FORMAT_GSM (1 << 1)
68 #define DAHDI_FORMAT_ULAW (1 << 2)
70 #define DAHDI_FORMAT_ALAW (1 << 3)
72 #define DAHDI_FORMAT_G726 (1 << 4)
74 #define DAHDI_FORMAT_ADPCM (1 << 5)
76 #define DAHDI_FORMAT_SLINEAR (1 << 6)
78 #define DAHDI_FORMAT_LPC10 (1 << 7)
80 #define DAHDI_FORMAT_G729A (1 << 8)
82 #define DAHDI_FORMAT_SPEEX (1 << 9)
84 #define DAHDI_FORMAT_ILBC (1 << 10)
93 #if defined(NOT_NEEDED)
105 static uint64_t bitfield_dahdi2ast(
unsigned dahdi)
161 static const struct ast_codec *get_dahdi_codec(uint32_t dahdi_fmt)
165 static const struct ast_codec dahdi_g723_1 = {
167 .type = AST_MEDIA_TYPE_AUDIO,
170 static const struct ast_codec dahdi_gsm = {
172 .type = AST_MEDIA_TYPE_AUDIO,
175 static const struct ast_codec dahdi_ulaw = {
177 .type = AST_MEDIA_TYPE_AUDIO,
180 static const struct ast_codec dahdi_alaw = {
182 .type = AST_MEDIA_TYPE_AUDIO,
185 static const struct ast_codec dahdi_g726 = {
187 .type = AST_MEDIA_TYPE_AUDIO,
190 static const struct ast_codec dahdi_adpcm = {
192 .type = AST_MEDIA_TYPE_AUDIO,
195 static const struct ast_codec dahdi_slinear = {
197 .type = AST_MEDIA_TYPE_AUDIO,
200 static const struct ast_codec dahdi_lpc10 = {
202 .type = AST_MEDIA_TYPE_AUDIO,
205 static const struct ast_codec dahdi_g729a = {
207 .type = AST_MEDIA_TYPE_AUDIO,
210 static const struct ast_codec dahdi_speex = {
212 .type = AST_MEDIA_TYPE_AUDIO,
215 static const struct ast_codec dahdi_ilbc = {
217 .type = AST_MEDIA_TYPE_AUDIO,
223 codec = &dahdi_g723_1;
238 codec = &dahdi_adpcm;
241 codec = &dahdi_slinear;
244 codec = &dahdi_lpc10;
247 codec = &dahdi_g729a;
250 codec = &dahdi_speex;
266 AST_CLI_DEFINE(handle_cli_transcoder_show,
"Display DAHDI transcoder utilization.")
271 uint32_t src_dahdi_fmt;
272 uint32_t dst_dahdi_fmt;
277 #define container_of(ptr, type, member) \
278 ((type *)((char *)(ptr) - offsetof(type, member)))
285 struct dahdi_transcoder_formats fmts;
286 unsigned int softslin:1;
288 uint16_t required_samples;
289 uint16_t samples_in_buffer;
290 uint16_t samples_written_to_hardware;
291 uint8_t ulaw_buffer[1024];
299 uint8_t *src = &dahdip->ulaw_buffer[0];
300 int16_t *dst = pvt->outbuf.i16 + pvt->
datalen;
304 *dst++ = AST_MULAW(*src++);
315 uint8_t *dst = &dahdip->ulaw_buffer[dahdip->samples_in_buffer];
316 int16_t *src = f->
data.ptr;
318 if (dahdip->samples_in_buffer + i >
sizeof(dahdip->ulaw_buffer)) {
319 ast_log(LOG_ERROR,
"Out of buffer space!\n");
324 *dst++ = AST_LIN2MU(*src++);
327 dahdip->samples_in_buffer += f->
samples;
337 e->
command =
"transcoder show";
339 "Usage: transcoder show\n"
340 " Displays channel utilization of DAHDI transcoder(s).\n";
347 return CLI_SHOWUSAGE;
352 ast_cli(a->fd,
"No DAHDI transcoders found.\n");
354 ast_cli(a->fd,
"%d/%d encoders/decoders of %d channels are in use.\n",
copy.encoders,
copy.decoders,
copy.total);
359 static void dahdi_write_frame(
struct codec_dahdi_pvt *dahdip,
const uint8_t *buffer,
const ssize_t count)
363 res = write(dahdip->fd, buffer, count);
365 ast_log(LOG_ERROR,
"Failed to write to transcoder: %s\n", strerror(errno));
368 ast_log(LOG_ERROR,
"Requested write of %zd bytes, but only wrote %d bytes.\n", count, res);
385 if (dahdip->softslin) {
394 if (dahdip->samples_in_buffer + f->
samples >
sizeof(dahdip->ulaw_buffer)) {
395 ast_log(LOG_ERROR,
"Out of buffer space.\n");
398 memcpy(&dahdip->ulaw_buffer[dahdip->samples_in_buffer], f->
data.ptr, f->
samples);
399 dahdip->samples_in_buffer += f->
samples;
402 while (dahdip->samples_in_buffer >= dahdip->required_samples) {
403 dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples);
404 dahdip->samples_written_to_hardware += dahdip->required_samples;
405 dahdip->samples_in_buffer -= dahdip->required_samples;
406 if (dahdip->samples_in_buffer) {
408 memmove(dahdip->ulaw_buffer, &dahdip->ulaw_buffer[dahdip->required_samples],
409 dahdip->samples_in_buffer);
417 static void dahdi_wait_for_packet(
int fd)
419 struct pollfd p = {0};
430 if (2 == dahdip->fake) {
433 .samples = dahdip->required_samples,
441 }
else if (1 == dahdip->fake) {
446 if (dahdip->samples_written_to_hardware >= dahdip->required_samples) {
447 dahdi_wait_for_packet(dahdip->fd);
452 if (EWOULDBLOCK == errno) {
456 ast_log(LOG_ERROR,
"Failed to read from transcoder: %s\n", strerror(errno));
463 dahdip->samples_written_to_hardware =
464 (dahdip->samples_written_to_hardware >= pvt->
f.
samples) ?
465 dahdip->samples_written_to_hardware - pvt->
f.
samples : 0;
488 if (f->
samples != dahdip->required_samples) {
489 ast_log(LOG_ERROR,
"%d != %d %d\n", f->
samples, dahdip->required_samples, f->
datalen);
492 dahdi_write_frame(dahdip, f->
data.ptr, f->
datalen);
493 dahdip->samples_written_to_hardware += f->
samples;
504 if (2 == dahdip->fake) {
507 .samples = dahdip->required_samples,
515 }
else if (1 == dahdip->fake) {
521 if (dahdip->samples_written_to_hardware >= ULAW_SAMPLES) {
522 dahdi_wait_for_packet(dahdip->fd);
526 if (dahdip->softslin) {
527 res = read(dahdip->fd, dahdip->ulaw_buffer,
sizeof(dahdip->ulaw_buffer));
533 if (EWOULDBLOCK == errno) {
537 ast_log(LOG_ERROR,
"Failed to read from transcoder: %s\n", strerror(errno));
541 if (dahdip->softslin) {
550 dahdip->samples_written_to_hardware =
551 (dahdip->samples_written_to_hardware >= res) ?
552 dahdip->samples_written_to_hardware - res : 0;
566 switch (dahdip->fmts.dstfmt) {
579 static struct ast_format *dahdi_format_to_cached(
int format)
611 static int dahdi_translate(
struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
617 const char *dev_filename =
"/dev/dahdi/transcode";
619 if ((fd = open(dev_filename, O_RDWR)) < 0) {
620 ast_log(LOG_ERROR,
"Failed to open %s: %s\n", dev_filename, strerror(errno));
624 dahdip->fmts.srcfmt = src_dahdi_fmt;
625 dahdip->fmts.dstfmt = dst_dahdi_fmt;
633 if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) {
634 if ((ENODEV == errno) && !tried_once) {
644 ast_debug(1,
"Using soft_slin support on source\n");
645 dahdip->softslin = 1;
648 ast_debug(1,
"Using soft_slin support on destination\n");
649 dahdip->softslin = 1;
655 ast_log(LOG_ERROR,
"Unable to attach to transcoder: %s\n", strerror(errno));
665 dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (
DAHDI_FORMAT_G723_1)) ? G723_SAMPLES : G729_SAMPLES;
667 switch (dahdip->fmts.dstfmt) {
686 return dahdi_translate(pvt, zt->dst_dahdi_fmt, zt->src_dahdi_fmt);
689 static struct ast_frame *fakesrc_sample(
void)
695 .src = __PRETTY_FUNCTION__
701 static bool is_encoder(uint32_t src_dahdi_fmt)
707 static int register_translator(uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
714 dst_codec = get_dahdi_codec(dst_dahdi_fmt);
715 src_codec = get_dahdi_codec(src_dahdi_fmt);
716 if (!dst_codec || !src_codec) {
724 zt->src_dahdi_fmt = src_dahdi_fmt;
725 zt->dst_dahdi_fmt = dst_dahdi_fmt;
727 snprintf(zt->t.
name,
sizeof(zt->t.
name),
"dahdi_%s_to_%s",
730 memcpy(&zt->t.
src_codec, src_codec,
sizeof(*src_codec));
731 memcpy(&zt->t.
dst_codec, dst_codec,
sizeof(*dst_codec));
733 if (is_encoder(src_dahdi_fmt)) {
734 zt->t.
framein = dahdi_encoder_framein;
735 zt->t.
frameout = dahdi_encoder_frameout;
737 zt->t.
framein = dahdi_decoder_framein;
738 zt->t.
frameout = dahdi_decoder_frameout;
743 zt->t.
sample = fakesrc_sample;
757 static void unregister_translators(
void)
770 static bool is_already_registered(uint32_t dstfmt, uint32_t srcfmt)
776 if ((zt->src_dahdi_fmt == srcfmt) && (zt->dst_dahdi_fmt == dstfmt)) {
785 static void build_translators(uint32_t dstfmts, uint32_t srcfmts)
792 for (srcfmt = 1; srcfmt != 0; srcfmt <<= 1) {
793 for (dstfmt = 1; dstfmt != 0; dstfmt <<= 1) {
794 if (!(dstfmts & dstfmt) || !(srcfmts & srcfmt)) {
797 if (is_already_registered(dstfmt, srcfmt)) {
800 register_translator(dstfmt, srcfmt);
807 static int find_transcoders(
void)
809 struct dahdi_transcoder_info info = { 0, };
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));
817 for (info.tcnum = 0; !ioctl(fd, DAHDI_TC_GETINFO, &info); info.tcnum++) {
818 ast_verb(2,
"Found transcoder '%s'.\n", info.name);
835 build_translators(info.dstfmts, info.srcfmts);
842 ast_verb(2,
"No hardware transcoders found.\n");
848 static int reload(
void)
853 static int unload_module(
void)
856 unregister_translators();
861 static int load_module(
void)
868 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
"Generic DAHDI Transcoder Codec Translator",
869 .support_level = AST_MODULE_SUPPORT_CORE,
871 .unload = unload_module,
int datalen
actual space used in outbuf
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
const char * name
Name for this codec.
Asterisk main include file. File version handling, generic pbx functions.
int(* newpvt)(struct ast_trans_pvt *)
Descriptor of a translator.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Support for translation of data formats. translate.c.
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define DAHDI_FORMAT_G723_1
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define DAHDI_FORMAT_LPC10
static struct ast_translator ulawtolin
The complete translator for ulawToLin.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
struct ast_frame_subclass subclass
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Configuration File Parser.
#define DAHDI_FORMAT_SPEEX
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
u-Law to Signed linear conversion
General Asterisk PBX channel definitions.
#define DAHDI_FORMAT_G729A
#define DAHDI_FORMAT_ULAW
#define ast_register_translator(t)
See __ast_register_translator()
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given translator.
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define DAHDI_FORMAT_SLINEAR
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
void(* destroy)(struct ast_trans_pvt *pvt)
struct ast_codec dst_codec
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
struct ast_codec src_codec
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
#define DAHDI_FORMAT_G726
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
struct ast_frame *(* sample)(void)
#define DAHDI_FORMAT_ALAW
Standard Command Line Interface.
#define DAHDI_FORMAT_ADPCM
struct ast_frame *(* frameout)(struct ast_trans_pvt *pvt)
Data structure associated with a single frame of data.
#define DAHDI_FORMAT_ILBC
static struct ast_translator lintoulaw
The complete translator for LinToulaw.
enum ast_frame_type frametype
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
Represents a media codec within Asterisk.
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
int buffer_samples
size of outbuf, in samples. Leave it 0 if you want the framein callback deal with the frame...