Sat Apr 26 2014 22:01:36

Asterisk developer's documentation


format_sln.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Anthony Minessale
00005  * Anthony Minessale (anthmct@yahoo.com)
00006  *
00007  * See http://www.asterisk.org for more information about
00008  * the Asterisk project. Please do not directly contact
00009  * any of the maintainers of this project for assistance;
00010  * the project provides a web site, mailing lists and IRC
00011  * channels for your use.
00012  *
00013  * This program is free software, distributed under the terms of
00014  * the GNU General Public License Version 2. See the LICENSE file
00015  * at the top of the source tree.
00016  */
00017 
00018 /*! \file
00019  *
00020  * \brief RAW SLINEAR Formats
00021  * \ingroup formats
00022  */
00023 
00024 /*** MODULEINFO
00025    <support_level>core</support_level>
00026  ***/
00027  
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 364580 $")
00031 
00032 #include "asterisk/mod_format.h"
00033 #include "asterisk/module.h"
00034 #include "asterisk/endian.h"
00035 
00036 static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size, enum ast_format_id id)
00037 {
00038    int res;
00039    /* Send a frame from the file to the appropriate channel */
00040 
00041    s->fr.frametype = AST_FRAME_VOICE;
00042    ast_format_set(&s->fr.subclass.format, id, 0);
00043    s->fr.mallocd = 0;
00044    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, buf_size);
00045    if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
00046       if (res)
00047          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00048       return NULL;
00049    }
00050    *whennext = s->fr.samples = res/2;
00051    s->fr.datalen = res;
00052    return &s->fr;
00053 }
00054 
00055 static int generic_write(struct ast_filestream *fs, struct ast_frame *f, enum ast_format_id id)
00056 {
00057    int res;
00058    if (f->frametype != AST_FRAME_VOICE) {
00059       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00060       return -1;
00061    }
00062    if (f->subclass.format.id != id) {
00063       ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format));
00064       return -1;
00065    }
00066    if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
00067          ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00068          return -1;
00069    }
00070    return 0;
00071 }
00072 
00073 static int slinear_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00074 {
00075    off_t offset=0, min = 0, cur, max;
00076 
00077    sample_offset <<= 1;
00078 
00079    if ((cur = ftello(fs->f)) < 0) {
00080       ast_log(AST_LOG_WARNING, "Unable to determine current position in sln filestream %p: %s\n", fs, strerror(errno));
00081       return -1;
00082    }
00083 
00084    if (fseeko(fs->f, 0, SEEK_END) < 0) {
00085       ast_log(AST_LOG_WARNING, "Unable to seek to end of sln filestream %p: %s\n", fs, strerror(errno));
00086       return -1;
00087    }
00088 
00089    if ((max = ftello(fs->f)) < 0) {
00090       ast_log(AST_LOG_WARNING, "Unable to determine max position in sln filestream %p: %s\n", fs, strerror(errno));
00091       return -1;
00092    }
00093 
00094    if (whence == SEEK_SET)
00095       offset = sample_offset;
00096    else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00097       offset = sample_offset + cur;
00098    else if (whence == SEEK_END)
00099       offset = max - sample_offset;
00100    if (whence != SEEK_FORCECUR) {
00101       offset = (offset > max)?max:offset;
00102    }
00103    /* always protect against seeking past begining. */
00104    offset = (offset < min)?min:offset;
00105    return fseeko(fs->f, offset, SEEK_SET);
00106 }
00107 
00108 static int slinear_trunc(struct ast_filestream *fs)
00109 {
00110    int fd;
00111    off_t cur;
00112 
00113    if ((fd = fileno(fs->f)) < 0) {
00114       ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for sln filestream %p: %s\n", fs, strerror(errno));
00115       return -1;
00116    }
00117    if ((cur = ftello(fs->f)) < 0) {
00118       ast_log(AST_LOG_WARNING, "Unable to determine current position in sln filestream %p: %s\n", fs, strerror(errno));
00119       return -1;
00120    }
00121    /* Truncate file to current length */
00122    return ftruncate(fd, cur);
00123 }
00124 
00125 static off_t slinear_tell(struct ast_filestream *fs)
00126 {
00127    return ftello(fs->f) / 2;
00128 }
00129 
00130 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR);}
00131 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320, AST_FORMAT_SLINEAR);}
00132 static struct ast_format_def slin_f = {
00133    .name = "sln",
00134    .exts = "sln|raw",
00135    .write = slinear_write,
00136    .seek = slinear_seek,
00137    .trunc = slinear_trunc,
00138    .tell = slinear_tell,
00139    .read = slinear_read,
00140    .buf_size = 320 + AST_FRIENDLY_OFFSET,
00141 };
00142 
00143 static int slinear12_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR12);}
00144 static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480, AST_FORMAT_SLINEAR12);}
00145 static struct ast_format_def slin12_f = {
00146    .name = "sln12",
00147    .exts = "sln12",
00148    .write = slinear12_write,
00149    .seek = slinear_seek,
00150    .trunc = slinear_trunc,
00151    .tell = slinear_tell,
00152    .read = slinear12_read,
00153    .buf_size = 480 + AST_FRIENDLY_OFFSET,
00154 };
00155 
00156 static int slinear16_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR16);}
00157 static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640, AST_FORMAT_SLINEAR16);}
00158 static struct ast_format_def slin16_f = {
00159    .name = "sln16",
00160    .exts = "sln16",
00161    .write = slinear16_write,
00162    .seek = slinear_seek,
00163    .trunc = slinear_trunc,
00164    .tell = slinear_tell,
00165    .read = slinear16_read,
00166    .buf_size = 640 + AST_FRIENDLY_OFFSET,
00167 };
00168 
00169 static int slinear24_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR24);}
00170 static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960, AST_FORMAT_SLINEAR24);}
00171 static struct ast_format_def slin24_f = {
00172    .name = "sln24",
00173    .exts = "sln24",
00174    .write = slinear24_write,
00175    .seek = slinear_seek,
00176    .trunc = slinear_trunc,
00177    .tell = slinear_tell,
00178    .read = slinear24_read,
00179    .buf_size = 960 + AST_FRIENDLY_OFFSET,
00180 };
00181 
00182 static int slinear32_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR32);}
00183 static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280, AST_FORMAT_SLINEAR32);}
00184 static struct ast_format_def slin32_f = {
00185    .name = "sln32",
00186    .exts = "sln32",
00187    .write = slinear32_write,
00188    .seek = slinear_seek,
00189    .trunc = slinear_trunc,
00190    .tell = slinear_tell,
00191    .read = slinear32_read,
00192    .buf_size = 1280 + AST_FRIENDLY_OFFSET,
00193 };
00194 
00195 static int slinear44_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR44);}
00196 static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764, AST_FORMAT_SLINEAR44);}
00197 static struct ast_format_def slin44_f = {
00198    .name = "sln44",
00199    .exts = "sln44",
00200    .write = slinear44_write,
00201    .seek = slinear_seek,
00202    .trunc = slinear_trunc,
00203    .tell = slinear_tell,
00204    .read = slinear44_read,
00205    .buf_size = 1764 + AST_FRIENDLY_OFFSET,
00206 };
00207 
00208 static int slinear48_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR48);}
00209 static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920, AST_FORMAT_SLINEAR48);}
00210 static struct ast_format_def slin48_f = {
00211    .name = "sln48",
00212    .exts = "sln48",
00213    .write = slinear48_write,
00214    .seek = slinear_seek,
00215    .trunc = slinear_trunc,
00216    .tell = slinear_tell,
00217    .read = slinear48_read,
00218    .buf_size = 1920 + AST_FRIENDLY_OFFSET,
00219 };
00220 
00221 static int slinear96_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR96);}
00222 static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840, AST_FORMAT_SLINEAR96);}
00223 static struct ast_format_def slin96_f = {
00224    .name = "sln96",
00225    .exts = "sln96",
00226    .write = slinear96_write,
00227    .seek = slinear_seek,
00228    .trunc = slinear_trunc,
00229    .tell = slinear_tell,
00230    .read = slinear96_read,
00231    .buf_size = 3840 + AST_FRIENDLY_OFFSET,
00232 };
00233 
00234 static int slinear192_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR192);}
00235 static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680, AST_FORMAT_SLINEAR192);}
00236 static struct ast_format_def slin192_f = {
00237    .name = "sln192",
00238    .exts = "sln192",
00239    .write = slinear192_write,
00240    .seek = slinear_seek,
00241    .trunc = slinear_trunc,
00242    .tell = slinear_tell,
00243    .read = slinear192_read,
00244    .buf_size = 7680 + AST_FRIENDLY_OFFSET,
00245 };
00246 
00247 static struct ast_format_def *slin_list[] = {
00248    &slin_f,
00249    &slin12_f,
00250    &slin16_f,
00251    &slin24_f,
00252    &slin32_f,
00253    &slin44_f,
00254    &slin48_f,
00255    &slin96_f,
00256    &slin192_f,
00257 };
00258 
00259 static int load_module(void)
00260 {
00261    int i;
00262    ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0);
00263    ast_format_set(&slin12_f.format, AST_FORMAT_SLINEAR12, 0);
00264    ast_format_set(&slin16_f.format, AST_FORMAT_SLINEAR16, 0);
00265    ast_format_set(&slin24_f.format, AST_FORMAT_SLINEAR24, 0);
00266    ast_format_set(&slin32_f.format, AST_FORMAT_SLINEAR32, 0);
00267    ast_format_set(&slin44_f.format, AST_FORMAT_SLINEAR44, 0);
00268    ast_format_set(&slin48_f.format, AST_FORMAT_SLINEAR48, 0);
00269    ast_format_set(&slin96_f.format, AST_FORMAT_SLINEAR96, 0);
00270    ast_format_set(&slin192_f.format, AST_FORMAT_SLINEAR192, 0);
00271 
00272    for (i = 0; i < ARRAY_LEN(slin_list); i++) {
00273       if (ast_format_def_register(slin_list[i])) {
00274          return AST_MODULE_LOAD_FAILURE;
00275       }
00276    }
00277 
00278    return AST_MODULE_LOAD_SUCCESS;
00279 }
00280 
00281 static int unload_module(void)
00282 {
00283    int res = 0;
00284    int i = 0;
00285 
00286    for (i = 0; i < ARRAY_LEN(slin_list); i++) {
00287       if (ast_format_def_unregister(slin_list[i]->name)) {
00288          res |= AST_MODULE_LOAD_FAILURE;
00289       }
00290    }
00291    return res;
00292 }
00293 
00294 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear Audio support (SLN) 8khz-192khz",
00295    .load = load_module,
00296    .unload = unload_module,
00297    .load_pri = AST_MODPRI_APP_DEPEND
00298 );