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$")
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
41 #include "asterisk/lock.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/file.h"
44 #include "asterisk/logger.h"
45 #include "asterisk/sched.h"
46 #include "asterisk/module.h"
47 #include "asterisk/endian.h"
49 /* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
51 /* Portions of the conversion code are by guido@sienanet.it */
53 #define ILBC_BUF_SIZE 50 /* One Real iLBC Frame */
54 #define ILBC_SAMPLES 240
56 static struct ast_frame
*ilbc_read(struct ast_filestream
*s
, int *whennext
)
59 /* Send a frame from the file to the appropriate channel */
60 s
->fr
.frametype
= AST_FRAME_VOICE
;
61 s
->fr
.subclass
= AST_FORMAT_ILBC
;
63 AST_FRAME_SET_BUFFER(&s
->fr
, s
->buf
, AST_FRIENDLY_OFFSET
, ILBC_BUF_SIZE
);
64 if ((res
= fread(s
->fr
.data
, 1, s
->fr
.datalen
, s
->f
)) != s
->fr
.datalen
) {
66 ast_log(LOG_WARNING
, "Short read (%d) (%s)!\n", res
, strerror(errno
));
69 *whennext
= s
->fr
.samples
= ILBC_SAMPLES
;
73 static int ilbc_write(struct ast_filestream
*fs
, struct ast_frame
*f
)
76 if (f
->frametype
!= AST_FRAME_VOICE
) {
77 ast_log(LOG_WARNING
, "Asked to write non-voice frame!\n");
80 if (f
->subclass
!= AST_FORMAT_ILBC
) {
81 ast_log(LOG_WARNING
, "Asked to write non-iLBC frame (%d)!\n", f
->subclass
);
84 if (f
->datalen
% 50) {
85 ast_log(LOG_WARNING
, "Invalid data length, %d, should be multiple of 50\n", f
->datalen
);
88 if ((res
= fwrite(f
->data
, 1, f
->datalen
, fs
->f
)) != f
->datalen
) {
89 ast_log(LOG_WARNING
, "Bad write (%d/50): %s\n", res
, strerror(errno
));
95 static int ilbc_seek(struct ast_filestream
*fs
, off_t sample_offset
, int whence
)
98 off_t min
,cur
,max
,offset
=0;
101 fseeko(fs
->f
, 0, SEEK_END
);
104 bytes
= ILBC_BUF_SIZE
* (sample_offset
/ ILBC_SAMPLES
);
105 if (whence
== SEEK_SET
)
107 else if (whence
== SEEK_CUR
|| whence
== SEEK_FORCECUR
)
108 offset
= cur
+ bytes
;
109 else if (whence
== SEEK_END
)
110 offset
= max
- bytes
;
111 if (whence
!= SEEK_FORCECUR
) {
112 offset
= (offset
> max
)?max
:offset
;
114 /* protect against seeking beyond begining. */
115 offset
= (offset
< min
)?min
:offset
;
116 if (fseeko(fs
->f
, offset
, SEEK_SET
) < 0)
121 static int ilbc_trunc(struct ast_filestream
*fs
)
123 /* Truncate file to current length */
124 if (ftruncate(fileno(fs
->f
), ftello(fs
->f
)) < 0)
129 static off_t
ilbc_tell(struct ast_filestream
*fs
)
131 off_t offset
= ftello(fs
->f
);
132 return (offset
/ILBC_BUF_SIZE
)*ILBC_SAMPLES
;
135 static const struct ast_format ilbc_f
= {
138 .format
= AST_FORMAT_ILBC
,
144 .buf_size
= ILBC_BUF_SIZE
+ AST_FRIENDLY_OFFSET
,
147 static int load_module(void)
149 return ast_format_register(&ilbc_f
);
152 static int unload_module(void)
154 return ast_format_unregister(ilbc_f
.name
);
157 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Raw iLBC data");