source: roaraudio/roard/codecfilter_vorbis.c @ 598:4c78782357f8

Last change on this file since 598:4c78782357f8 was 598:4c78782357f8, checked in by phi, 16 years ago

let codecfilter_vorbis.c use vio for writeing

File size: 8.0 KB
RevLine 
[204]1//codecfilter_vorbis.c:
2
3#include "roard.h"
4
[362]5#ifdef ROAR_HAVE_LIBVORBISFILE
6
[205]7int cf_vorbis_open(CODECFILTER_USERDATA_T * inst, int codec,
8                                            struct roar_stream_server * info,
9                                            struct roar_codecfilter   * filter) {
10 struct codecfilter_vorbis_inst * self = malloc(sizeof(struct codecfilter_vorbis_inst));
[569]11 struct roar_stream * s = ROAR_STREAM(info);
[205]12
13 if ( !self )
14  return -1;
15
16 self->current_section      = -1;
17 self->last_section         = -1;
[382]18 self->opened               =  0;
19 self->got_it_running       =  0;
[205]20 self->stream               = info;
21// self->outlen               = ROAR_OUTPUT_BUFFER_SAMPLES * s->info.channels * s->info.bits / 8; // optimal size
[569]22#ifdef ROAR_HAVE_LIBVORBISENC
23 self->encoding             = 0;
24#endif
[205]25
[486]26 ROAR_DBG("cf_vorbis_open(*): info->id=%i", ROAR_STREAM(info)->id);
27
[569]28 if ( (self->in = fdopen(s->fh, "r")) == NULL ) {
[205]29  free((void*)self);
30  return -1;
31 }
32
33 *inst = (CODECFILTER_USERDATA_T) self;
34
[569]35 s->info.codec = ROAR_CODEC_DEFAULT;
36 s->info.bits  = 16;
37
38 if ( s->dir == ROAR_DIR_PLAY ) {
39  return 0;
40 } else if ( s->dir == ROAR_DIR_MONITOR ) {
41#ifdef ROAR_HAVE_LIBVORBISENC
42  // set up the encoder here
43
44  memset(&(self->encoder), 0, sizeof(self->encoder));
45
46  self->encoding = 1;
47
48  vorbis_info_init(&(self->encoder.vi));
49  vorbis_comment_init(&(self->encoder.vc));
50  vorbis_comment_add_tag(&(self->encoder.vc), "SERVER", "RoarAudio");
51  vorbis_comment_add_tag(&(self->encoder.vc), "ENCODER", "RoarAudio Vorbis codecfilter");
52
53  if( vorbis_encode_init_vbr(&(self->encoder.vi), (long) s->info.channels, (long) s->info.rate,
54                                                  self->encoder.v_base_quality) != 0 ) {
55   ROAR_ERR("cf_vorbis_open(*): Can not vorbis_encode_init_vbr(*)!");
56   vorbis_info_clear(&(self->encoder.vi)); // TODO: do we need to free vc also?
57   free(self);
58   return -1;
59  }
60
61  vorbis_analysis_init(&(self->encoder.vd), &(self->encoder.vi));
62  vorbis_block_init(&(self->encoder.vd), &(self->encoder.vb));
63
64                                     //  "RA"<<16 + PID<<8 + Stream ID
65  ogg_stream_init(&(self->encoder.os), 0x52410000 + ((getpid() & 0xff)<<8) + s->id);
66
67#else
68 free(self);
69 return -1;
70#endif
71 } else {
72  free(self);
73  return -1;
74 }
[206]75
76 return 0;
[205]77}
78
79int cf_vorbis_close(CODECFILTER_USERDATA_T   inst) {
80 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
81
82 if ( !inst )
83  return -1;
84
[382]85 if ( self->got_it_running )
86  ov_clear(&(self->vf));
[205]87
[569]88#ifdef ROAR_HAVE_LIBVORBISENC
89 if ( self->encoding ) {
90  ogg_stream_clear(&(self->encoder.os));
91  vorbis_block_clear(&(self->encoder.vb));
92  vorbis_dsp_clear(&(self->encoder.vd));
93  vorbis_info_clear(&(self->encoder.vi));
94 }
95#endif
96
[205]97 free(inst);
[206]98 return 0;
[205]99}
100
[582]101int cf_vorbis_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
102#ifdef ROAR_HAVE_LIBVORBISENC
103 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
104 struct roar_stream * s = ROAR_STREAM(self->stream);
105 ogg_packet header;
106 ogg_packet header_comm;
107 ogg_packet header_code;
[586]108 float ** encbuf;
109 int i, c;
110 int chans;
111 int end;
112 int16_t * data = (int16_t *) buf;
[582]113
[584]114 if ( ! self->opened ) {
[582]115  vorbis_analysis_headerout(&(self->encoder.vd), &(self->encoder.vc), &header, &header_comm, &header_code);
116
117  ogg_stream_packetin(&(self->encoder.os), &header);
118  ogg_stream_packetin(&(self->encoder.os), &header_comm);
119  ogg_stream_packetin(&(self->encoder.os), &header_code);
120
121  while (ogg_stream_flush(&(self->encoder.os), &(self->encoder.og))) {
[598]122   if ( stream_vio_s_write(self->stream, self->encoder.og.header, self->encoder.og.header_len)
123                                                                 != self->encoder.og.header_len ||
124        stream_vio_s_write(self->stream, self->encoder.og.body,   self->encoder.og.body_len  )
125                                                                 != self->encoder.og.body_len     ) {
[582]126    free(self); // TODO: do we need addional cleanup?
127    return -1;
128   }
129  }
[584]130  self->opened = 1;
[586]131 } else {
132  encbuf = vorbis_analysis_buffer(&(self->encoder.vd), len /* TODO: need to lookup the menaing of this */);
133  chans  = s->info.channels;
134  end    = len/(2*chans);
135
136  if ( chans == 1 ) { // use optimized code
137   for (i = 0; i < end; i++)
138    encbuf[0][i] = data[i]/32768.0;
139
140  } else if ( chans == 2 ) { // use optimized code
141   for (i = 0; i < end; i++) {
142    encbuf[0][i] = data[2*i  ]/32768.0;
143    encbuf[1][i] = data[2*i+1]/32768.0;
144   }
145  } else { // use generic multi channel code
146   for (i = 0; i < end; i++) {
147    for (c = 0; c < chans; c++) {
148     encbuf[c][i] = data[chans*i+c]/32768.0;
149    }
150   }
151  }
[587]152
153  vorbis_analysis_wrote(&(self->encoder.vd), i);
154
155  while ( vorbis_analysis_blockout(&(self->encoder.vd), &(self->encoder.vb)) == 1 ) {
156   vorbis_analysis(&(self->encoder.vb), &(self->encoder.op));
157   vorbis_bitrate_addblock(&(self->encoder.vb));
158
159   while ( vorbis_bitrate_flushpacket(&(self->encoder.vd), &(self->encoder.op)) ) {
160    ogg_stream_packetin(&(self->encoder.os), &(self->encoder.op));
161
162    while( ogg_stream_pageout(&(self->encoder.os), &(self->encoder.og)) ) {
[598]163     stream_vio_s_write(self->stream, self->encoder.og.header, self->encoder.og.header_len);
164     stream_vio_s_write(self->stream, self->encoder.og.body,   self->encoder.og.body_len  );
[587]165    }
166   }
167  }
[584]168 }
[582]169
170  return len; // we assume every thing was written (at least into our dsp anaylises buffer
171#else
172 errno = ENOSYS;
173 return -1;
174#endif
175}
[205]176int cf_vorbis_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
177 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
178 long r;
[206]179 long todo = len;
180 long done = 0;
[205]181
[206]182// printf("cf_vorbis_read(inst=%p, buf=%p, len=%i) = ?\n", inst, buf, len);
183
184 self->opened++;
185 if ( self->opened == 16 ) {
186  //printf("cf_vorbis_read(*): opening...\n");
[205]187  if ( ov_open(self->in, &(self->vf), NULL, 0) < 0 ) {
[382]188//   free((void*)self);
[206]189   return 0;
[205]190  }
191 }
[206]192
193 if ( self->opened < 16 ) {
[541]194  errno = EAGAIN;
[206]195  return -1;
196 }
[205]197
[382]198
199 self->got_it_running = 1;
200
[206]201 while (todo) {
202  r = ov_read(&(self->vf), buf+done, todo, 0, 2, 1, &(self->current_section));
203  if ( r < 1 ) {
204   break;
205  } else {
[207]206   if ( self->last_section != self->current_section )
207    if ( cf_vorbis_update_stream(self) == -1 )
208     return 0;
209
210   self->last_section = self->current_section;
[206]211   todo -= r;
212   done += r;
213  }
214 }
[205]215
[206]216 //printf("ov_read(*) = %i\n", done);
217
218 if ( done == 0 ) {
[205]219  // do some EOF handling...
[206]220  return 0;
[205]221 } else {
[206]222  return len;
[205]223 }
224}
225
[207]226int cf_vorbis_update_stream (struct codecfilter_vorbis_inst * self) {
227 vorbis_info *vi = ov_info(&(self->vf), -1);
228 char **ptr = ov_comment(&(self->vf), -1)->user_comments;
229 char key[80] = {0}, value[80] = {0};
[583]230 struct roar_stream * s = ROAR_STREAM(self->stream);
[207]231 int type;
232 int j, h = 0;
[222]233 float rpg_track = 0, rpg_album = 0;
[207]234
235 s->info.channels = vi->channels;
236 s->info.rate     = vi->rate;
237 s->info.bits     = 16;
238 s->info.codec    = ROAR_CODEC_DEFAULT;
239
240 stream_meta_clear(s->id);
241
242 while(*ptr){
243   for (j = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++)
244    key[j] = (*ptr)[j];
245    key[j] = 0;
246
247   for (j++, h = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++)
248    value[h++] = (*ptr)[j];
249    value[h]   = 0;
250
251   type = roar_meta_inttype(key);
252   if ( type != -1 )
253    stream_meta_set(s->id, type, "", value);
254
255   ROAR_DBG("cf_vorbis_update_stream(*): Meta %-16s: %s", key, value);
[222]256
257   if ( strcmp(key, "REPLAYGAIN_TRACK_PEAK") == 0 ) {
258    rpg_track = 1/atof(value);
259/*
260   } else if ( strcmp(key, "REPLAYGAIN_TRACK_GAIN") == 0 ) {
261    rpg_track = powf(10, atof(value)/20);
262*/
263   } else if ( strcmp(key, "REPLAYGAIN_ALBUM_PEAK") == 0 ) {
264    rpg_album = 1/atof(value);
265/*
266   } else if ( strcmp(key, "REPLAYGAIN_ALBUM_GAIN") == 0 ) {
267    rpg_album = powf(10, atof(value)/20);
268*/
269   }
270
[207]271   ++ptr;
272 }
273
[222]274 if ( rpg_album ) {
275  self->stream->mixer.rpg_div = 2718;  // = int(exp(1)*1000)
276  self->stream->mixer.rpg_mul = (float)rpg_album*2718;
277 } else if ( rpg_track ) {
278  self->stream->mixer.rpg_div = 2718;
279  self->stream->mixer.rpg_mul = (float)rpg_track*2718;
280 }
281
[223]282 //printf("RPG: mul=%i, div=%i\n", self->stream->mixer.rpg_mul, self->stream->mixer.rpg_div);
[207]283 return 0;
284}
285
[362]286#endif
287
[204]288//ll
Note: See TracBrowser for help on using the repository browser.