2 * Asterisk -- An open source telephony toolkit.
4 * Brian K. West <brian@bkw.org>
6 * Copyright (C) 1999 - 2005, Digium, Inc.
8 * Mark Spencer <markster@digium.com>
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
23 * \brief Save to raw, headerless iLBC data.
24 * \arg File name extension: ilbc
30 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
32 #include "asterisk/mod_format.h"
33 #include "asterisk/module.h"
34 #include "asterisk/endian.h"
36 /* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
38 /* Portions of the conversion code are by guido@sienanet.it */
40 #define ILBC_BUF_SIZE 50 /* One Real iLBC Frame */
41 #define ILBC_SAMPLES 240
43 static struct ast_frame
*ilbc_read(struct ast_filestream
*s
, int *whennext
)
46 /* Send a frame from the file to the appropriate channel */
47 s
->fr
.frametype
= AST_FRAME_VOICE
;
48 s
->fr
.subclass
= AST_FORMAT_ILBC
;
50 AST_FRAME_SET_BUFFER(&s
->fr
, s
->buf
, AST_FRIENDLY_OFFSET
, ILBC_BUF_SIZE
);
51 if ((res
= fread(s
->fr
.data
.ptr
, 1, s
->fr
.datalen
, s
->f
)) != s
->fr
.datalen
) {
53 ast_log(LOG_WARNING
, "Short read (%d) (%s)!\n", res
, strerror(errno
));
56 *whennext
= s
->fr
.samples
= ILBC_SAMPLES
;
60 static int ilbc_write(struct ast_filestream
*fs
, struct ast_frame
*f
)
63 if (f
->frametype
!= AST_FRAME_VOICE
) {
64 ast_log(LOG_WARNING
, "Asked to write non-voice frame!\n");
67 if (f
->subclass
!= AST_FORMAT_ILBC
) {
68 ast_log(LOG_WARNING
, "Asked to write non-iLBC frame (%d)!\n", f
->subclass
);
71 if (f
->datalen
% 50) {
72 ast_log(LOG_WARNING
, "Invalid data length, %d, should be multiple of 50\n", f
->datalen
);
75 if ((res
= fwrite(f
->data
.ptr
, 1, f
->datalen
, fs
->f
)) != f
->datalen
) {
76 ast_log(LOG_WARNING
, "Bad write (%d/50): %s\n", res
, strerror(errno
));
82 static int ilbc_seek(struct ast_filestream
*fs
, off_t sample_offset
, int whence
)
85 off_t min
,cur
,max
,offset
=0;
88 fseeko(fs
->f
, 0, SEEK_END
);
91 bytes
= ILBC_BUF_SIZE
* (sample_offset
/ ILBC_SAMPLES
);
92 if (whence
== SEEK_SET
)
94 else if (whence
== SEEK_CUR
|| whence
== SEEK_FORCECUR
)
96 else if (whence
== SEEK_END
)
98 if (whence
!= SEEK_FORCECUR
) {
99 offset
= (offset
> max
)?max
:offset
;
101 /* protect against seeking beyond begining. */
102 offset
= (offset
< min
)?min
:offset
;
103 if (fseeko(fs
->f
, offset
, SEEK_SET
) < 0)
108 static int ilbc_trunc(struct ast_filestream
*fs
)
110 /* Truncate file to current length */
111 if (ftruncate(fileno(fs
->f
), ftello(fs
->f
)) < 0)
116 static off_t
ilbc_tell(struct ast_filestream
*fs
)
118 off_t offset
= ftello(fs
->f
);
119 return (offset
/ILBC_BUF_SIZE
)*ILBC_SAMPLES
;
122 static const struct ast_format ilbc_f
= {
125 .format
= AST_FORMAT_ILBC
,
131 .buf_size
= ILBC_BUF_SIZE
+ AST_FRIENDLY_OFFSET
,
134 static int load_module(void)
136 if (ast_format_register(&ilbc_f
))
137 return AST_MODULE_LOAD_FAILURE
;
138 return AST_MODULE_LOAD_SUCCESS
;
141 static int unload_module(void)
143 return ast_format_unregister(ilbc_f
.name
);
146 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Raw iLBC data");