1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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