2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Save to raw, headerless G729 data.
22 * \note This is not an encoder/decoder. The codec fo g729 is only
23 * available with a commercial license from Digium, due to patent
24 * restrictions. Check http://www.digium.com for information.
25 * \arg Extensions: g729
31 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
33 #include "asterisk/mod_format.h"
34 #include "asterisk/module.h"
35 #include "asterisk/endian.h"
37 /* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
39 /* Portions of the conversion code are by guido@sienanet.it */
41 #define BUF_SIZE 20 /* two G729 frames */
42 #define G729A_SAMPLES 160
44 static struct ast_frame
*g729_read(struct ast_filestream
*s
, int *whennext
)
47 /* Send a frame from the file to the appropriate channel */
48 s
->fr
.frametype
= AST_FRAME_VOICE
;
49 s
->fr
.subclass
= AST_FORMAT_G729A
;
51 s
->fr
.samples
= G729A_SAMPLES
;
52 AST_FRAME_SET_BUFFER(&s
->fr
, s
->buf
, AST_FRIENDLY_OFFSET
, BUF_SIZE
);
53 if ((res
= fread(s
->fr
.data
.ptr
, 1, s
->fr
.datalen
, s
->f
)) != s
->fr
.datalen
) {
54 if (res
&& (res
!= 10)) /* XXX what for ? */
55 ast_log(LOG_WARNING
, "Short read (%d) (%s)!\n", res
, strerror(errno
));
58 *whennext
= s
->fr
.samples
;
62 static int g729_write(struct ast_filestream
*fs
, struct ast_frame
*f
)
65 if (f
->frametype
!= AST_FRAME_VOICE
) {
66 ast_log(LOG_WARNING
, "Asked to write non-voice frame!\n");
69 if (f
->subclass
!= AST_FORMAT_G729A
) {
70 ast_log(LOG_WARNING
, "Asked to write non-G729 frame (%d)!\n", f
->subclass
);
73 if (f
->datalen
% 10) {
74 ast_log(LOG_WARNING
, "Invalid data length, %d, should be multiple of 10\n", f
->datalen
);
77 if ((res
= fwrite(f
->data
.ptr
, 1, f
->datalen
, fs
->f
)) != f
->datalen
) {
78 ast_log(LOG_WARNING
, "Bad write (%d/10): %s\n", res
, strerror(errno
));
84 static int g729_seek(struct ast_filestream
*fs
, off_t sample_offset
, int whence
)
87 off_t min
,cur
,max
,offset
=0;
90 fseeko(fs
->f
, 0, SEEK_END
);
93 bytes
= BUF_SIZE
* (sample_offset
/ G729A_SAMPLES
);
94 if (whence
== SEEK_SET
)
96 else if (whence
== SEEK_CUR
|| whence
== SEEK_FORCECUR
)
98 else if (whence
== SEEK_END
)
100 if (whence
!= SEEK_FORCECUR
) {
101 offset
= (offset
> max
)?max
:offset
;
103 /* protect against seeking beyond begining. */
104 offset
= (offset
< min
)?min
:offset
;
105 if (fseeko(fs
->f
, offset
, SEEK_SET
) < 0)
110 static int g729_trunc(struct ast_filestream
*fs
)
112 /* Truncate file to current length */
113 if (ftruncate(fileno(fs
->f
), ftello(fs
->f
)) < 0)
118 static off_t
g729_tell(struct ast_filestream
*fs
)
120 off_t offset
= ftello(fs
->f
);
121 return (offset
/BUF_SIZE
)*G729A_SAMPLES
;
124 static const struct ast_format g729_f
= {
127 .format
= AST_FORMAT_G729A
,
133 .buf_size
= BUF_SIZE
+ AST_FRIENDLY_OFFSET
,
136 static int load_module(void)
138 if (ast_format_register(&g729_f
))
139 return AST_MODULE_LOAD_FAILURE
;
140 return AST_MODULE_LOAD_SUCCESS
;
143 static int unload_module(void)
145 return ast_format_unregister(g729_f
.name
);
148 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Raw G729 data");