1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7 * *
8 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2003 *
9 * by Stan Seibert <volsung@xiph.org> AND OTHER CONTRIBUTORS *
10 * http://www.xiph.org/ *
11 * *
12 ********************************************************************
13
14 last mod: $Id$
15
16 ********************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <ogg/ogg.h>
27 #include <vorbis/codec.h>
28 #include <vorbis/vorbisfile.h>
29 #include "transport.h"
30 #include "format.h"
31 #include "vorbis_comments.h"
32 #include "utf8.h"
33 #include "i18n.h"
34
35 #ifdef HAVE_OV_READ_FILTER
36 #include "vgfilter.h"
37 #endif
38
39 typedef struct ovf_private_t {
40 OggVorbis_File vf;
41 vorbis_comment *vc;
42 vorbis_info *vi;
43 int current_section;
44
45 int bos; /* At beginning of logical bitstream */
46
47 decoder_stats_t stats;
48 #ifdef HAVE_OV_READ_FILTER
49 vgain_state vg;
50 #endif
51 } ovf_private_t;
52
53 /* Forward declarations */
54 format_t oggvorbis_format;
55 ov_callbacks vorbisfile_callbacks;
56
57
58 void print_vorbis_stream_info (decoder_t *decoder);
59 void print_vorbis_comments (vorbis_comment *vc, decoder_callbacks_t *cb,
60 void *callback_arg);
61
62
63 /* ----------------------------------------------------------- */
64
65
ovf_can_decode(data_source_t * source)66 int ovf_can_decode (data_source_t *source)
67 {
68 return 1; /* The file transport is tested last, so always try it */
69 }
70
71
ovf_init(data_source_t * source,ogg123_options_t * ogg123_opts,audio_format_t * audio_fmt,decoder_callbacks_t * callbacks,void * callback_arg)72 decoder_t* ovf_init (data_source_t *source, ogg123_options_t *ogg123_opts,
73 audio_format_t *audio_fmt,
74 decoder_callbacks_t *callbacks, void *callback_arg)
75 {
76 decoder_t *decoder;
77 ovf_private_t *private;
78 int ret;
79
80
81 /* Allocate data source structures */
82 decoder = malloc(sizeof(decoder_t));
83 private = malloc(sizeof(ovf_private_t));
84
85 if (decoder != NULL && private != NULL) {
86 decoder->source = source;
87 decoder->actual_fmt = decoder->request_fmt = *audio_fmt;
88 decoder->format = &oggvorbis_format;
89 decoder->callbacks = callbacks;
90 decoder->callback_arg = callback_arg;
91 decoder->private = private;
92
93 private->bos = 1;
94 private->current_section = -1;
95
96 private->stats.total_time = 0.0;
97 private->stats.current_time = 0.0;
98 private->stats.instant_bitrate = 0;
99 private->stats.avg_bitrate = 0;
100
101 #ifdef HAVE_OV_READ_FILTER
102 private->vg.scale_factor = 1.0;
103 private->vg.max_scale = 1.0;
104 #endif
105 } else {
106 fprintf(stderr, _("ERROR: Out of memory.\n"));
107 exit(1);
108 }
109
110 /* Initialize vorbisfile decoder */
111
112 ret = ov_open_callbacks (decoder, &private->vf, NULL, 0,
113 vorbisfile_callbacks);
114
115 if (ret < 0) {
116 free(private);
117 /* free(source); nope. caller frees. */
118 return NULL;
119 }
120
121 return decoder;
122 }
123
124
ovf_read(decoder_t * decoder,void * ptr,int nbytes,int * eos,audio_format_t * audio_fmt)125 int ovf_read (decoder_t *decoder, void *ptr, int nbytes, int *eos,
126 audio_format_t *audio_fmt)
127 {
128 ovf_private_t *priv = decoder->private;
129 decoder_callbacks_t *cb = decoder->callbacks;
130 int bytes_read = 0;
131 int ret;
132 int old_section;
133
134 /* Read comments and audio info at the start of a logical bitstream */
135 if (priv->bos) {
136 priv->vc = ov_comment(&priv->vf, -1);
137 priv->vi = ov_info(&priv->vf, -1);
138
139 decoder->actual_fmt.rate = priv->vi->rate;
140 decoder->actual_fmt.channels = priv->vi->channels;
141
142 switch(decoder->actual_fmt.channels){
143 case 1:
144 decoder->actual_fmt.matrix="M";
145 break;
146 case 2:
147 decoder->actual_fmt.matrix="L,R";
148 break;
149 case 3:
150 decoder->actual_fmt.matrix="L,C,R";
151 break;
152 case 4:
153 decoder->actual_fmt.matrix="L,R,BL,BR";
154 break;
155 case 5:
156 decoder->actual_fmt.matrix="L,C,R,BL,BR";
157 break;
158 case 6:
159 decoder->actual_fmt.matrix="L,C,R,BL,BR,LFE";
160 break;
161 case 7:
162 decoder->actual_fmt.matrix="L,C,R,SL,SR,BC,LFE";
163 break;
164 case 8:
165 decoder->actual_fmt.matrix="L,C,R,SL,SR,BL,BR,LFE";
166 break;
167 default:
168 decoder->actual_fmt.matrix=NULL;
169 break;
170 }
171
172 #ifdef HAVE_OV_READ_FILTER
173 vg_init(&priv->vg, priv->vc);
174 #endif
175
176 print_vorbis_stream_info(decoder);
177 print_vorbis_comments(priv->vc, cb, decoder->callback_arg);
178 priv->bos = 0;
179 }
180
181 *audio_fmt = decoder->actual_fmt;
182
183 /* Attempt to read as much audio as is requested */
184 while (nbytes >= audio_fmt->word_size * audio_fmt->channels) {
185
186 old_section = priv->current_section;
187 #ifdef HAVE_OV_READ_FILTER
188 ret = ov_read_filter(&priv->vf, ptr, nbytes, audio_fmt->big_endian,
189 audio_fmt->word_size, audio_fmt->signed_sample,
190 &priv->current_section,
191 vg_filter, &priv->vg);
192 #else
193 ret = ov_read(&priv->vf, ptr, nbytes, audio_fmt->big_endian,
194 audio_fmt->word_size, audio_fmt->signed_sample,
195 &priv->current_section);
196 #endif
197
198 if (ret == 0) {
199
200 /* EOF */
201 *eos = 1;
202 break;
203
204 } else if (ret == OV_HOLE) {
205
206 if (cb->printf_error != NULL)
207 cb->printf_error(decoder->callback_arg, INFO,
208 _("--- Hole in the stream; probably harmless\n"));
209
210 } else if (ret < 0) {
211
212 if (cb->printf_error != NULL)
213 cb->printf_error(decoder->callback_arg, ERROR,
214 _("=== Vorbis library reported a stream error.\n"));
215
216 /* EOF */
217 *eos = 1;
218 break;
219 } else {
220
221 bytes_read += ret;
222 ptr = (void *)((unsigned char *)ptr + ret);
223 nbytes -= ret;
224
225 /* did we enter a new logical bitstream? */
226 if (old_section != priv->current_section && old_section != -1) {
227
228 *eos = 1;
229 priv->bos = 1; /* Read new headers next time through */
230 break;
231 }
232 }
233
234 }
235
236 return bytes_read;
237 }
238
239
ovf_seek(decoder_t * decoder,double offset,int whence)240 int ovf_seek (decoder_t *decoder, double offset, int whence)
241 {
242 ovf_private_t *priv = decoder->private;
243 int ret;
244 double cur;
245
246 if (whence == DECODER_SEEK_CUR) {
247 cur = ov_time_tell(&priv->vf);
248 if (cur >= 0.0)
249 offset += cur;
250 else
251 return 0;
252 }
253
254 ret = ov_time_seek(&priv->vf, offset);
255 if (ret == 0)
256 return 1;
257 else
258 return 0;
259 }
260
261
ovf_statistics(decoder_t * decoder)262 decoder_stats_t *ovf_statistics (decoder_t *decoder)
263 {
264 ovf_private_t *priv = decoder->private;
265 long instant_bitrate;
266 long avg_bitrate;
267
268 /* ov_time_tell() doesn't work on non-seekable streams, so we use
269 ov_pcm_tell() */
270 priv->stats.total_time = (double) ov_pcm_total(&priv->vf, -1) /
271 (double) decoder->actual_fmt.rate;
272 priv->stats.current_time = (double) ov_pcm_tell(&priv->vf) /
273 (double) decoder->actual_fmt.rate;
274
275 /* vorbisfile returns 0 when no bitrate change has occurred */
276 instant_bitrate = ov_bitrate_instant(&priv->vf);
277 if (instant_bitrate > 0)
278 priv->stats.instant_bitrate = instant_bitrate;
279
280 avg_bitrate = ov_bitrate(&priv->vf, priv->current_section);
281 /* Catch error case caused by non-seekable stream */
282 priv->stats.avg_bitrate = avg_bitrate > 0 ? avg_bitrate : 0;
283
284
285 return malloc_decoder_stats(&priv->stats);
286 }
287
288
ovf_cleanup(decoder_t * decoder)289 void ovf_cleanup (decoder_t *decoder)
290 {
291 ovf_private_t *priv = decoder->private;
292
293 ov_clear(&priv->vf);
294
295 free(decoder->private);
296 free(decoder);
297 }
298
299
300 format_t oggvorbis_format = {
301 "oggvorbis",
302 &ovf_can_decode,
303 &ovf_init,
304 &ovf_read,
305 &ovf_seek,
306 &ovf_statistics,
307 &ovf_cleanup,
308 };
309
310
311 /* ------------------- Vorbisfile Callbacks ----------------- */
312
vorbisfile_cb_read(void * ptr,size_t size,size_t nmemb,void * arg)313 size_t vorbisfile_cb_read (void *ptr, size_t size, size_t nmemb, void *arg)
314 {
315 decoder_t *decoder = arg;
316
317 return decoder->source->transport->read(decoder->source, ptr, size, nmemb);
318 }
319
vorbisfile_cb_seek(void * arg,ogg_int64_t offset,int whence)320 int vorbisfile_cb_seek (void *arg, ogg_int64_t offset, int whence)
321 {
322 decoder_t *decoder = arg;
323
324 return decoder->source->transport->seek(decoder->source, offset, whence);
325 }
326
vorbisfile_cb_close(void * arg)327 int vorbisfile_cb_close (void *arg)
328 {
329 return 1; /* Ignore close request so transport can be closed later */
330 }
331
vorbisfile_cb_tell(void * arg)332 long vorbisfile_cb_tell (void *arg)
333 {
334 decoder_t *decoder = arg;
335
336 return decoder->source->transport->tell(decoder->source);
337 }
338
339
340 ov_callbacks vorbisfile_callbacks = {
341 &vorbisfile_cb_read,
342 &vorbisfile_cb_seek,
343 &vorbisfile_cb_close,
344 &vorbisfile_cb_tell
345 };
346
347
348 /* ------------------- Private functions -------------------- */
349
350
print_vorbis_stream_info(decoder_t * decoder)351 void print_vorbis_stream_info (decoder_t *decoder)
352 {
353 ovf_private_t *priv = decoder->private;
354 decoder_callbacks_t *cb = decoder->callbacks;
355
356
357 if (cb == NULL || cb->printf_metadata == NULL)
358 return;
359
360 cb->printf_metadata(decoder->callback_arg, 2,
361 _("Ogg Vorbis stream: %d channel, %ld Hz"),
362 priv->vi->channels,
363 priv->vi->rate);
364
365 cb->printf_metadata(decoder->callback_arg, 3,
366 _("Vorbis format: Version %d"),
367 priv->vi->version);
368
369 cb->printf_metadata(decoder->callback_arg, 3,
370 _("Bitrate hints: upper=%ld nominal=%ld lower=%ld "
371 "window=%ld"),
372 priv->vi->bitrate_upper,
373 priv->vi->bitrate_nominal,
374 priv->vi->bitrate_lower,
375 priv->vi->bitrate_window);
376
377 cb->printf_metadata(decoder->callback_arg, 3,
378 _("Encoded by: %s"), priv->vc->vendor);
379 }
380
print_vorbis_comments(vorbis_comment * vc,decoder_callbacks_t * cb,void * callback_arg)381 void print_vorbis_comments (vorbis_comment *vc, decoder_callbacks_t *cb,
382 void *callback_arg)
383 {
384 int i;
385 char *temp = NULL;
386 int temp_len = 0;
387
388 for (i = 0; i < vc->comments; i++) {
389
390 /* Gotta null terminate these things */
391 if (temp_len < vc->comment_lengths[i] + 1) {
392 temp_len = vc->comment_lengths[i] + 1;
393 temp = realloc(temp, sizeof(char) * temp_len);
394 }
395
396 strncpy(temp, vc->user_comments[i], vc->comment_lengths[i]);
397 temp[vc->comment_lengths[i]] = '\0';
398
399 print_vorbis_comment(temp, cb, callback_arg);
400 }
401
402 free(temp);
403 }
404