comparison src/vorbis/vorbis.c @ 2329:7b38e28464ee

Modified the playback loop to fix the last seconds skip (fixes bug #87) The time won't refresh durnig those few seconds, so it still needs some work...
author Cristi Magherusan <majeru@atheme.org>
date Sat, 19 Jan 2008 03:04:39 +0200
parents a13b8f308dce
children db02ad480056
comparison
equal deleted inserted replaced
2328:224727e6c73d 2329:7b38e28464ee
1 /* 1 /*
2 * Copyright (C) Tony Arcieri <bascule@inferno.tusculum.edu> 2 * Copyright (C) Tony Arcieri <bascule@inferno.tusculum.edu>
3 * Copyright (C) 2001-2002 Haavard Kvaalen <havardk@xmms.org> 3 * Copyright (C) 2001-2002 Haavard Kvaalen <havardk@xmms.org>
4 * Copyright (C) 2007 William Pitcock <nenolod@sacredspiral.co.uk> 4 * Copyright (C) 2007 William Pitcock <nenolod@sacredspiral.co.uk>
5 * Copyright (C) 2008 Cristi Măgherușan <majeru@gentoo.ro>
5 * 6 *
6 * ReplayGain processing Copyright (C) 2002 Gian-Carlo Pascutto <gcp@sjeng.org> 7 * ReplayGain processing Copyright (C) 2002 Gian-Carlo Pascutto <gcp@sjeng.org>
7 * 8 *
8 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
228 seekneeded = -1; 229 seekneeded = -1;
229 playback->eof = FALSE; 230 playback->eof = FALSE;
230 } 231 }
231 } 232 }
232 233
233 static int
234 vorbis_process_data(InputPlayback *playback, int last_section,
235 gboolean use_rg, float rg_scale)
236 {
237 char pcmout[4096];
238 int bytes;
239 float **pcm;
240
241 /*
242 * A vorbis physical bitstream may consist of many logical
243 * sections (information for each of which may be fetched from
244 * the vf structure). This value is filled in by ov_read to
245 * alert us what section we're currently decoding in case we
246 * need to change playback settings at a section boundary
247 */
248 int current_section = last_section;
249
250 g_mutex_lock(vf_mutex);
251 if (use_rg) {
252 bytes =
253 ov_read_float(&vf, &pcm, sizeof(pcmout) / 2 / channels,
254 &current_section);
255 if (bytes > 0)
256 bytes = vorbis_process_replaygain(pcm, bytes, channels,
257 pcmout, rg_scale);
258 }
259 else {
260 bytes = ov_read(&vf, pcmout, sizeof(pcmout),
261 (int) (G_BYTE_ORDER == G_BIG_ENDIAN),
262 2, 1, &current_section);
263 }
264
265 /*
266 * We got some sort of error. Bail.
267 */
268 if (bytes <= 0 && bytes != OV_HOLE) {
269 g_mutex_unlock(vf_mutex);
270 playback->playing = 0;
271 playback->output->buffer_free();
272 playback->output->buffer_free();
273 playback->eof = TRUE;
274 return last_section;
275 }
276
277 if (current_section != last_section) {
278 /*
279 * The info struct is different in each section. vf
280 * holds them all for the given bitstream. This
281 * requests the current one
282 */
283 vorbis_info *vi = ov_info(&vf, -1);
284
285 if (vi->channels > 2) {
286 playback->eof = TRUE;
287 g_mutex_unlock(vf_mutex);
288 return current_section;
289 }
290
291
292 if (vi->rate != samplerate || vi->channels != channels) {
293 samplerate = vi->rate;
294 channels = vi->channels;
295 playback->output->buffer_free();
296 playback->output->buffer_free();
297 playback->output->close_audio();
298 if (!playback->output->
299 open_audio(FMT_S16_NE, vi->rate, vi->channels)) {
300 playback->error = TRUE;
301 playback->eof = TRUE;
302 g_mutex_unlock(vf_mutex);
303 return current_section;
304 }
305 playback->output->flush(ov_time_tell(&vf) * 1000);
306 }
307 }
308
309 g_mutex_unlock(vf_mutex);
310
311 playback->pass_audio(playback, FMT_S16_NE, channels, bytes, pcmout, &playback->playing);
312
313 if (!playback->playing)
314 return current_section;
315
316 if (seekneeded != -1)
317 do_seek(playback);
318
319 return current_section;
320 }
321
322 static gpointer 234 static gpointer
323 vorbis_play_loop(gpointer arg) 235 vorbis_play_loop(gpointer arg)
324 { 236 {
325 InputPlayback *playback = arg; 237 InputPlayback *playback = arg;
326 char *filename = playback->filename; 238 char *filename = playback->filename;
348 260
349 fd = g_new0(VFSVorbisFile, 1); 261 fd = g_new0(VFSVorbisFile, 1);
350 fd->fd = stream; 262 fd->fd = stream;
351 datasource = (void *) fd; 263 datasource = (void *) fd;
352 264
265 char pcmout[4096];
266 int bytes;
267 float **pcm;
268
353 /* 269 /*
354 * The open function performs full stream detection and 270 * The open function performs full stream detection and
355 * machine initialization. None of the rest of ov_xx() works 271 * machine initialization. None of the rest of ov_xx() works
356 * without it 272 * without it
273 *
274 * A vorbis physical bitstream may consist of many logical
275 * sections (information for each of which may be fetched from
276 * the vf structure). This value is filled in by ov_read to
277 * alert us what section we're currently decoding in case we
278 * need to change playback settings at a section boundary
357 */ 279 */
358 280
281
359 g_mutex_lock(vf_mutex); 282 g_mutex_lock(vf_mutex);
360 if (ov_open_callbacks(datasource, &vf, NULL, 0, aud_vfs_is_streaming(fd->fd) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { 283 if (ov_open_callbacks(datasource, &vf, NULL, 0, aud_vfs_is_streaming(fd->fd) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) {
361 vorbis_callbacks.close_func(datasource); 284 vorbis_callbacks.close_func(datasource);
362 g_mutex_unlock(vf_mutex); 285 g_mutex_unlock(vf_mutex);
363 playback->eof = TRUE; 286 playback->eof = TRUE;
401 * You can fetch the information for any section of the file 324 * You can fetch the information for any section of the file
402 * using the ov_ interface. 325 * using the ov_ interface.
403 */ 326 */
404 327
405 while (playback->playing) { 328 while (playback->playing) {
406 int current_section; 329
407
408 if (seekneeded != -1)
409 do_seek(playback);
410
411 if (playback->eof) { 330 if (playback->eof) {
412 g_usleep(20000); 331 g_usleep(20000);
413 continue; 332 continue;
414 } 333 }
415 334
416 current_section = vorbis_process_data(playback, last_section, 335 if (seekneeded != -1)
417 use_rg, rg_scale); 336 do_seek(playback);
418 337
419 if (current_section != last_section) { 338
339 int current_section = last_section;
340
341 g_mutex_lock(vf_mutex);
342 if (use_rg) {
343 bytes =
344 ov_read_float(&vf, &pcm, sizeof(pcmout) / 2 / channels,
345 &current_section);
346 if (bytes > 0)
347 bytes = vorbis_process_replaygain(pcm, bytes, channels,
348 pcmout, rg_scale);
349 }
350 else {
351 bytes = ov_read(&vf, pcmout, sizeof(pcmout),
352 (int) (G_BYTE_ORDER == G_BIG_ENDIAN),
353 2, 1, &current_section);
354 }
355
356 /*
357 * We got some sort of error. Bail.
358 */
359 if (bytes <= 0 && bytes != OV_HOLE) {
360 /*
361 * EOF
362 */
363 playback->playing = 0;
364 playback->output->buffer_free();
365 playback->output->buffer_free();
366 playback->eof = TRUE;
367 current_section = last_section;
368 }
369
370
371
372 if (current_section <= last_section) {
420 /* 373 /*
421 * set total play time, bitrate, rate, and channels of 374 * The info struct is different in each section. vf
422 * current section 375 * holds them all for the given bitstream. This
376 * requests the current one
423 */ 377 */
424 if (title) 378 vorbis_info *vi = ov_info(&vf, -1);
425 g_free(title); 379
426 380 if (vi->channels > 2) {
427 g_mutex_lock(vf_mutex); 381 playback->eof = TRUE;
428 title = vorbis_generate_title(&vf, filename); 382 g_mutex_unlock(vf_mutex);
429 use_rg = vorbis_update_replaygain(&rg_scale); 383 goto stop_processing;
430 384 }
431 if (time != -1) 385
432 time = ov_time_total(&vf, -1) * 1000; 386
433 387 if (vi->rate != samplerate || vi->channels != channels) {
434 g_mutex_unlock(vf_mutex); 388 samplerate = vi->rate;
435 389 channels = vi->channels;
436 playback->set_params(playback, title, time, br, samplerate, channels); 390 playback->output->buffer_free();
437 timercount = playback->output->output_time(); 391 playback->output->buffer_free();
438 392 playback->output->close_audio();
439 last_section = current_section; 393 if (!playback->output->
394 open_audio(FMT_S16_NE, vi->rate, vi->channels)) {
395 playback->error = TRUE;
396 playback->eof = TRUE;
397 g_mutex_unlock(vf_mutex);
398 goto stop_processing;
399 }
400 playback->output->flush(ov_time_tell(&vf) * 1000);
401 }
440 } 402 }
441 } 403
442 if (!playback->error) 404 g_mutex_unlock(vf_mutex);
443 playback->output->close_audio(); 405
406 playback->pass_audio(playback, FMT_S16_NE, channels, bytes, pcmout, &playback->playing);
407
408 if (!playback->playing)
409 goto stop_processing;
410
411 if (seekneeded != -1)
412 do_seek(playback);
413
414 stop_processing:
415
416 if (current_section <= last_section) {
417 /*
418 * set total play time, bitrate, rate, and channels of
419 * current section
420 */
421 if (title)
422 g_free(title);
423
424 g_mutex_lock(vf_mutex);
425 title = vorbis_generate_title(&vf, filename);
426 use_rg = vorbis_update_replaygain(&rg_scale);
427
428 if (time != -1)
429 time = ov_time_total(&vf, -1) * 1000;
430
431 g_mutex_unlock(vf_mutex);
432
433 playback->set_params(playback, title, time, br, samplerate, channels);
434
435 timercount = playback->output->output_time();
436
437 last_section = current_section;
438
439 }
440 }
441
442
443
444 if (!playback->error)
445 playback->output->close_audio();
444 /* fall through intentional */ 446 /* fall through intentional */
445 447
446 play_cleanup: 448 /*this loop makes it not skip the last ~4 seconds, but the playback
447 g_free(title); 449 * timer isn't updated in this period, so it still needs a bit of work
448 450 *
449 /* 451 * majeru
450 * ov_clear closes the stream if its open. Safe to call on an
451 * uninitialized structure as long as we've zeroed it
452 */ 452 */
453 while(playback->output->buffer_playing()&& playback->output->buffer_free())
454 g_usleep(50000);
455
456
457 play_cleanup:
458 g_free(title);
459
460 /*
461 * ov_clear closes the stream if its open. Safe to call on an
462 * uninitialized structure as long as we've zeroed it
463 */
453 g_mutex_lock(vf_mutex); 464 g_mutex_lock(vf_mutex);
454 ov_clear(&vf); 465 ov_clear(&vf);
455 g_mutex_unlock(vf_mutex); 466 g_mutex_unlock(vf_mutex);
456 playback->playing = 0; 467 playback->playing = 0;
468 playback->output->buffer_free();
457 return NULL; 469 return NULL;
458 } 470 }
459 471
460 static void 472 static void
461 vorbis_play(InputPlayback *playback) 473 vorbis_play(InputPlayback *playback)
884 gint ret = 0; 896 gint ret = 0;
885 897
886 if (handle->probe == FALSE) 898 if (handle->probe == FALSE)
887 { 899 {
888 ret = aud_vfs_fclose(handle->fd); 900 ret = aud_vfs_fclose(handle->fd);
889 // g_free(handle); // it causes double free. i'm not really sure that commenting out at here is correct. --yaz 901 /* g_free(handle); it causes double free. i'm not really sure that commenting out at here is correct. --yaz*/
890 } 902 }
891 903
892 return ret; 904 return ret;
893 } 905 }
894 906