source: roaraudio/roard/codecfilter_celt.c @ 638:f7cdb2c9bb59

Last change on this file since 638:f7cdb2c9bb59 was 638:f7cdb2c9bb59, checked in by phi, 16 years ago

in error case we should cancel playback as errors may/will result in buffer overflow!

File size: 5.9 KB
Line 
1//codecfilter_celt.c:
2
3#include "roard.h"
4#ifdef ROAR_HAVE_LIBCELT
5
6int cf_celt_open(CODECFILTER_USERDATA_T * inst, int codec,
7                                            struct roar_stream_server * info,
8                                            struct roar_codecfilter   * filter) {
9 struct codecfilter_celt_inst * self = malloc(sizeof(struct codecfilter_celt_inst));
10 struct roar_stream * s = ROAR_STREAM(info);
11
12 if ( !self )
13  return -1;
14
15/*
16 CELTMode * mode;
17 CELTEncoder * encoder;
18 CELTDecoder * decoder;
19 int frame_size;
20 int lookahead;
21 int out_size;
22 char * ibuf;
23 char * obuf;
24 char * rest;
25 int s_buf;
26 int f_rest; /-* how much is in rest? *-/
27*/
28
29 self->stream               = info;
30 self->frame_size           = 256;
31 self->lookahead            = self->frame_size;
32 self->encoder              = NULL;
33 self->decoder              = NULL;
34 self->opened               = 0;
35 self->s_buf                = s->info.channels * self->frame_size * 2;
36 self->ibuf                 = malloc(self->s_buf);
37 self->obuf                 = malloc(self->s_buf);
38 self->i_rest               = malloc(self->s_buf);
39 self->o_rest               = malloc(self->s_buf);
40 self->fi_rest              = 0;
41 self->fo_rest              = 0;
42
43 if ( !(self->ibuf && self->obuf && self->i_rest && self->o_rest) ) {
44  if ( self->ibuf )
45   free(self->ibuf);
46
47  if ( self->obuf )
48   free(self->obuf);
49
50  if ( self->i_rest )
51   free(self->o_rest);
52
53  if ( self->o_rest )
54   free(self->o_rest);
55
56  free(self);
57  return -1;
58 }
59 
60 self->mode                 = celt_mode_create(s->info.rate, s->info.channels, self->frame_size, NULL);
61
62 if ( !self->mode ) {
63  free(self);
64  return -1;
65 }
66
67 if ( s->dir == ROAR_DIR_PLAY ) {
68   self->decoder = celt_decoder_create(self->mode);
69 } else if ( s->dir == ROAR_DIR_MONITOR || s->dir == ROAR_DIR_OUTPUT ) {
70   self->encoder = celt_encoder_create(self->mode);
71 } else {
72  celt_mode_destroy(self->mode);
73  free(self);
74  return -1;
75 }
76
77 *inst = (CODECFILTER_USERDATA_T) self;
78
79 s->info.codec = ROAR_CODEC_DEFAULT;
80 s->info.bits  = 16; // CELT hardcoded
81
82 return 0;
83}
84
85int cf_celt_close(CODECFILTER_USERDATA_T   inst) {
86 struct codecfilter_celt_inst * self = (struct codecfilter_celt_inst *) inst;
87
88 if ( !inst )
89  return -1;
90
91 if ( self->encoder )
92 celt_encoder_destroy(self->encoder);
93
94 if ( self->decoder )
95 celt_decoder_destroy(self->decoder);
96
97 if ( self->mode )
98  celt_mode_destroy(self->mode);
99
100 if ( self->ibuf )
101  free(self->ibuf);
102
103 if ( self->obuf )
104  free(self->obuf);
105
106 if ( self->i_rest )
107  free(self->i_rest);
108
109 if ( self->o_rest )
110  free(self->o_rest);
111
112 free(inst);
113 return 0;
114}
115
116int cf_celt_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
117 struct codecfilter_celt_inst * self = (struct codecfilter_celt_inst *) inst;
118 int r = 0;
119 uint16_t fs;
120 char * cbuf;
121 char magic[ROAR_CELT_MAGIC_LEN];
122
123// printf("buf=%p, len=%i\n", buf, len);
124
125 if ( !self->opened ) {
126  errno = ENOSYS;
127  if ( stream_vio_s_read(self->stream, magic, ROAR_CELT_MAGIC_LEN) != ROAR_CELT_MAGIC_LEN )
128   return -1;
129  if ( memcmp(magic, ROAR_CELT_MAGIC, ROAR_CELT_MAGIC_LEN) != 0 )
130   return -1;
131
132  errno = 0;
133  self->opened = 1;
134 }
135
136 if ( self->fi_rest ) {
137  memcpy(buf, self->i_rest, self->fi_rest);
138  r += self->fi_rest;
139  self->fi_rest = 0;
140 }
141
142 while ( r <= (len - self->s_buf) ) {
143  if ( stream_vio_s_read(self->stream, &fs, 2) != 2 )
144   break;
145
146  fs = ROAR_NET2HOST16(fs);
147
148  if ( fs > self->s_buf )
149   return -1;
150
151  if ( stream_vio_s_read(self->stream, self->ibuf, fs) != fs )
152   return -1;
153
154  cbuf = buf + r;
155
156//  printf("buf=%p, r=%i // cbuf=%p\n", buf, r, cbuf);
157  if ( celt_decode(self->decoder, (unsigned char *) self->ibuf, fs, (celt_int16_t *) cbuf) < 0 )
158   return -1;
159
160  r += self->s_buf;
161 }
162
163 if ( r < len ) {
164//  printf("r < len!\n");
165  if ( stream_vio_s_read(self->stream, &fs, 2) == 2 ) {
166   fs = ROAR_NET2HOST16(fs);
167//   printf("next: fs=%i\n", fs);
168   if ( fs > self->s_buf )
169    return -1;
170   if ( stream_vio_s_read(self->stream, self->ibuf, fs) == fs ) {
171//    printf("got data!\n");
172    if ( celt_decode(self->decoder, (unsigned char *) self->ibuf, fs, (celt_int16_t *) self->obuf) >= 0 ) {
173//     printf("{ // decode rest\n");
174//     printf(" r=%i // need %i Bytes\n", r, len - r);
175//     printf(" memcpy(buf+%i, self->obuf, %i) = ?\n", r, len - r);
176     memcpy(buf+r, self->obuf, len - r);
177     self->fi_rest = self->s_buf + r - len;
178     memcpy(self->i_rest, self->obuf + len - r, self->fi_rest);
179//     printf(" len=%i, r=%i, fi_rest=%i, s_buf=%i\n", len, r, self->fi_rest, self->s_buf);
180     r = len;
181//     printf("}\n");
182    }
183   }
184  }
185 }
186
187 ROAR_DBG("cf_celt_read(inst=%p, buf=%p, len=%i) = %i", inst, buf, len, r);
188 return r;
189}
190
191#define BS (ROAR_STREAM(self->stream)->info.channels * 64)
192int cf_celt_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
193 struct codecfilter_celt_inst * self = (struct codecfilter_celt_inst *) inst;
194 int have = 0;
195 int org_len = len;
196 int diff;
197 int fs2 = self->frame_size * 2 * ROAR_STREAM(self->stream)->info.channels;
198 uint16_t pkglen_net, pkglen;
199 unsigned char cbits[BS+2];
200
201 if ( (self->fo_rest + len) > fs2 ) {
202  if ( self->fo_rest ) {
203   memcpy(self->obuf, self->o_rest, self->fo_rest);
204   have = self->fo_rest;
205   self->fo_rest = 0;
206  }
207
208  memcpy(self->obuf+have, buf, (diff=fs2-have));
209  buf += diff;
210  len -= diff;
211
212  pkglen     = celt_encode(self->encoder, (celt_int16_t *) self->obuf, cbits+2, BS);
213  pkglen_net = ROAR_HOST2NET16(pkglen);
214  *(uint16_t*)cbits = pkglen_net;
215
216  if ( stream_vio_s_write(self->stream, cbits, pkglen+2) == -1 )
217   return -1;
218
219  while (len >= fs2) {
220   pkglen     = celt_encode(self->encoder, (celt_int16_t *) buf, cbits+2, BS);
221   pkglen_net = ROAR_HOST2NET16(pkglen);
222   *(uint16_t*)cbits = pkglen_net;
223
224   if ( stream_vio_s_write(self->stream, cbits, pkglen+2) == -1 )
225    return -1;
226   len -= fs2;
227   buf += fs2;
228  }
229 }
230
231 if ( len ) {
232  memcpy(self->o_rest + self->fo_rest, buf, len);
233  self->fo_rest += len;
234  len            = 0;
235 }
236
237 return org_len;
238}
239
240#endif
241//ll
Note: See TracBrowser for help on using the repository browser.