summaryrefslogtreecommitdiffstats
path: root/media/libmedia/AudioTrack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmedia/AudioTrack.cpp')
-rw-r--r--media/libmedia/AudioTrack.cpp62
1 files changed, 41 insertions, 21 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index f9f8568..d26b0c5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -128,22 +128,21 @@ status_t AudioTrack::set(
return NO_INIT;
}
int afSampleRate;
- if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
return NO_INIT;
}
int afFrameCount;
- if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+ if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
return NO_INIT;
}
uint32_t afLatency;
- if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) {
+ if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
return NO_INIT;
}
-
// handle default values first.
- if (streamType == DEFAULT) {
- streamType = MUSIC;
+ if (streamType == AudioSystem::DEFAULT) {
+ streamType = AudioSystem::MUSIC;
}
if (sampleRate == 0) {
sampleRate = afSampleRate;
@@ -157,7 +156,7 @@ status_t AudioTrack::set(
}
// validate parameters
- if (((format != AudioSystem::PCM_8_BIT) || mSharedBuffer != 0) &&
+ if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
(format != AudioSystem::PCM_16_BIT)) {
LOGE("Invalid format");
return BAD_VALUE;
@@ -169,6 +168,8 @@ status_t AudioTrack::set(
// Ensure that buffer depth covers at least audio hardware latency
uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+ if (minBufCount < 2) minBufCount = 2;
+
// When playing from shared buffer, playback will start even if last audioflinger
// block is partly filled.
if (sharedBuffer != 0 && minBufCount > 1) {
@@ -260,7 +261,7 @@ status_t AudioTrack::set(
mMarkerPosition = 0;
mNewPosition = 0;
mUpdatePeriod = 0;
-
+
return NO_ERROR;
}
@@ -317,7 +318,7 @@ void AudioTrack::start()
{
sp<AudioTrackThread> t = mAudioTrackThread;
- LOGV("start");
+ LOGV("start %p", this);
if (t != 0) {
if (t->exitPending()) {
if (t->requestExitAndWait() == WOULD_BLOCK) {
@@ -349,7 +350,7 @@ void AudioTrack::stop()
{
sp<AudioTrackThread> t = mAudioTrackThread;
- LOGV("stop");
+ LOGV("stop %p", this);
if (t != 0) {
t->mLock.lock();
}
@@ -434,12 +435,12 @@ void AudioTrack::setSampleRate(int rate)
{
int afSamplingRate;
- if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) {
+ if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
return;
}
// Resampler implementation limits input sampling rate to 2 x output sampling rate.
+ if (rate <= 0) rate = 1;
if (rate > afSamplingRate*2) rate = afSamplingRate*2;
-
if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
mCblk->sampleRate = rate;
@@ -467,10 +468,15 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount
if (loopStart >= loopEnd ||
loopEnd - loopStart > mFrameCount) {
- LOGW("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
+ LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
return BAD_VALUE;
}
- // TODO handle shared buffer here: limit loop end to framecount
+
+ if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) {
+ LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
+ loopStart, loopEnd, mFrameCount);
+ return BAD_VALUE;
+ }
cblk->loopStart = loopStart;
cblk->loopEnd = loopEnd;
@@ -603,13 +609,20 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
if (__builtin_expect(result!=NO_ERROR, false)) {
cblk->waitTimeMs += WAIT_PERIOD_MS;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
- LOGW( "obtainBuffer timed out (is the CPU pegged?) "
- "user=%08x, server=%08x", cblk->user, cblk->server);
- mAudioTrack->start(); // FIXME: Wake up audioflinger
- timeout = 1;
+ // timing out when a loop has been set and we have already written upto loop end
+ // is a normal condition: no need to wake AudioFlinger up.
+ if (cblk->user < cblk->loopEnd) {
+ LOGW( "obtainBuffer timed out (is the CPU pegged?) %p "
+ "user=%08x, server=%08x", this, cblk->user, cblk->server);
+ //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
+ cblk->lock.unlock();
+ mAudioTrack->start();
+ cblk->lock.lock();
+ timeout = 1;
+ }
cblk->waitTimeMs = 0;
}
- ;
+
if (--waitCount == 0) {
return TIMED_OUT;
}
@@ -668,7 +681,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
return BAD_VALUE;
}
- LOGV("write %d bytes, mActive=%d", userSize, mActive);
+ LOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive);
ssize_t written = 0;
const int8_t *src = (const int8_t *)buffer;
@@ -795,7 +808,14 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
writtenSize = audioBuffer.size;
// Sanity check on returned size
- if (ssize_t(writtenSize) <= 0) break;
+ if (ssize_t(writtenSize) <= 0) {
+ // The callback is done filling buffers
+ // Keep this thread going to handle timed events and
+ // still try to get more data in intervals of WAIT_PERIOD_MS
+ // but don't just loop and block the CPU, so wait
+ usleep(WAIT_PERIOD_MS*1000);
+ break;
+ }
if (writtenSize > reqSize) writtenSize = reqSize;
if (mFormat == AudioSystem::PCM_8_BIT) {