Commit f31b667f authored by Chris Kuiper's avatar Chris Kuiper Committed by Commit Bot

[Chromecast] Wait before starting AudioTrack playback until data is available

This removes the call to start() at the end of init(), and instead
waits until data is fed in. At that time, it writes as much data as
the AudioTrack instance takes, then calls start(), then feeds in any
additional data not taken on the first call.

Bug: internal b/62923451
Test: run on IMX7, observe logs for playback of TTS and Media
      streams, notice no underruns reported

Change-Id: I89b272655176d22e0cb17e896fe6b9c1daa3e717
Reviewed-on: https://chromium-review.googlesource.com/545262Reviewed-by: default avatarLuke Halliwell <halliwell@chromium.org>
Commit-Queue: Chris Kuiper <ckuiper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#481915}
parent 84011271
...@@ -151,9 +151,6 @@ class AudioSinkAudioTrackImpl { ...@@ -151,9 +151,6 @@ class AudioSinkAudioTrackImpl {
nativeCacheDirectBufferAddress( nativeCacheDirectBufferAddress(
mNativeAudioSinkAudioTrackImpl, mPcmBuffer, mRenderingDelayBuffer); mNativeAudioSinkAudioTrackImpl, mPcmBuffer, mRenderingDelayBuffer);
// Put into PLAYING state so it starts playing right when data is fed in.
play();
mIsInitialized = true; mIsInitialized = true;
} }
...@@ -180,6 +177,10 @@ class AudioSinkAudioTrackImpl { ...@@ -180,6 +177,10 @@ class AudioSinkAudioTrackImpl {
} }
} }
private boolean isStopped() {
return mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_STOPPED;
}
private boolean isPlaying() { private boolean isPlaying() {
return mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING; return mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING;
} }
...@@ -247,6 +248,32 @@ class AudioSinkAudioTrackImpl { ...@@ -247,6 +248,32 @@ class AudioSinkAudioTrackImpl {
long beforeMsecs = SystemClock.elapsedRealtime(); long beforeMsecs = SystemClock.elapsedRealtime();
int bytesWritten = mAudioTrack.write(mPcmBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING); int bytesWritten = mAudioTrack.write(mPcmBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING);
if (bytesWritten < 0) {
int error = bytesWritten;
Log.e(TAG, "Couldn't write into AudioTrack (" + error + ")");
return error;
}
if (isStopped()) {
// Data was written, start playing now.
play();
// If not all data fit on the previous write() call (since we were not in PLAYING state
// it didn't block), do a second (now blocking) call to write().
int bytesLeft = sizeInBytes - bytesWritten;
if (bytesLeft > 0) {
mPcmBuffer.position(bytesWritten);
int moreBytesWritten =
mAudioTrack.write(mPcmBuffer, bytesLeft, AudioTrack.WRITE_BLOCKING);
if (moreBytesWritten < 0) {
int error = moreBytesWritten;
Log.e(TAG, "Couldn't write into AudioTrack (" + error + ")");
return error;
}
bytesWritten += moreBytesWritten;
}
}
int framesWritten = bytesWritten / BYTES_PER_FRAME; int framesWritten = bytesWritten / BYTES_PER_FRAME;
mTotalFramesWritten += framesWritten; mTotalFramesWritten += framesWritten;
...@@ -257,10 +284,9 @@ class AudioSinkAudioTrackImpl { ...@@ -257,10 +284,9 @@ class AudioSinkAudioTrackImpl {
+ " took:" + (SystemClock.elapsedRealtime() - beforeMsecs) + "ms"); + " took:" + (SystemClock.elapsedRealtime() - beforeMsecs) + "ms");
} }
if (bytesWritten <= 0 || isPaused()) { if (bytesWritten < sizeInBytes && isPaused()) {
// Either hit an error or we are in PAUSED state, in which case the // We are in PAUSED state, in which case the write() is non-blocking. If not all data
// write() is non-blocking. If not all data was written, we will come // was written, we will come back here once we transition back into PLAYING state.
// back here once we transition back into PLAYING state.
return bytesWritten; return bytesWritten;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment