mirror of https://github.com/asterisk/asterisk
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@65 65c4cc65-6c06-0410-ace0-fbb531ad65f31.0
parent
60cc32f242
commit
42a21812e9
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Everybody's favorite format: MP3 Files! Yay!
|
||||
*
|
||||
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/sched.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include "../channels/adtranvofr.h"
|
||||
|
||||
|
||||
#define MP3_MAX_SIZE 1400
|
||||
|
||||
struct ast_filestream {
|
||||
/* First entry MUST be reserved for the channel type */
|
||||
void *reserved[AST_RESERVED_POINTERS];
|
||||
/* This is what a filestream means to us */
|
||||
int fd; /* Descriptor */
|
||||
struct ast_channel *owner;
|
||||
struct ast_filestream *next;
|
||||
struct ast_frame *fr; /* Frame representation of buf */
|
||||
char buf[sizeof(struct ast_frame) + MP3_MAX_SIZE + AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
|
||||
int pos;
|
||||
};
|
||||
|
||||
|
||||
static struct ast_filestream *glist = NULL;
|
||||
static pthread_mutex_t mp3_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int glistcnt = 0;
|
||||
|
||||
static char *name = "mp3";
|
||||
static char *desc = "MPEG-2 Layer 3 File Format Support";
|
||||
static char *exts = "mp3|mpeg3";
|
||||
|
||||
#if 0
|
||||
#define MP3_FRAMELEN 417
|
||||
#else
|
||||
#define MP3_FRAMELEN 400
|
||||
#endif
|
||||
#define MP3_OUTPUTLEN 2304 /* Bytes */
|
||||
#define MP3_TIMELEN ((MP3_OUTPUTLEN * 1000 / 16000) )
|
||||
|
||||
static struct ast_filestream *mp3_open(int fd)
|
||||
{
|
||||
/* We don't have any header to read or anything really, but
|
||||
if we did, it would go here. We also might want to check
|
||||
and be sure it's a valid file. */
|
||||
struct ast_filestream *tmp;
|
||||
if ((tmp = malloc(sizeof(struct ast_filestream)))) {
|
||||
if (pthread_mutex_lock(&mp3_lock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock mp3 list\n");
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
tmp->next = glist;
|
||||
glist = tmp;
|
||||
tmp->fd = fd;
|
||||
tmp->owner = NULL;
|
||||
tmp->fr = (struct ast_frame *)tmp->buf;
|
||||
tmp->fr->data = tmp->buf + sizeof(struct ast_frame);
|
||||
tmp->fr->frametype = AST_FRAME_VOICE;
|
||||
tmp->fr->subclass = AST_FORMAT_MP3;
|
||||
/* datalen will vary for each frame */
|
||||
tmp->fr->src = name;
|
||||
tmp->fr->mallocd = 0;
|
||||
glistcnt++;
|
||||
pthread_mutex_unlock(&mp3_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct ast_filestream *mp3_rewrite(int fd, char *comment)
|
||||
{
|
||||
/* We don't have any header to read or anything really, but
|
||||
if we did, it would go here. We also might want to check
|
||||
and be sure it's a valid file. */
|
||||
struct ast_filestream *tmp;
|
||||
if ((tmp = malloc(sizeof(struct ast_filestream)))) {
|
||||
if (pthread_mutex_lock(&mp3_lock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock mp3 list\n");
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
tmp->next = glist;
|
||||
glist = tmp;
|
||||
tmp->fd = fd;
|
||||
tmp->owner = NULL;
|
||||
tmp->fr = NULL;
|
||||
glistcnt++;
|
||||
pthread_mutex_unlock(&mp3_lock);
|
||||
ast_update_use_count();
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct ast_frame *mp3_read(struct ast_filestream *s)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mp3_close(struct ast_filestream *s)
|
||||
{
|
||||
struct ast_filestream *tmp, *tmpl = NULL;
|
||||
if (pthread_mutex_lock(&mp3_lock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock mp3 list\n");
|
||||
return;
|
||||
}
|
||||
tmp = glist;
|
||||
while(tmp) {
|
||||
if (tmp == s) {
|
||||
if (tmpl)
|
||||
tmpl->next = tmp->next;
|
||||
else
|
||||
glist = tmp->next;
|
||||
break;
|
||||
}
|
||||
tmpl = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
glistcnt--;
|
||||
if (s->owner) {
|
||||
s->owner->stream = NULL;
|
||||
if (s->owner->streamid > -1)
|
||||
ast_sched_del(s->owner->sched, s->owner->streamid);
|
||||
s->owner->streamid = -1;
|
||||
}
|
||||
pthread_mutex_unlock(&mp3_lock);
|
||||
ast_update_use_count();
|
||||
if (!tmp)
|
||||
ast_log(LOG_WARNING, "Freeing a filestream we don't seem to own\n");
|
||||
close(s->fd);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static int ast_read_callback(void *data)
|
||||
{
|
||||
/* XXX Don't assume frames are this size XXX */
|
||||
u_int16_t size=MP3_FRAMELEN;
|
||||
u_int32_t delay = -1;
|
||||
int res;
|
||||
struct ast_filestream *s = data;
|
||||
/* Send a frame from the file to the appropriate channel */
|
||||
/* Read the data into the buffer */
|
||||
s->fr->offset = AST_FRIENDLY_OFFSET;
|
||||
s->fr->datalen = size;
|
||||
s->fr->data = s->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
|
||||
if ((res = read(s->fd, s->fr->data , size)) != size) {
|
||||
ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
|
||||
s->owner->streamid = -1;
|
||||
return 0;
|
||||
}
|
||||
delay = MP3_TIMELEN;
|
||||
s->fr->timelen = delay;
|
||||
/* Lastly, process the frame */
|
||||
if (ast_write(s->owner, s->fr)) {
|
||||
ast_log(LOG_WARNING, "Failed to write frame\n");
|
||||
s->owner->streamid = -1;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mp3_apply(struct ast_channel *c, struct ast_filestream *s)
|
||||
{
|
||||
/* Select our owner for this stream, and get the ball rolling. */
|
||||
s->owner = c;
|
||||
s->owner->streamid = ast_sched_add(s->owner->sched, MP3_TIMELEN, ast_read_callback, s);
|
||||
ast_read_callback(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
|
||||
{
|
||||
int res;
|
||||
if (fs->fr) {
|
||||
ast_log(LOG_WARNING, "Asked to write on a read stream??\n");
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype != AST_FRAME_VOICE) {
|
||||
ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
|
||||
return -1;
|
||||
}
|
||||
if (f->subclass != AST_FORMAT_MP3) {
|
||||
ast_log(LOG_WARNING, "Asked to write non-mp3 frame!\n");
|
||||
return -1;
|
||||
}
|
||||
if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
|
||||
ast_log(LOG_WARNING, "Unable to write frame: res=%d (%s)\n", res, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *mp3_getcomment(struct ast_filestream *s)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int load_module()
|
||||
{
|
||||
return ast_format_register(name, exts, AST_FORMAT_MP3,
|
||||
mp3_open,
|
||||
mp3_rewrite,
|
||||
mp3_apply,
|
||||
mp3_write,
|
||||
mp3_read,
|
||||
mp3_close,
|
||||
mp3_getcomment);
|
||||
|
||||
|
||||
}
|
||||
|
||||
int unload_module()
|
||||
{
|
||||
struct ast_filestream *tmp, *tmpl;
|
||||
if (pthread_mutex_lock(&mp3_lock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock mp3 list\n");
|
||||
return -1;
|
||||
}
|
||||
tmp = glist;
|
||||
while(tmp) {
|
||||
if (tmp->owner)
|
||||
ast_softhangup(tmp->owner);
|
||||
tmpl = tmp;
|
||||
tmp = tmp->next;
|
||||
free(tmpl);
|
||||
}
|
||||
pthread_mutex_unlock(&mp3_lock);
|
||||
return ast_format_unregister(name);
|
||||
}
|
||||
|
||||
int usecount()
|
||||
{
|
||||
int res;
|
||||
if (pthread_mutex_lock(&mp3_lock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock mp3 list\n");
|
||||
return -1;
|
||||
}
|
||||
res = glistcnt;
|
||||
pthread_mutex_unlock(&mp3_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description()
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Frame manipulation routines
|
||||
*
|
||||
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Important: I should be made more efficient. Frame headers should
|
||||
* most definitely be cached
|
||||
*/
|
||||
|
||||
void ast_frfree(struct ast_frame *fr)
|
||||
{
|
||||
if (fr->mallocd & AST_MALLOCD_DATA) {
|
||||
if (fr->data)
|
||||
free(fr->data - fr->offset);
|
||||
}
|
||||
if (fr->mallocd & AST_MALLOCD_SRC) {
|
||||
if (fr->src)
|
||||
free(fr->src);
|
||||
}
|
||||
if (fr->mallocd & AST_MALLOCD_HDR) {
|
||||
free(fr);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_frchain(struct ast_frame_chain *fc)
|
||||
{
|
||||
struct ast_frame_chain *last;
|
||||
while(fc) {
|
||||
last = fc;
|
||||
fc = fc->next;
|
||||
if (last->fr)
|
||||
ast_frfree(last->fr);
|
||||
free(last);
|
||||
}
|
||||
}
|
||||
|
||||
struct ast_frame *ast_frisolate(struct ast_frame *fr)
|
||||
{
|
||||
struct ast_frame *out;
|
||||
if (!(fr->mallocd & AST_MALLOCD_HDR)) {
|
||||
/* Allocate a new header if needed */
|
||||
out = malloc(sizeof(struct ast_frame));
|
||||
if (!out) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
out->frametype = fr->frametype;
|
||||
out->subclass = fr->subclass;
|
||||
out->datalen = 0;
|
||||
out->timelen = fr->timelen;
|
||||
out->offset = 0;
|
||||
out->src = NULL;
|
||||
out->data = NULL;
|
||||
} else {
|
||||
out = fr;
|
||||
}
|
||||
if (!(fr->mallocd & AST_MALLOCD_SRC)) {
|
||||
if (fr->src)
|
||||
out->src = strdup(fr->src);
|
||||
} else
|
||||
out->src = fr->src;
|
||||
if (!(fr->mallocd & AST_MALLOCD_DATA)) {
|
||||
out->data = malloc(fr->datalen + fr->offset);
|
||||
out->data += fr->offset;
|
||||
out->offset = fr->offset;
|
||||
out->datalen = fr->datalen;
|
||||
memcpy(out->data, fr->data, fr->datalen);
|
||||
if (!out->data) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
|
||||
return out;
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Generic File Format Support.
|
||||
*
|
||||
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_FILE_H
|
||||
#define _ASTERISK_FILE_H
|
||||
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Convenient for waiting */
|
||||
#define AST_DIGIT_ANY "0123456789#*"
|
||||
|
||||
/* Defined by individual formats. First item MUST be a
|
||||
pointer for use by the stream manager */
|
||||
struct ast_filestream;
|
||||
|
||||
/* Register a new file format capability */
|
||||
int ast_format_register(char *name, char *exts, int format,
|
||||
struct ast_filestream * (*open)(int fd),
|
||||
struct ast_filestream * (*rewrite)(int fd, char *comment),
|
||||
int (*apply)(struct ast_channel *, struct ast_filestream *),
|
||||
int (*write)(struct ast_filestream *, struct ast_frame *),
|
||||
struct ast_frame * (*read)(struct ast_filestream *),
|
||||
void (*close)(struct ast_filestream *),
|
||||
char * (*getcomment)(struct ast_filestream *));
|
||||
|
||||
int ast_format_unregister(char *name);
|
||||
|
||||
/* Start streaming a file */
|
||||
int ast_streamfile(struct ast_channel *c, char *filename);
|
||||
|
||||
/* Stop playback of a stream */
|
||||
int ast_stopstream(struct ast_channel *c);
|
||||
|
||||
/* See if a given file exists in a given format. If fmt is NULL, any format is accepted.*/
|
||||
int ast_fileexists(char *filename, char *fmt);
|
||||
|
||||
/* Rename a given file in a given format, or if fmt is NULL, then do so for all */
|
||||
int ast_filerename(char *oldname, char *newname, char *fmt);
|
||||
|
||||
/* Delete a given file in a given format, or if fmt is NULL, then do so for all */
|
||||
int ast_filedelete(char *filename, char *fmt);
|
||||
|
||||
/* Wait for a stream to stop or for any one of a given digit to arrive, Returns
|
||||
0 if the stream finishes, the character if it was interrupted, and -1 on error */
|
||||
char ast_waitstream(struct ast_channel *c, char *breakon);
|
||||
|
||||
/* Create an outgoing file stream. oflags are flags for the open() command, and
|
||||
if check is non-zero, then it will not write a file if there are any files that
|
||||
start with that name and have an extension */
|
||||
struct ast_filestream *ast_writefile(char *filename, char *type, char *comment, int oflags, int check, mode_t mode);
|
||||
|
||||
/* Send a frame to a filestream -- note: does NOT free the frame, call ast_frfree manually */
|
||||
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f);
|
||||
|
||||
/* Close a playback or recording stream */
|
||||
int ast_closestream(struct ast_filestream *f);
|
||||
|
||||
#define AST_RESERVED_POINTERS 4
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Asterisk internal frame definitions.
|
||||
*
|
||||
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_FRAME_H
|
||||
#define _ASTERISK_FRAME_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A frame of data read used to communicate between
|
||||
between channels and applications */
|
||||
struct ast_frame {
|
||||
int frametype; /* Kind of frame */
|
||||
int subclass; /* Subclass, frame dependent */
|
||||
int datalen; /* Length of data */
|
||||
int timelen; /* Amount of time associated with this frame */
|
||||
int mallocd; /* Was the data malloc'd? i.e. should we
|
||||
free it when we discard the frame? */
|
||||
int offset; /* How far into "data" the data really starts */
|
||||
char *src; /* Optional source of frame for debugging */
|
||||
void *data; /* Pointer to actual data */
|
||||
};
|
||||
|
||||
struct ast_frame_chain {
|
||||
/* XXX Should ast_frame chain's be just prt of frames, i.e. should they just link? XXX */
|
||||
struct ast_frame *fr;
|
||||
struct ast_frame_chain *next;
|
||||
};
|
||||
|
||||
#define AST_FRIENDLY_OFFSET 64 /* It's polite for a a new frame to
|
||||
have at least this number of bytes
|
||||
of offset before your real frame data
|
||||
so that additional headers can be
|
||||
added. */
|
||||
|
||||
#define AST_MALLOCD_HDR (1 << 0) /* Need the header be free'd? */
|
||||
#define AST_MALLOCD_DATA (1 << 1) /* Need the data be free'd? */
|
||||
#define AST_MALLOCD_SRC (1 << 2) /* Need the source be free'd? (haha!) */
|
||||
|
||||
/* Frame types */
|
||||
#define AST_FRAME_DTMF 1 /* A DTMF digit, subclass is the digit */
|
||||
#define AST_FRAME_VOICE 2 /* Voice data, subclass is AST_FORMAT_* */
|
||||
#define AST_FRAME_VIDEO 3 /* Video frame, maybe?? :) */
|
||||
#define AST_FRAME_CONTROL 4 /* A control frame, subclass is AST_CONTROL_* */
|
||||
#define AST_FRAME_NULL 5 /* An empty, useless frame */
|
||||
|
||||
/* Data formats for capabilities and frames alike */
|
||||
#define AST_FORMAT_G723_1 (1 << 0) /* G.723.1 compression */
|
||||
#define AST_FORMAT_GSM (1 << 1) /* GSM compression */
|
||||
#define AST_FORMAT_ULAW (1 << 2) /* Raw mu-law data (G.711) */
|
||||
#define AST_FORMAT_ALAW (1 << 3) /* Raw A-law data (G.711) */
|
||||
#define AST_FORMAT_MP3 (1 << 4) /* MPEG-2 layer 3 */
|
||||
#define AST_FORMAT_ADPCM (1 << 5) /* ADPCM */
|
||||
#define AST_FORMAT_SLINEAR (1 << 6) /* Raw 16-bit Signed Linear (8000 Hz) PCM */
|
||||
#define AST_FORMAT_MAX_AUDIO (1 << 15) /* Maximum audio format */
|
||||
#define AST_FORMAT_JPEG (1 << 16) /* JPEG Images */
|
||||
#define AST_FORMAT_PNG (1 << 17) /* PNG Images */
|
||||
#define AST_FORMAT_H261 (1 << 18) /* H.261 Video */
|
||||
#define AST_FORMAT_H263 (1 << 19) /* H.263 Video */
|
||||
|
||||
/* Control frame types */
|
||||
#define AST_CONTROL_HANGUP 1 /* Other end has hungup */
|
||||
#define AST_CONTROL_RING 2 /* Local ring */
|
||||
#define AST_CONTROL_RINGING 3 /* Remote end is ringing */
|
||||
#define AST_CONTROL_ANSWER 4 /* Remote end has answered */
|
||||
#define AST_CONTROL_BUSY 5 /* Remote end is busy */
|
||||
#define AST_CONTROL_TAKEOFFHOOK 6 /* Make it go off hook */
|
||||
#define AST_CONTROL_OFFHOOK 7 /* Line is off hook */
|
||||
|
||||
/* Request a frame be allocated. source is an optional source of the frame,
|
||||
len is the requested length, or "0" if the caller will supply the buffer */
|
||||
struct ast_frame *ast_fralloc(char *source, int len);
|
||||
|
||||
/* Free a frame, and the memory it used if applicable */
|
||||
void ast_frfree(struct ast_frame *fr);
|
||||
|
||||
/* Take a frame, and if it's not been malloc'd, make a malloc'd copy
|
||||
and if the data hasn't been malloced then make the
|
||||
data malloc'd. If you need to store frames, say for queueing, then
|
||||
you should call this function. */
|
||||
struct ast_frame *ast_frisolate(struct ast_frame *fr);
|
||||
|
||||
void ast_frchain(struct ast_frame_chain *fc);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Translate via the use of pseudo channels
|
||||
*
|
||||
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_TRANSLATE_H
|
||||
#define _ASTERISK_TRANSLATE_H
|
||||
|
||||
#define MAX_FORMAT 32
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <asterisk/frame.h>
|
||||
|
||||
/* Declared by individual translators */
|
||||
struct ast_translator_pvt;
|
||||
|
||||
struct ast_translator {
|
||||
char name[80];
|
||||
int srcfmt;
|
||||
int dstfmt;
|
||||
struct ast_translator_pvt *(*new)();
|
||||
int (*framein)(struct ast_translator_pvt *pvt, struct ast_frame *in);
|
||||
struct ast_frame * (*frameout)(struct ast_translator_pvt *pvt);
|
||||
void (*destroy)(struct ast_translator_pvt *pvt);
|
||||
/* For performance measurements */
|
||||
/* Generate an example frame */
|
||||
struct ast_frame * (*sample)(void);
|
||||
/* Cost in milliseconds for encoding/decoding 1 second of sound */
|
||||
int cost;
|
||||
/* For linking, not to be modified by the translator */
|
||||
struct ast_translator *next;
|
||||
};
|
||||
|
||||
struct ast_trans_pvt;
|
||||
|
||||
/* Create a pseudo channel which translates from a real channel into our
|
||||
desired format. When a translator is installed, you should not use the
|
||||
sub channel until you have stopped the translator. For all other
|
||||
actions, use the real channel. Generally, translators should be created
|
||||
when needed and immediately destroyed when no longer needed. */
|
||||
|
||||
/* Directions */
|
||||
#define AST_DIRECTION_OUT 1
|
||||
#define AST_DIRECTION_IN 2
|
||||
#define AST_DIRECTION_BOTH 3
|
||||
|
||||
extern struct ast_channel *ast_translator_create(struct ast_channel *real, int format, int direction);
|
||||
extern void ast_translator_destroy(struct ast_channel *tran);
|
||||
/* Register a Codec translator */
|
||||
extern int ast_register_translator(struct ast_translator *t);
|
||||
/* Unregister same */
|
||||
extern int ast_unregister_translator(struct ast_translator *t);
|
||||
/* Given a list of sources, and a designed destination format, which should
|
||||
I choose? */
|
||||
extern int ast_translator_best_choice(int dst, int srcs);
|
||||
extern struct ast_trans_pvt *ast_translator_build_path(int source, int dest);
|
||||
extern void ast_translator_free_path(struct ast_trans_pvt *tr);
|
||||
extern struct ast_frame_chain *ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f);
|
||||
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in new issue