1 /********************************************************************
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. *
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/ *
12 ********************************************************************
14 last mod: $Id: oggvorbis_format.c,v 1.13 2003/06/24 12:34:40 giles Exp $
16 ********************************************************************/
27 #include <vorbis/codec.h>
28 #include <vorbis/vorbisfile.h>
29 #include "transport.h"
31 #include "vorbis_comments.h"
36 typedef struct ovf_private_t
{
42 int bos
; /* At beginning of logical bitstream */
44 decoder_stats_t stats
;
47 /* Forward declarations */
48 format_t oggvorbis_format
;
49 ov_callbacks vorbisfile_callbacks
;
52 void print_vorbis_stream_info (decoder_t
*decoder
);
53 void print_vorbis_comments (vorbis_comment
*vc
, decoder_callbacks_t
*cb
,
57 /* ----------------------------------------------------------- */
60 int ovf_can_decode (data_source_t
*source
)
62 return 1; /* The file transport is tested last, so always try it */
66 decoder_t
* ovf_init (data_source_t
*source
, ogg123_options_t
*ogg123_opts
,
67 audio_format_t
*audio_fmt
,
68 decoder_callbacks_t
*callbacks
, void *callback_arg
)
71 ovf_private_t
*private;
75 /* Allocate data source structures */
76 decoder
= malloc(sizeof(decoder_t
));
77 private = malloc(sizeof(ovf_private_t
));
79 if (decoder
!= NULL
&& private != NULL
) {
80 decoder
->source
= source
;
81 decoder
->actual_fmt
= decoder
->request_fmt
= *audio_fmt
;
82 decoder
->format
= &oggvorbis_format
;
83 decoder
->callbacks
= callbacks
;
84 decoder
->callback_arg
= callback_arg
;
85 decoder
->private = private;
88 private->current_section
= -1;
90 private->stats
.total_time
= 0.0;
91 private->stats
.current_time
= 0.0;
92 private->stats
.instant_bitrate
= 0;
93 private->stats
.avg_bitrate
= 0;
95 fprintf(stderr
, _("Error: Out of memory.\n"));
99 /* Initialize vorbisfile decoder */
101 ret
= ov_open_callbacks (decoder
, &private->vf
, NULL
, 0,
102 vorbisfile_callbacks
);
106 /* free(source); nope. caller frees. */
114 int ovf_read (decoder_t
*decoder
, void *ptr
, int nbytes
, int *eos
,
115 audio_format_t
*audio_fmt
)
117 ovf_private_t
*priv
= decoder
->private;
118 decoder_callbacks_t
*cb
= decoder
->callbacks
;
123 /* Read comments and audio info at the start of a logical bitstream */
125 priv
->vc
= ov_comment(&priv
->vf
, -1);
126 priv
->vi
= ov_info(&priv
->vf
, -1);
128 decoder
->actual_fmt
.rate
= priv
->vi
->rate
;
129 decoder
->actual_fmt
.channels
= priv
->vi
->channels
;
132 print_vorbis_stream_info(decoder
);
133 print_vorbis_comments(priv
->vc
, cb
, decoder
->callback_arg
);
137 *audio_fmt
= decoder
->actual_fmt
;
139 /* Attempt to read as much audio as is requested */
140 while (nbytes
>= audio_fmt
->word_size
* audio_fmt
->channels
) {
142 old_section
= priv
->current_section
;
143 ret
= ov_read(&priv
->vf
, ptr
, nbytes
, audio_fmt
->big_endian
,
144 audio_fmt
->word_size
, audio_fmt
->signed_sample
,
145 &priv
->current_section
);
153 } else if (ret
== OV_HOLE
) {
155 if (cb
->printf_error
!= NULL
)
156 cb
->printf_error(decoder
->callback_arg
, INFO
,
157 _("--- Hole in the stream; probably harmless\n"));
159 } else if (ret
< 0) {
161 if (cb
->printf_error
!= NULL
)
162 cb
->printf_error(decoder
->callback_arg
, ERROR
,
163 _("=== Vorbis library reported a stream error.\n"));
171 ptr
= (void *)((unsigned char *)ptr
+ ret
);
174 /* did we enter a new logical bitstream? */
175 if (old_section
!= priv
->current_section
&& old_section
!= -1) {
178 priv
->bos
= 1; /* Read new headers next time through */
189 int ovf_seek (decoder_t
*decoder
, double offset
, int whence
)
191 ovf_private_t
*priv
= decoder
->private;
195 if (whence
== DECODER_SEEK_CUR
) {
196 cur
= ov_time_tell(&priv
->vf
);
203 ret
= ov_time_seek(&priv
->vf
, offset
);
211 decoder_stats_t
*ovf_statistics (decoder_t
*decoder
)
213 ovf_private_t
*priv
= decoder
->private;
214 long instant_bitrate
;
217 /* ov_time_tell() doesn't work on non-seekable streams, so we use
219 priv
->stats
.total_time
= (double) ov_pcm_total(&priv
->vf
, -1) /
220 (double) decoder
->actual_fmt
.rate
;
221 priv
->stats
.current_time
= (double) ov_pcm_tell(&priv
->vf
) /
222 (double) decoder
->actual_fmt
.rate
;
224 /* vorbisfile returns 0 when no bitrate change has occurred */
225 instant_bitrate
= ov_bitrate_instant(&priv
->vf
);
226 if (instant_bitrate
> 0)
227 priv
->stats
.instant_bitrate
= instant_bitrate
;
229 avg_bitrate
= ov_bitrate(&priv
->vf
, priv
->current_section
);
230 /* Catch error case caused by non-seekable stream */
231 priv
->stats
.avg_bitrate
= avg_bitrate
> 0 ? avg_bitrate
: 0;
234 return malloc_decoder_stats(&priv
->stats
);
238 void ovf_cleanup (decoder_t
*decoder
)
240 ovf_private_t
*priv
= decoder
->private;
244 free(decoder
->private);
249 format_t oggvorbis_format
= {
260 /* ------------------- Vorbisfile Callbacks ----------------- */
262 size_t vorbisfile_cb_read (void *ptr
, size_t size
, size_t nmemb
, void *arg
)
264 decoder_t
*decoder
= arg
;
266 return decoder
->source
->transport
->read(decoder
->source
, ptr
, size
, nmemb
);
269 int vorbisfile_cb_seek (void *arg
, ogg_int64_t offset
, int whence
)
271 decoder_t
*decoder
= arg
;
273 return decoder
->source
->transport
->seek(decoder
->source
, offset
, whence
);
276 int vorbisfile_cb_close (void *arg
)
278 return 1; /* Ignore close request so transport can be closed later */
281 long vorbisfile_cb_tell (void *arg
)
283 decoder_t
*decoder
= arg
;
285 return decoder
->source
->transport
->tell(decoder
->source
);
289 ov_callbacks vorbisfile_callbacks
= {
292 &vorbisfile_cb_close
,
297 /* ------------------- Private functions -------------------- */
300 void print_vorbis_stream_info (decoder_t
*decoder
)
302 ovf_private_t
*priv
= decoder
->private;
303 decoder_callbacks_t
*cb
= decoder
->callbacks
;
306 if (cb
== NULL
|| cb
->printf_metadata
== NULL
)
309 cb
->printf_metadata(decoder
->callback_arg
, 2,
310 _("Ogg Vorbis stream: %d channel, %ld Hz"),
314 cb
->printf_metadata(decoder
->callback_arg
, 3,
315 _("Vorbis format: Version %d"),
318 cb
->printf_metadata(decoder
->callback_arg
, 3,
319 _("Bitrate hints: upper=%ld nominal=%ld lower=%ld "
321 priv
->vi
->bitrate_upper
,
322 priv
->vi
->bitrate_nominal
,
323 priv
->vi
->bitrate_lower
,
324 priv
->vi
->bitrate_window
);
326 cb
->printf_metadata(decoder
->callback_arg
, 3,
327 _("Encoded by: %s"), priv
->vc
->vendor
);
330 void print_vorbis_comments (vorbis_comment
*vc
, decoder_callbacks_t
*cb
,
337 for (i
= 0; i
< vc
->comments
; i
++) {
339 /* Gotta null terminate these things */
340 if (temp_len
< vc
->comment_lengths
[i
] + 1) {
341 temp_len
= vc
->comment_lengths
[i
] + 1;
342 temp
= realloc(temp
, sizeof(char) * temp_len
);
345 strncpy(temp
, vc
->user_comments
[i
], vc
->comment_lengths
[i
]);
346 temp
[vc
->comment_lengths
[i
]] = '\0';
348 print_vorbis_comment(temp
, cb
, callback_arg
);