comparison decoders/ogg.c @ 433:f1c16afd9ebe

Read until buffer is full in Sound_Decode() rather than one packet per call.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 21 Dec 2002 11:32:14 +0000
parents cbb15ecf423a
children 30f96c853462
comparison
equal deleted inserted replaced
432:ddce7101673e 433:f1c16afd9ebe
236 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private; 236 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
237 ov_clear(vf); 237 ov_clear(vf);
238 free(vf); 238 free(vf);
239 } /* OGG_close */ 239 } /* OGG_close */
240 240
241 241 /* Note: According to the Vorbis documentation:
242 * "ov_read() will decode at most one vorbis packet per invocation,
243 * so the value returned will generally be less than length."
244 * Due to this, for buffer sizes like 16384, SDL_Sound was always getting
245 * an underfilled buffer and always setting the EAGAIN flag.
246 * Since the SDL_Sound API implies that the entire buffer
247 * should be filled unless EOF, additional code has been added
248 * to this function to call ov_read() until the buffer is filled.
249 * However, there may still be some corner cases where the buffer
250 * cannot be entirely filled. So be aware.
251 */
242 static Uint32 OGG_read(Sound_Sample *sample) 252 static Uint32 OGG_read(Sound_Sample *sample)
243 { 253 {
244 int rc; 254 int rc;
245 int bitstream; 255 int bitstream;
246 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 256 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
247 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private; 257 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
248 258
249 rc = ov_read(vf, internal->buffer, internal->buffer_size, 259 rc = ov_read(vf, internal->buffer, internal->buffer_size,
250 ((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */ 260 ((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */
251 ((sample->actual.format & 0xFF) / 8), /* bytes per sample point */ 261 ((sample->actual.format & 0xFF) / 8), /* bytes per sample point */
252 ((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */ 262 ((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */
253 &bitstream); 263 &bitstream);
254 264
255 /* Make sure the read went smoothly... */ 265 /* Make sure the read went smoothly... */
256 if (rc == 0) 266 if (rc == 0)
257 sample->flags |= SOUND_SAMPLEFLAG_EOF; 267 sample->flags |= SOUND_SAMPLEFLAG_EOF;
258 268
259 else if (rc < 0) 269 else if (rc < 0)
260 sample->flags |= SOUND_SAMPLEFLAG_ERROR; 270 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
261 271
262 /* (next call this EAGAIN may turn into an EOF or error.) */ 272 /* If the buffer isn't filled, keep trying to fill it
273 * until no more data can be grabbed */
263 else if ((Uint32) rc < internal->buffer_size) 274 else if ((Uint32) rc < internal->buffer_size)
264 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN; 275 {
276 /* Creating a pointer to the buffer that denotes where to start
277 * writing new data. */
278 Uint8* buffer_start_point = NULL;
279 int total_bytes_read = rc;
280 int bytes_remaining = internal->buffer_size - rc;
281
282 /* Keep grabbing data until something prevents
283 * us from getting more. (Could be EOF,
284 * packets are too large to fit in remaining
285 * space, or an error.)
286 */
287 while( (rc > 0) && (bytes_remaining > 0) )
288 {
289 /* Set buffer pointer to end of last write */
290 /* All the messiness is to get rid of the warning for
291 * dereferencing a void*
292 */
293 buffer_start_point = &(((Uint8*)internal->buffer)[total_bytes_read]);
294 rc = ov_read(vf, buffer_start_point, bytes_remaining,
295 ((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */
296 ((sample->actual.format & 0xFF) / 8), /* bytes per sample point */
297 ((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */
298 &bitstream);
299 /* Make sure rc > 0 because we don't accidently want
300 * to change the counters if there was an error
301 */
302 if(rc > 0)
303 {
304 total_bytes_read += rc;
305 bytes_remaining = bytes_remaining - rc;
306 }
307 }
308 /* I think the minimum read size is 2, though I'm
309 * not sure about this. (I've hit cases where I
310 * couldn't read less than 4.) What I don't want to do is
311 * accidently claim we hit EOF when the reason rc == 0
312 * is because the requested amount of data was smaller
313 * than the minimum packet size.
314 * For now, I will be conservative
315 * and not set the EOF flag, and let the next call to
316 * this function figure it out.
317 * I think the ERROR flag is safe to set because
318 * it looks like OGG simply returns 0 if the
319 * read size is too small.
320 * And in most cases for sensible buffer sizes,
321 * this fix will fill the buffer,
322 * so we can set the EAGAIN flag without worrying
323 * that it will always be set.
324 */
325 if(rc < 0)
326 {
327 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
328 }
329 else if(rc == 0)
330 {
331 /* Do nothing for now until there is a better solution */
332 /* sample->flags |= SOUND_SAMPLEFLAG_EOF; */
333 }
334
335 /* Test for a buffer underrun. It should occur less frequently
336 * now, but it still may happen and not necessarily mean
337 * anything useful. */
338 if ((Uint32) total_bytes_read < internal->buffer_size)
339 {
340 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
341 }
342 /* change rc to the total bytes read so function
343 * can return the correct value.
344 */
345 rc = total_bytes_read;
346 }
265 347
266 return((Uint32) rc); 348 return((Uint32) rc);
267 } /* OGG_read */ 349 } /* OGG_read */
268 350
269 351