Remove BlockingMediaPlayer.

No need to spawn a new thread for every audio item sent to
the TTS class.

Change-Id: Ia52b0951f4249b0da460a5ecaff5dd11a6e5d5fc
This commit is contained in:
Narayan Kamath
2011-12-05 11:20:07 +00:00
parent 4a3d5b04da
commit af802c6831
4 changed files with 76 additions and 205 deletions

View File

@@ -15,27 +15,91 @@
*/
package android.speech.tts;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.ConditionVariable;
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
import android.util.Log;
class AudioPlaybackQueueItem extends PlaybackQueueItem {
private final BlockingMediaPlayer mPlayer;
private static final String TAG = "TTS.AudioQueueItem";
private final Context mContext;
private final Uri mUri;
private final int mStreamType;
private final ConditionVariable mDone;
private MediaPlayer mPlayer;
private volatile boolean mFinished;
AudioPlaybackQueueItem(UtteranceProgressDispatcher dispatcher,
Object callerIdentity, BlockingMediaPlayer player) {
Object callerIdentity,
Context context, Uri uri, int streamType) {
super(dispatcher, callerIdentity);
mPlayer = player;
mContext = context;
mUri = uri;
mStreamType = streamType;
mDone = new ConditionVariable();
mPlayer = null;
mFinished = false;
}
@Override
public void run() {
getDispatcher().dispatchOnStart();
// TODO: This can be avoided. Will be fixed later in this CL.
mPlayer.startAndWait();
getDispatcher().dispatchOnDone();
final UtteranceProgressDispatcher dispatcher = getDispatcher();
dispatcher.dispatchOnStart();
mPlayer = MediaPlayer.create(mContext, mUri);
if (mPlayer == null) {
dispatcher.dispatchOnError();
return;
}
try {
mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.w(TAG, "Audio playback error: " + what + ", " + extra);
mDone.open();
return true;
}
});
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mFinished = true;
mDone.open();
}
});
mPlayer.setAudioStreamType(mStreamType);
mPlayer.start();
mDone.block();
finish();
} catch (IllegalArgumentException ex) {
Log.w(TAG, "MediaPlayer failed", ex);
mDone.open();
}
if (mFinished) {
dispatcher.dispatchOnDone();
} else {
dispatcher.dispatchOnError();
}
}
private void finish() {
try {
mPlayer.stop();
} catch (IllegalStateException ex) {
// Do nothing, the player is already stopped
}
mPlayer.release();
}
@Override
void stop(boolean isError) {
mPlayer.stop();
mDone.open();
}
}

View File

@@ -1,145 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.speech.tts;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Log;
/**
* A media player that allows blocking to wait for it to finish.
*/
class BlockingMediaPlayer {
private static final String TAG = "BlockMediaPlayer";
private static final String MEDIA_PLAYER_THREAD_NAME = "TTS-MediaPlayer";
private final Context mContext;
private final Uri mUri;
private final int mStreamType;
private final ConditionVariable mDone;
// Only accessed on the Handler thread
private MediaPlayer mPlayer;
private volatile boolean mFinished;
/**
* Creates a new blocking media player.
* Creating a blocking media player is a cheap operation.
*
* @param context
* @param uri
* @param streamType
*/
public BlockingMediaPlayer(Context context, Uri uri, int streamType) {
mContext = context;
mUri = uri;
mStreamType = streamType;
mDone = new ConditionVariable();
}
/**
* Starts playback and waits for it to finish.
* Can be called from any thread.
*
* @return {@code true} if the playback finished normally, {@code false} if the playback
* failed or {@link #stop} was called before the playback finished.
*/
public boolean startAndWait() {
HandlerThread thread = new HandlerThread(MEDIA_PLAYER_THREAD_NAME);
thread.start();
Handler handler = new Handler(thread.getLooper());
mFinished = false;
handler.post(new Runnable() {
@Override
public void run() {
startPlaying();
}
});
mDone.block();
handler.post(new Runnable() {
@Override
public void run() {
finish();
// No new messages should get posted to the handler thread after this
Looper.myLooper().quit();
}
});
return mFinished;
}
/**
* Stops playback. Can be called multiple times.
* Can be called from any thread.
*/
public void stop() {
mDone.open();
}
/**
* Starts playback.
* Called on the handler thread.
*/
private void startPlaying() {
mPlayer = MediaPlayer.create(mContext, mUri);
if (mPlayer == null) {
Log.w(TAG, "Failed to play " + mUri);
mDone.open();
return;
}
try {
mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.w(TAG, "Audio playback error: " + what + ", " + extra);
mDone.open();
return true;
}
});
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mFinished = true;
mDone.open();
}
});
mPlayer.setAudioStreamType(mStreamType);
mPlayer.start();
} catch (IllegalArgumentException ex) {
Log.w(TAG, "MediaPlayer failed", ex);
mDone.open();
}
}
/**
* Stops playback and release the media player.
* Called on the handler thread.
*/
private void finish() {
try {
mPlayer.stop();
} catch (IllegalStateException ex) {
// Do nothing, the player is already stopped
}
mPlayer.release();
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.speech.tts;
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
abstract class MessageParams {
static final int TYPE_SYNTHESIS = 1;
static final int TYPE_AUDIO = 2;
static final int TYPE_SILENCE = 3;
private final UtteranceProgressDispatcher mDispatcher;
private final Object mCallerIdentity;
MessageParams(UtteranceProgressDispatcher dispatcher, Object callerIdentity) {
mDispatcher = dispatcher;
mCallerIdentity = callerIdentity;
}
UtteranceProgressDispatcher getDispatcher() {
return mDispatcher;
}
Object getCallerIdentity() {
return mCallerIdentity;
}
@Override
public String toString() {
return "MessageParams[" + hashCode() + "]";
}
abstract int getType();
}

View File

@@ -694,12 +694,12 @@ public abstract class TextToSpeechService extends Service {
}
private class AudioSpeechItem extends SpeechItem {
private final BlockingMediaPlayer mPlayer;
private final AudioPlaybackQueueItem mItem;
public AudioSpeechItem(Object callerIdentity, int callerUid, int callerPid,
Bundle params, Uri uri) {
super(callerIdentity, callerUid, callerPid, params);
mPlayer = new BlockingMediaPlayer(TextToSpeechService.this, uri, getStreamType());
mItem = new AudioPlaybackQueueItem(this, getCallerIdentity(),
TextToSpeechService.this, uri, getStreamType());
}
@Override
@@ -709,8 +709,7 @@ public abstract class TextToSpeechService extends Service {
@Override
protected int playImpl() {
mAudioPlaybackHandler.enqueue(new AudioPlaybackQueueItem(
this, getCallerIdentity(), mPlayer));
mAudioPlaybackHandler.enqueue(mItem);
return TextToSpeech.SUCCESS;
}