source: roaraudio/roard/codecfilter_vorbis.c @ 569:b35e761f50f4

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

adding a lot thingss in preperation to encode vorbis :)

File size: 6.1 KB
Line 
1//codecfilter_vorbis.c:
2
3#include "roard.h"
4
5#ifdef ROAR_HAVE_LIBVORBISFILE
6
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));
11 struct roar_stream * s = ROAR_STREAM(info);
12 ogg_packet header;
13 ogg_packet header_comm;
14 ogg_packet header_code;
15
16 if ( !self )
17  return -1;
18
19 self->current_section      = -1;
20 self->last_section         = -1;
21 self->opened               =  0;
22 self->got_it_running       =  0;
23 self->stream               = info;
24// self->outlen               = ROAR_OUTPUT_BUFFER_SAMPLES * s->info.channels * s->info.bits / 8; // optimal size
25#ifdef ROAR_HAVE_LIBVORBISENC
26 self->encoding             = 0;
27#endif
28
29 ROAR_DBG("cf_vorbis_open(*): info->id=%i", ROAR_STREAM(info)->id);
30
31 if ( (self->in = fdopen(s->fh, "r")) == NULL ) {
32  free((void*)self);
33  return -1;
34 }
35
36 *inst = (CODECFILTER_USERDATA_T) self;
37
38 s->info.codec = ROAR_CODEC_DEFAULT;
39 s->info.bits  = 16;
40
41 if ( s->dir == ROAR_DIR_PLAY ) {
42  return 0;
43 } else if ( s->dir == ROAR_DIR_MONITOR ) {
44#ifdef ROAR_HAVE_LIBVORBISENC
45  // set up the encoder here
46
47  memset(&(self->encoder), 0, sizeof(self->encoder));
48
49  self->encoding = 1;
50
51  vorbis_info_init(&(self->encoder.vi));
52  vorbis_comment_init(&(self->encoder.vc));
53  vorbis_comment_add_tag(&(self->encoder.vc), "SERVER", "RoarAudio");
54  vorbis_comment_add_tag(&(self->encoder.vc), "ENCODER", "RoarAudio Vorbis codecfilter");
55
56  if( vorbis_encode_init_vbr(&(self->encoder.vi), (long) s->info.channels, (long) s->info.rate,
57                                                  self->encoder.v_base_quality) != 0 ) {
58   ROAR_ERR("cf_vorbis_open(*): Can not vorbis_encode_init_vbr(*)!");
59   vorbis_info_clear(&(self->encoder.vi)); // TODO: do we need to free vc also?
60   free(self);
61   return -1;
62  }
63
64  vorbis_analysis_init(&(self->encoder.vd), &(self->encoder.vi));
65  vorbis_block_init(&(self->encoder.vd), &(self->encoder.vb));
66
67                                     //  "RA"<<16 + PID<<8 + Stream ID
68  ogg_stream_init(&(self->encoder.os), 0x52410000 + ((getpid() & 0xff)<<8) + s->id);
69
70  vorbis_analysis_headerout(&(self->encoder.vd), &(self->encoder.vc), &header, &header_comm, &header_code);
71
72  ogg_stream_packetin(&(self->encoder.os), &header);
73  ogg_stream_packetin(&(self->encoder.os), &header_comm);
74  ogg_stream_packetin(&(self->encoder.os), &header_code);
75
76  while (ogg_stream_flush(&(self->encoder.os), &(self->encoder.og))) {
77   if ( write(s->fh, self->encoder.og.header, self->encoder.og.header_len) != self->encoder.og.header_len ||
78        write(s->fh, self->encoder.og.body,   self->encoder.og.body_len  ) != self->encoder.og.body_len     ) {
79    free(self); // TODO: do we need adtional cleanup?
80    return -1;
81   }
82  }
83
84#else
85 free(self);
86 return -1;
87#endif
88 } else {
89  free(self);
90  return -1;
91 }
92
93 return 0;
94}
95
96int cf_vorbis_close(CODECFILTER_USERDATA_T   inst) {
97 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
98
99 if ( !inst )
100  return -1;
101
102 if ( self->got_it_running )
103  ov_clear(&(self->vf));
104
105#ifdef ROAR_HAVE_LIBVORBISENC
106 if ( self->encoding ) {
107  ogg_stream_clear(&(self->encoder.os));
108  vorbis_block_clear(&(self->encoder.vb));
109  vorbis_dsp_clear(&(self->encoder.vd));
110  vorbis_info_clear(&(self->encoder.vi));
111 }
112#endif
113
114 free(inst);
115 return 0;
116}
117
118int cf_vorbis_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
119 struct codecfilter_vorbis_inst * self = (struct codecfilter_vorbis_inst *) inst;
120 long r;
121 long todo = len;
122 long done = 0;
123
124// printf("cf_vorbis_read(inst=%p, buf=%p, len=%i) = ?\n", inst, buf, len);
125
126 self->opened++;
127 if ( self->opened == 16 ) {
128  //printf("cf_vorbis_read(*): opening...\n");
129  if ( ov_open(self->in, &(self->vf), NULL, 0) < 0 ) {
130//   free((void*)self);
131   return 0;
132  }
133 }
134
135 if ( self->opened < 16 ) {
136  errno = EAGAIN;
137  return -1;
138 }
139
140
141 self->got_it_running = 1;
142
143 while (todo) {
144  r = ov_read(&(self->vf), buf+done, todo, 0, 2, 1, &(self->current_section));
145  if ( r < 1 ) {
146   break;
147  } else {
148   if ( self->last_section != self->current_section )
149    if ( cf_vorbis_update_stream(self) == -1 )
150     return 0;
151
152   self->last_section = self->current_section;
153   todo -= r;
154   done += r;
155  }
156 }
157
158 //printf("ov_read(*) = %i\n", done);
159
160 if ( done == 0 ) {
161  // do some EOF handling...
162  return 0;
163 } else {
164  return len;
165 }
166}
167
168int cf_vorbis_update_stream (struct codecfilter_vorbis_inst * self) {
169 vorbis_info *vi = ov_info(&(self->vf), -1);
170 char **ptr = ov_comment(&(self->vf), -1)->user_comments;
171 char key[80] = {0}, value[80] = {0};
172 struct roar_stream * s = (struct roar_stream *) self->stream;
173 int type;
174 int j, h = 0;
175 float rpg_track = 0, rpg_album = 0;
176
177 s->info.channels = vi->channels;
178 s->info.rate     = vi->rate;
179 s->info.bits     = 16;
180 s->info.codec    = ROAR_CODEC_DEFAULT;
181
182 stream_meta_clear(s->id);
183
184 while(*ptr){
185   for (j = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++)
186    key[j] = (*ptr)[j];
187    key[j] = 0;
188
189   for (j++, h = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++)
190    value[h++] = (*ptr)[j];
191    value[h]   = 0;
192
193   type = roar_meta_inttype(key);
194   if ( type != -1 )
195    stream_meta_set(s->id, type, "", value);
196
197   ROAR_DBG("cf_vorbis_update_stream(*): Meta %-16s: %s", key, value);
198
199   if ( strcmp(key, "REPLAYGAIN_TRACK_PEAK") == 0 ) {
200    rpg_track = 1/atof(value);
201/*
202   } else if ( strcmp(key, "REPLAYGAIN_TRACK_GAIN") == 0 ) {
203    rpg_track = powf(10, atof(value)/20);
204*/
205   } else if ( strcmp(key, "REPLAYGAIN_ALBUM_PEAK") == 0 ) {
206    rpg_album = 1/atof(value);
207/*
208   } else if ( strcmp(key, "REPLAYGAIN_ALBUM_GAIN") == 0 ) {
209    rpg_album = powf(10, atof(value)/20);
210*/
211   }
212
213   ++ptr;
214 }
215
216 if ( rpg_album ) {
217  self->stream->mixer.rpg_div = 2718;  // = int(exp(1)*1000)
218  self->stream->mixer.rpg_mul = (float)rpg_album*2718;
219 } else if ( rpg_track ) {
220  self->stream->mixer.rpg_div = 2718;
221  self->stream->mixer.rpg_mul = (float)rpg_track*2718;
222 }
223
224 //printf("RPG: mul=%i, div=%i\n", self->stream->mixer.rpg_mul, self->stream->mixer.rpg_div);
225 return 0;
226}
227
228#endif
229
230//ll
Note: See TracBrowser for help on using the repository browser.