Merged revisions 328247 via svnmerge from
[asterisk/asterisk.git] / formats / format_g723.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*! 
20  * \file
21  *
22  * \brief Old-style G.723.1 frame/timestamp format.
23  * 
24  * \arg Extensions: g723, g723sf
25  * \ingroup formats
26  */
27
28 /*** MODULEINFO
29         <support_level>core</support_level>
30  ***/
31  
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/mod_format.h"
37 #include "asterisk/module.h"
38
39 #define G723_MAX_SIZE 1024
40
41 static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext)
42 {
43         unsigned short size;
44         int res;
45         int delay;
46         /* Read the delay for the next packet, and schedule again if necessary */
47         /* XXX is this ignored ? */
48         if (fread(&delay, 1, 4, s->f) == 4) 
49                 delay = ntohl(delay);
50         else
51                 delay = -1;
52         if (fread(&size, 1, 2, s->f) != 2) {
53                 /* Out of data, or the file is no longer valid.  In any case
54                    go ahead and stop the stream */
55                 return NULL;
56         }
57         /* Looks like we have a frame to read from here */
58         size = ntohs(size);
59         if (size > G723_MAX_SIZE) {
60                 ast_log(LOG_WARNING, "Size %d is invalid\n", size);
61                 /* The file is apparently no longer any good, as we
62                    shouldn't ever get frames even close to this 
63                    size.  */
64                 return NULL;
65         }
66         /* Read the data into the buffer */
67         s->fr.frametype = AST_FRAME_VOICE;
68         ast_format_set(&s->fr.subclass.format, AST_FORMAT_G723_1, 0);
69         s->fr.mallocd = 0;
70         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, size);
71         if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != size) {
72                 ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
73                 return NULL;
74         }
75         *whennext = s->fr.samples = 240;
76         return &s->fr;
77 }
78
79 static int g723_write(struct ast_filestream *s, struct ast_frame *f)
80 {
81         uint32_t delay;
82         uint16_t size;
83         int res;
84         /* XXX there used to be a check s->fr means a read stream */
85         if (f->frametype != AST_FRAME_VOICE) {
86                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
87                 return -1;
88         }
89         if (f->subclass.format.id != AST_FORMAT_G723_1) {
90                 ast_log(LOG_WARNING, "Asked to write non-g723 frame!\n");
91                 return -1;
92         }
93         delay = 0;
94         if (f->datalen <= 0) {
95                 ast_log(LOG_WARNING, "Short frame ignored (%d bytes long?)\n", f->datalen);
96                 return 0;
97         }
98         if ((res = fwrite(&delay, 1, 4, s->f)) != 4) {
99                 ast_log(LOG_WARNING, "Unable to write delay: res=%d (%s)\n", res, strerror(errno));
100                 return -1;
101         }
102         size = htons(f->datalen);
103         if ((res = fwrite(&size, 1, 2, s->f)) != 2) {
104                 ast_log(LOG_WARNING, "Unable to write size: res=%d (%s)\n", res, strerror(errno));
105                 return -1;
106         }
107         if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
108                 ast_log(LOG_WARNING, "Unable to write frame: res=%d (%s)\n", res, strerror(errno));
109                 return -1;
110         }       
111         return 0;
112 }
113
114 static int g723_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
115 {
116         return -1;
117 }
118
119 static int g723_trunc(struct ast_filestream *fs)
120 {
121         /* Truncate file to current length */
122         if (ftruncate(fileno(fs->f), ftello(fs->f)) < 0)
123                 return -1;
124         return 0;
125 }
126
127 static off_t g723_tell(struct ast_filestream *fs)
128 {
129         return -1;
130 }
131
132 static struct ast_format_def g723_1_f = {
133         .name = "g723sf",
134         .exts = "g723|g723sf",
135         .write = g723_write,
136         .seek = g723_seek,
137         .trunc = g723_trunc,
138         .tell = g723_tell,
139         .read = g723_read,
140         .buf_size = G723_MAX_SIZE + AST_FRIENDLY_OFFSET,
141 };
142
143 static int load_module(void)
144 {
145         ast_format_set(&g723_1_f.format, AST_FORMAT_G723_1, 0);
146
147         if (ast_format_def_register(&g723_1_f))
148                 return AST_MODULE_LOAD_FAILURE;
149         return AST_MODULE_LOAD_SUCCESS;
150 }
151
152 static int unload_module(void)
153 {
154         return ast_format_def_unregister(g723_1_f.name);
155 }
156
157 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "G.723.1 Simple Timestamp File Format",
158         .load = load_module,
159         .unload = unload_module,
160         .load_pri = AST_MODPRI_APP_DEPEND
161 );