Mercurial > audlegacy-plugins
changeset 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 | 224727e6c73d |
children | 5b37a9f2d0cc |
files | src/vorbis/vorbis.c |
diffstat | 1 files changed, 133 insertions(+), 121 deletions(-) [+] |
line wrap: on
line diff
--- a/src/vorbis/vorbis.c Fri Jan 18 18:56:34 2008 +0100 +++ b/src/vorbis/vorbis.c Sat Jan 19 03:04:39 2008 +0200 @@ -2,6 +2,7 @@ * Copyright (C) Tony Arcieri <bascule@inferno.tusculum.edu> * Copyright (C) 2001-2002 Haavard Kvaalen <havardk@xmms.org> * Copyright (C) 2007 William Pitcock <nenolod@sacredspiral.co.uk> + * Copyright (C) 2008 Cristi Măgherușan <majeru@gentoo.ro> * * ReplayGain processing Copyright (C) 2002 Gian-Carlo Pascutto <gcp@sjeng.org> * @@ -230,95 +231,6 @@ } } -static int -vorbis_process_data(InputPlayback *playback, int last_section, - gboolean use_rg, float rg_scale) -{ - char pcmout[4096]; - int bytes; - float **pcm; - - /* - * A vorbis physical bitstream may consist of many logical - * sections (information for each of which may be fetched from - * the vf structure). This value is filled in by ov_read to - * alert us what section we're currently decoding in case we - * need to change playback settings at a section boundary - */ - int current_section = last_section; - - g_mutex_lock(vf_mutex); - if (use_rg) { - bytes = - ov_read_float(&vf, &pcm, sizeof(pcmout) / 2 / channels, - ¤t_section); - if (bytes > 0) - bytes = vorbis_process_replaygain(pcm, bytes, channels, - pcmout, rg_scale); - } - else { - bytes = ov_read(&vf, pcmout, sizeof(pcmout), - (int) (G_BYTE_ORDER == G_BIG_ENDIAN), - 2, 1, ¤t_section); - } - - /* - * We got some sort of error. Bail. - */ - if (bytes <= 0 && bytes != OV_HOLE) { - g_mutex_unlock(vf_mutex); - playback->playing = 0; - playback->output->buffer_free(); - playback->output->buffer_free(); - playback->eof = TRUE; - return last_section; - } - - if (current_section != last_section) { - /* - * The info struct is different in each section. vf - * holds them all for the given bitstream. This - * requests the current one - */ - vorbis_info *vi = ov_info(&vf, -1); - - if (vi->channels > 2) { - playback->eof = TRUE; - g_mutex_unlock(vf_mutex); - return current_section; - } - - - if (vi->rate != samplerate || vi->channels != channels) { - samplerate = vi->rate; - channels = vi->channels; - playback->output->buffer_free(); - playback->output->buffer_free(); - playback->output->close_audio(); - if (!playback->output-> - open_audio(FMT_S16_NE, vi->rate, vi->channels)) { - playback->error = TRUE; - playback->eof = TRUE; - g_mutex_unlock(vf_mutex); - return current_section; - } - playback->output->flush(ov_time_tell(&vf) * 1000); - } - } - - g_mutex_unlock(vf_mutex); - - playback->pass_audio(playback, FMT_S16_NE, channels, bytes, pcmout, &playback->playing); - - if (!playback->playing) - return current_section; - - if (seekneeded != -1) - do_seek(playback); - - return current_section; -} - static gpointer vorbis_play_loop(gpointer arg) { @@ -350,12 +262,23 @@ fd->fd = stream; datasource = (void *) fd; + char pcmout[4096]; + int bytes; + float **pcm; + /* * The open function performs full stream detection and * machine initialization. None of the rest of ov_xx() works * without it + * + * A vorbis physical bitstream may consist of many logical + * sections (information for each of which may be fetched from + * the vf structure). This value is filled in by ov_read to + * alert us what section we're currently decoding in case we + * need to change playback settings at a section boundary */ - + + g_mutex_lock(vf_mutex); if (ov_open_callbacks(datasource, &vf, NULL, 0, aud_vfs_is_streaming(fd->fd) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { vorbis_callbacks.close_func(datasource); @@ -403,57 +326,146 @@ */ while (playback->playing) { - int current_section; - - if (seekneeded != -1) - do_seek(playback); - + if (playback->eof) { g_usleep(20000); continue; } - current_section = vorbis_process_data(playback, last_section, - use_rg, rg_scale); + if (seekneeded != -1) + do_seek(playback); + + + int current_section = last_section; - if (current_section != last_section) { + g_mutex_lock(vf_mutex); + if (use_rg) { + bytes = + ov_read_float(&vf, &pcm, sizeof(pcmout) / 2 / channels, + ¤t_section); + if (bytes > 0) + bytes = vorbis_process_replaygain(pcm, bytes, channels, + pcmout, rg_scale); + } + else { + bytes = ov_read(&vf, pcmout, sizeof(pcmout), + (int) (G_BYTE_ORDER == G_BIG_ENDIAN), + 2, 1, ¤t_section); + } + + /* + * We got some sort of error. Bail. + */ + if (bytes <= 0 && bytes != OV_HOLE) { + /* + * EOF + */ + playback->playing = 0; + playback->output->buffer_free(); + playback->output->buffer_free(); + playback->eof = TRUE; + current_section = last_section; + } + + + + if (current_section <= last_section) { /* - * set total play time, bitrate, rate, and channels of - * current section + * The info struct is different in each section. vf + * holds them all for the given bitstream. This + * requests the current one */ - if (title) - g_free(title); + vorbis_info *vi = ov_info(&vf, -1); + + if (vi->channels > 2) { + playback->eof = TRUE; + g_mutex_unlock(vf_mutex); + goto stop_processing; + } + - g_mutex_lock(vf_mutex); - title = vorbis_generate_title(&vf, filename); - use_rg = vorbis_update_replaygain(&rg_scale); + if (vi->rate != samplerate || vi->channels != channels) { + samplerate = vi->rate; + channels = vi->channels; + playback->output->buffer_free(); + playback->output->buffer_free(); + playback->output->close_audio(); + if (!playback->output-> + open_audio(FMT_S16_NE, vi->rate, vi->channels)) { + playback->error = TRUE; + playback->eof = TRUE; + g_mutex_unlock(vf_mutex); + goto stop_processing; + } + playback->output->flush(ov_time_tell(&vf) * 1000); + } + } - if (time != -1) - time = ov_time_total(&vf, -1) * 1000; + g_mutex_unlock(vf_mutex); + + playback->pass_audio(playback, FMT_S16_NE, channels, bytes, pcmout, &playback->playing); - g_mutex_unlock(vf_mutex); + if (!playback->playing) + goto stop_processing; + + if (seekneeded != -1) + do_seek(playback); - playback->set_params(playback, title, time, br, samplerate, channels); - timercount = playback->output->output_time(); + stop_processing: + + if (current_section <= last_section) { + /* + * set total play time, bitrate, rate, and channels of + * current section + */ + if (title) + g_free(title); + + g_mutex_lock(vf_mutex); + title = vorbis_generate_title(&vf, filename); + use_rg = vorbis_update_replaygain(&rg_scale); - last_section = current_section; + if (time != -1) + time = ov_time_total(&vf, -1) * 1000; + + g_mutex_unlock(vf_mutex); + + playback->set_params(playback, title, time, br, samplerate, channels); + + timercount = playback->output->output_time(); + + last_section = current_section; + } - } - if (!playback->error) - playback->output->close_audio(); +} + + + +if (!playback->error) + playback->output->close_audio(); /* fall through intentional */ - play_cleanup: - g_free(title); + /*this loop makes it not skip the last ~4 seconds, but the playback + * timer isn't updated in this period, so it still needs a bit of work + * + * majeru + */ +while(playback->output->buffer_playing()&& playback->output->buffer_free()) + g_usleep(50000); - /* - * ov_clear closes the stream if its open. Safe to call on an - * uninitialized structure as long as we've zeroed it - */ + +play_cleanup: +g_free(title); + +/* + * ov_clear closes the stream if its open. Safe to call on an + * uninitialized structure as long as we've zeroed it + */ g_mutex_lock(vf_mutex); ov_clear(&vf); g_mutex_unlock(vf_mutex); playback->playing = 0; + playback->output->buffer_free(); return NULL; } @@ -886,7 +898,7 @@ if (handle->probe == FALSE) { ret = aud_vfs_fclose(handle->fd); -// g_free(handle); // it causes double free. i'm not really sure that commenting out at here is correct. --yaz +/* g_free(handle); it causes double free. i'm not really sure that commenting out at here is correct. --yaz*/ } return ret;