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
This commit is contained in:
Thomas Martitz 2010-08-08 15:53:02 +00:00
parent 446445e916
commit 4aa3d01066

View file

@ -24,6 +24,9 @@ package org.rockbox;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.util.Log;
public class RockboxPCM extends AudioTrack
@ -31,6 +34,8 @@ public class RockboxPCM extends AudioTrack
byte[] raw_data;
private int buf_len;
private PCMListener l;
private HandlerThread ht;
private Handler h = null;
private void LOG(CharSequence text)
{
@ -46,6 +51,8 @@ public class RockboxPCM extends AudioTrack
AudioFormat.ENCODING_PCM_16BIT,
24<<10,
AudioTrack.MODE_STREAM);
ht = new HandlerThread("audio thread", Process.THREAD_PRIORITY_URGENT_AUDIO);
ht.start();
buf_len = 24<<10; /* in bytes */
raw_data = new byte[buf_len]; /* in shorts */
@ -76,10 +83,12 @@ public class RockboxPCM extends AudioTrack
RockboxService.startForeground();
if (getState() == AudioTrack.STATE_INITIALIZED)
{
if (h == null)
h = new Handler(ht.getLooper());
if (setNotificationMarkerPosition(bytes2frames(buf_len)/4) != AudioTrack.SUCCESS)
LOG("setNotificationMarkerPosition Error");
else
setPlaybackPositionUpdateListener(l);
setPlaybackPositionUpdateListener(l, h);
}
/* need to fill with silence before starting playback */
write(raw_data, frames2bytes(getPlaybackHeadPosition()), raw_data.length);
@ -140,10 +149,11 @@ public class RockboxPCM extends AudioTrack
{
case AudioTrack.PLAYSTATE_PLAYING:
case AudioTrack.PLAYSTATE_PAUSED:
/* recharge */
setPlaybackPositionUpdateListener(this);
/* refill at 25% no matter of how many bytes we've written */
setNotificationMarkerPosition(bytes2frames(refill_mark));
if (setNotificationMarkerPosition(bytes2frames(refill_mark)) != AudioTrack.SUCCESS)
LOG("Error in onMarkerReached: Could not set notification marker");
else /* recharge */
setPlaybackPositionUpdateListener(this, h);
break;
case AudioTrack.PLAYSTATE_STOPPED:
LOG("State STOPPED");