summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-08-08 15:53:02 +0000
committerThomas Martitz <kugel@rockbox.org>2010-08-08 15:53:02 +0000
commit4aa3d010660dd5e785e02050ab9a87522f297f7a (patch)
tree1a32ad40a29b425a63ae953b2297447b5a87bf4f
parent446445e9162d19ceeabf889e6aa916ec9ec58b5b (diff)
downloadrockbox-4aa3d010660dd5e785e02050ab9a87522f297f7a.tar.gz
rockbox-4aa3d010660dd5e785e02050ab9a87522f297f7a.zip
Run the pcm callback from a separate OS thread, that seems to make audio playback
much more reliable. Especially on the broken HTC phones. Now it recovers from stuttering instead of simply stopping playback on my phone. Previously it was run on the main/UI thread (the docs lie in that regard), which I suspect happened to be blocked if it's in the background and tries to get too much CPU. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27753 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--android/src/org/rockbox/RockboxPCM.java18
1 files changed, 14 insertions, 4 deletions
diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java
index 631d925b12..eef56f501d 100644
--- a/android/src/org/rockbox/RockboxPCM.java
+++ b/android/src/org/rockbox/RockboxPCM.java
@@ -24,6 +24,9 @@ package org.rockbox;
24import android.media.AudioFormat; 24import android.media.AudioFormat;
25import android.media.AudioManager; 25import android.media.AudioManager;
26import android.media.AudioTrack; 26import android.media.AudioTrack;
27import android.os.Handler;
28import android.os.HandlerThread;
29import android.os.Process;
27import android.util.Log; 30import android.util.Log;
28 31
29public class RockboxPCM extends AudioTrack 32public class RockboxPCM extends AudioTrack
@@ -31,6 +34,8 @@ public class RockboxPCM extends AudioTrack
31 byte[] raw_data; 34 byte[] raw_data;
32 private int buf_len; 35 private int buf_len;
33 private PCMListener l; 36 private PCMListener l;
37 private HandlerThread ht;
38 private Handler h = null;
34 39
35 private void LOG(CharSequence text) 40 private void LOG(CharSequence text)
36 { 41 {
@@ -46,6 +51,8 @@ public class RockboxPCM extends AudioTrack
46 AudioFormat.ENCODING_PCM_16BIT, 51 AudioFormat.ENCODING_PCM_16BIT,
47 24<<10, 52 24<<10,
48 AudioTrack.MODE_STREAM); 53 AudioTrack.MODE_STREAM);
54 ht = new HandlerThread("audio thread", Process.THREAD_PRIORITY_URGENT_AUDIO);
55 ht.start();
49 buf_len = 24<<10; /* in bytes */ 56 buf_len = 24<<10; /* in bytes */
50 57
51 raw_data = new byte[buf_len]; /* in shorts */ 58 raw_data = new byte[buf_len]; /* in shorts */
@@ -76,10 +83,12 @@ public class RockboxPCM extends AudioTrack
76 RockboxService.startForeground(); 83 RockboxService.startForeground();
77 if (getState() == AudioTrack.STATE_INITIALIZED) 84 if (getState() == AudioTrack.STATE_INITIALIZED)
78 { 85 {
86 if (h == null)
87 h = new Handler(ht.getLooper());
79 if (setNotificationMarkerPosition(bytes2frames(buf_len)/4) != AudioTrack.SUCCESS) 88 if (setNotificationMarkerPosition(bytes2frames(buf_len)/4) != AudioTrack.SUCCESS)
80 LOG("setNotificationMarkerPosition Error"); 89 LOG("setNotificationMarkerPosition Error");
81 else 90 else
82 setPlaybackPositionUpdateListener(l); 91 setPlaybackPositionUpdateListener(l, h);
83 } 92 }
84 /* need to fill with silence before starting playback */ 93 /* need to fill with silence before starting playback */
85 write(raw_data, frames2bytes(getPlaybackHeadPosition()), raw_data.length); 94 write(raw_data, frames2bytes(getPlaybackHeadPosition()), raw_data.length);
@@ -140,10 +149,11 @@ public class RockboxPCM extends AudioTrack
140 { 149 {
141 case AudioTrack.PLAYSTATE_PLAYING: 150 case AudioTrack.PLAYSTATE_PLAYING:
142 case AudioTrack.PLAYSTATE_PAUSED: 151 case AudioTrack.PLAYSTATE_PAUSED:
143 /* recharge */
144 setPlaybackPositionUpdateListener(this);
145 /* refill at 25% no matter of how many bytes we've written */ 152 /* refill at 25% no matter of how many bytes we've written */
146 setNotificationMarkerPosition(bytes2frames(refill_mark)); 153 if (setNotificationMarkerPosition(bytes2frames(refill_mark)) != AudioTrack.SUCCESS)
154 LOG("Error in onMarkerReached: Could not set notification marker");
155 else /* recharge */
156 setPlaybackPositionUpdateListener(this, h);
147 break; 157 break;
148 case AudioTrack.PLAYSTATE_STOPPED: 158 case AudioTrack.PLAYSTATE_STOPPED:
149 LOG("State STOPPED"); 159 LOG("State STOPPED");