From 789294ffb7092770a3b14a900308383c224776d1 Mon Sep 17 00:00:00 2001
From: Thomas Martitz <[email protected]>
Date: Thu, 8 Sep 2011 01:46:46 +0200
Subject: [PATCH] Buflib/swcodec: Improve playback stopping behavior on
allocation.

Reuse playback's Q_AUDIO_REMAKE_AUDIO_BUFFER capabilities to set the new
playback buffer, instead of stopping/restarting manual. This strongly
reduces the visibility of the short audio stop.
---
apps/playback.c | 59 ++++++++++++++++++++++--------------------------------
1 files changed, 24 insertions(+), 35 deletions(-)

diff --git a/apps/playback.c b/apps/playback.c
index dbe28dd..fd7ab48 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -744,7 +744,7 @@ size_t audio_buffer_available(void)

/* Set up the audio buffer for playback
* filebuflen must be pre-initialized with the maximum size */
-static void audio_reset_buffer_noalloc(void* filebuf)
+static void audio_reset_buffer_noalloc(void)
{
/*
* Layout audio buffer as follows:
@@ -761,6 +761,7 @@ static void audio_reset_buffer_noalloc(void* filebuf)
/* Initially set up file buffer as all space available */
size_t allocsize;

+ void* filebuf = core_get_data(audiobuf_handle);
/* Subtract whatever voice needs */
allocsize = talkbuf_init(filebuf);
allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
@@ -828,44 +829,30 @@ bufpanic:
/* Buffer must not move. */
static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size)
{
- long offset = audio_current_track()->offset;
- int status = audio_status();
- /* TODO: Do it without stopping playback, if possible */
- /* don't call audio_hard_stop() as it frees this handle */
- if (thread_self() == audio_thread_id)
- { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
- * if we're in the audio thread */
- audio_stop_playback();
- queue_clear(&audio_queue);
- }
- else
- audio_queue_send(Q_AUDIO_STOP, 1);
-#ifdef PLAYBACK_VOICE
- voice_stop();
-#endif
/* we should be free to change the buffer now */
size_t wanted_size = (hints & BUFLIB_SHRINK_SIZE_MASK);
ssize_t size = (ssize_t)old_size - wanted_size;
- /* set final buffer size before calling audio_reset_buffer_noalloc() */
- filebuflen = size;
switch (hints & BUFLIB_SHRINK_POS_MASK)
{
case BUFLIB_SHRINK_POS_BACK:
core_shrink(handle, start, size);
- audio_reset_buffer_noalloc(start);
break;
case BUFLIB_SHRINK_POS_FRONT:
core_shrink(handle, start + wanted_size, size);
- audio_reset_buffer_noalloc(start + wanted_size);
break;
}
- if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
- {
- if (thread_self() == audio_thread_id)
- audio_start_playback(offset, 0); /* inline Q_AUDIO_PLAY */
- else
- audio_play(offset);
+ /* set final buffer size before calling audio_start_playback()
+ * (which calls audio_reset_buffer_noalloc() which needs the new size) */
+ filebuflen = size;
+ /* TODO: Do it without stopping playback, if possible */
+ /* don't call audio_hard_stop() as it frees this handle */
+ if (thread_self() == audio_thread_id)
+ { /* inline case Q_AUDIO_REMAKE_AUDIO_BUFFER to avoid deadlock if
+ * we're in the audio thread */
+ audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
}
+ else
+ audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);

return BUFLIB_CB_OK;
}
@@ -883,9 +870,8 @@ static void audio_reset_buffer(void)
audiobuf_handle = 0;
}
audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops);
- unsigned char *filebuf = core_get_data(audiobuf_handle);

- audio_reset_buffer_noalloc(filebuf);
+ audio_reset_buffer_noalloc();
}

/* Set the buffer margin to begin rebuffering when 'seconds' from empty */
@@ -1944,7 +1930,7 @@ audio_finish_load_track_exit:
}

/* Start a new track load */
-static int audio_fill_file_buffer(void)
+static int audio_fill_file_buffer(bool realloc)
{
if (play_status == PLAY_STOPPED)
return LOAD_TRACK_ERR_FAILED;
@@ -1955,7 +1941,10 @@ static int audio_fill_file_buffer(void)
file size shouldn't have changed so we can go straight from
AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
- audio_reset_buffer();
+ {
+ realloc ?
+ audio_reset_buffer() : audio_reset_buffer_noalloc();
+ }

logf("Starting buffer fill");

@@ -1994,7 +1983,7 @@ static int audio_reset_and_rebuffer(
playlist_peek_offset = peek_offset;

/* Fill the buffer */
- return audio_fill_file_buffer();
+ return audio_fill_file_buffer(true);
}

/* Handle buffering events
@@ -2051,7 +2040,7 @@ static void audio_on_buffering(int event)
(Q_AUDIO_FILL_BUFFER) */
static void audio_on_fill_buffer(void)
{
- audio_handle_track_load_status(audio_fill_file_buffer());
+ audio_handle_track_load_status(audio_fill_file_buffer(true));
}

/* Handle posted load track finish event
@@ -2467,8 +2456,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL);
}

- /* Fill the buffer */
- int trackstat = audio_fill_file_buffer();
+ /* Fill the buffer, assumed to be setup already here, thus realloc=false */
+ int trackstat = audio_fill_file_buffer(false);

if (trackstat >= LOAD_TRACK_OK)
{
@@ -2860,7 +2849,7 @@ static void audio_on_audio_flush(void)
audio_update_and_announce_next_track(NULL);

/* Ignore return since it's about the next track, not this one */
- audio_fill_file_buffer();
+ audio_fill_file_buffer(true);

if (skip_pending == TRACK_SKIP_NONE)
break;
--
1.7.5.4