summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2009-09-24 07:03:14 -0700
committerEric Laurent <elaurent@google.com>2009-09-24 23:49:40 -0700
commit824b6a4a67166c3937400702944f659bd0d5d386 (patch)
tree6191f9487ca60d2bf8dbaa16dd8889dd0f594376
parentcdc9847ba4caa93817a8edf3014919d4480298ad (diff)
downloadframeworks_av-824b6a4a67166c3937400702944f659bd0d5d386.zip
frameworks_av-824b6a4a67166c3937400702944f659bd0d5d386.tar.gz
frameworks_av-824b6a4a67166c3937400702944f659bd0d5d386.tar.bz2
Fix issue 2142613: ToneGenerator: short tones sometimes don't play on sholes or over A2DP.
When the AudioTrack callback notification size is relatively high (Which is the case on Sholes and over A2DP), it is likely that the end of tone is reached during the first callback. In this case, the AudioTrack is stopped before exiting the callback which causes 2 problems: - 1: If the AudioFlinger thread is scheduled before we exit the ToneGenerator callback, the track can be stopped and reset before the data is actually marked as present in the buffer by the AudioTrack callback => no audio will be processed by AudioFlinger. - 2: In this case, the data write index in the AudioTrack buffer is incremented after the track was reset by the AudioFlinger which leaves unplayed data in the buffer. This data will be played the next time the AudioTrack is started if not flushed in between. The fix consists in adding an intermediate state to ToneGenerator state machine so that we exit the callback function when the stop condition is reached and stop the AudioTrack the next time we execute the callback.
-rw-r--r--include/media/ToneGenerator.h3
-rw-r--r--media/libmedia/ToneGenerator.cpp27
2 files changed, 21 insertions, 9 deletions
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index ea6bf5d..e8df08e 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -167,7 +167,8 @@ private:
TONE_STARTING, // ToneGenerator is starting playing
TONE_PLAYING, // ToneGenerator is playing
TONE_STOPPING, // ToneGenerator is stoping
- TONE_RESTARTING //
+ TONE_STOPPED, // ToneGenerator is stopped: the AudioTrack will be stopped
+ TONE_RESTARTING // A start request was received in active state (playing or stopping)
};
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 4008bfd..d36bec9 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1066,7 +1066,7 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
if (event != AudioTrack::EVENT_MORE_DATA) return;
- const AudioTrack::Buffer *buffer = static_cast<const AudioTrack::Buffer *>(info);
+ AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info);
ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
short *lpOut = buffer->i16;
unsigned int lNumSmp = buffer->size/sizeof(short);
@@ -1106,14 +1106,14 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
lWaveCmd = WaveGenerator::WAVEGEN_STOP;
lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
break;
+ case TONE_STOPPED:
+ LOGV("Stopped Cbk");
+ goto audioCallback_EndLoop;
default:
LOGV("Extra Cbk");
- // Force loop exit
- lNumSmp = 0;
goto audioCallback_EndLoop;
}
-
// Exit if tone sequence is over
if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0 ||
lpToneGen->mTotalSmp > lpToneGen->mMaxSmp) {
@@ -1123,7 +1123,7 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
goto audioCallback_EndLoop;
}
- // fade out before stopping if maximum duraiton reached
+ // fade out before stopping if maximum duration reached
lWaveCmd = WaveGenerator::WAVEGEN_STOP;
lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
}
@@ -1256,20 +1256,31 @@ audioCallback_EndLoop:
lSignal = true;
break;
case TONE_STOPPING:
+ LOGV("Cbk Stopping\n");
+ lpToneGen->mState = TONE_STOPPED;
+ // Force loop exit
+ lNumSmp = 0;
+ break;
+ case TONE_STOPPED:
lpToneGen->mState = TONE_INIT;
- LOGV("Cbk Stopping track\n");
- lSignal = true;
+ LOGV("Cbk Stopped track\n");
lpToneGen->mpAudioTrack->stop();
-
// Force loop exit
lNumSmp = 0;
+ buffer->size = 0;
+ lSignal = true;
break;
case TONE_STARTING:
LOGV("Cbk starting track\n");
lpToneGen->mState = TONE_PLAYING;
lSignal = true;
break;
+ case TONE_PLAYING:
+ break;
default:
+ // Force loop exit
+ lNumSmp = 0;
+ buffer->size = 0;
break;
}