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.cpp163
1 files changed, 103 insertions, 60 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 4b9d272..8529a8e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -122,11 +122,6 @@ status_t AudioTrack::set(
return INVALID_OPERATION;
}
- const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
- if (audioFlinger == 0) {
- LOGE("Could not get audioflinger");
- return NO_INIT;
- }
int afSampleRate;
if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
return NO_INIT;
@@ -217,28 +212,16 @@ status_t AudioTrack::set(
}
}
- // create the track
- status_t status;
- sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
- streamType,
- sampleRate,
- format,
- channelCount,
- frameCount,
- ((uint16_t)flags) << 16,
- sharedBuffer,
- output,
- &status);
+ mVolume[LEFT] = 1.0f;
+ mVolume[RIGHT] = 1.0f;
+ // create the IAudioTrack
+ status_t status = createTrack(streamType, sampleRate, format, channelCount,
+ frameCount, flags, sharedBuffer, output);
- if (track == 0) {
- LOGE("AudioFlinger could not create track, status: %d", status);
+ if (status != NO_ERROR) {
return status;
}
- sp<IMemory> cblk = track->getCblk();
- if (cblk == 0) {
- LOGE("Could not get control block");
- return NO_INIT;
- }
+
if (cbf != 0) {
mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
if (mAudioTrackThread == 0) {
@@ -249,22 +232,6 @@ status_t AudioTrack::set(
mStatus = NO_ERROR;
- mAudioTrack = track;
- mCblkMemory = cblk;
- mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
- mCblk->out = 1;
- // Update buffer size in case it has been limited by AudioFlinger during track creation
- mFrameCount = mCblk->frameCount;
- if (sharedBuffer == 0) {
- mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- } else {
- mCblk->buffers = sharedBuffer->pointer();
- // Force buffer full condition as data is already present in shared memory
- mCblk->stepUser(mFrameCount);
- }
- mCblk->volume[0] = mCblk->volume[1] = 0x1000;
- mVolume[LEFT] = 1.0f;
- mVolume[RIGHT] = 1.0f;
mStreamType = streamType;
mFormat = format;
mChannels = channels;
@@ -351,16 +318,27 @@ void AudioTrack::start()
}
if (android_atomic_or(1, &mActive) == 0) {
- AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
- mNewPosition = mCblk->server + mUpdatePeriod;
- mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
- mCblk->waitTimeMs = 0;
- if (t != 0) {
- t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
+ audio_io_handle_t output = AudioTrack::getOutput();
+ status_t status = mAudioTrack->start();
+ if (status == DEAD_OBJECT) {
+ LOGV("start() dead IAudioTrack: creating a new one");
+ status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
+ mFrameCount, mFlags, mSharedBuffer, output);
+ }
+ if (status == NO_ERROR) {
+ AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
+ mNewPosition = mCblk->server + mUpdatePeriod;
+ mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+ mCblk->waitTimeMs = 0;
+ if (t != 0) {
+ t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
+ } else {
+ setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+ }
} else {
- setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+ LOGV("start() failed");
+ android_atomic_and(~1, &mActive);
}
- mAudioTrack->start();
}
if (t != 0) {
@@ -617,10 +595,67 @@ audio_io_handle_t AudioTrack::getOutput()
// -------------------------------------------------------------------------
+status_t AudioTrack::createTrack(
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelCount,
+ int frameCount,
+ uint32_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output)
+{
+ status_t status;
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ LOGE("Could not get audioflinger");
+ return NO_INIT;
+ }
+
+ sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
+ streamType,
+ sampleRate,
+ format,
+ channelCount,
+ frameCount,
+ ((uint16_t)flags) << 16,
+ sharedBuffer,
+ output,
+ &status);
+
+ if (track == 0) {
+ LOGE("AudioFlinger could not create track, status: %d", status);
+ return status;
+ }
+ sp<IMemory> cblk = track->getCblk();
+ if (cblk == 0) {
+ LOGE("Could not get control block");
+ return NO_INIT;
+ }
+ mAudioTrack.clear();
+ mAudioTrack = track;
+ mCblkMemory.clear();
+ mCblkMemory = cblk;
+ mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+ mCblk->out = 1;
+ // Update buffer size in case it has been limited by AudioFlinger during track creation
+ mFrameCount = mCblk->frameCount;
+ if (sharedBuffer == 0) {
+ mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+ } else {
+ mCblk->buffers = sharedBuffer->pointer();
+ // Force buffer full condition as data is already present in shared memory
+ mCblk->stepUser(mFrameCount);
+ }
+
+ mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
+
+ return NO_ERROR;
+}
+
status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
int active;
- int timeout = 0;
status_t result;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
@@ -632,17 +667,20 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
uint32_t framesAvail = cblk->framesAvailable();
if (framesAvail == 0) {
- Mutex::Autolock _l(cblk->lock);
+ cblk->lock.lock();
goto start_loop_here;
while (framesAvail == 0) {
active = mActive;
if (UNLIKELY(!active)) {
LOGV("Not active and NO_MORE_BUFFERS");
+ cblk->lock.unlock();
return NO_MORE_BUFFERS;
}
- if (UNLIKELY(!waitCount))
+ if (UNLIKELY(!waitCount)) {
+ cblk->lock.unlock();
return WOULD_BLOCK;
- timeout = 0;
+ }
+
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
if (__builtin_expect(result!=NO_ERROR, false)) {
cblk->waitTimeMs += waitTimeMs;
@@ -654,14 +692,23 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
"user=%08x, server=%08x", this, cblk->user, cblk->server);
//unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
cblk->lock.unlock();
- mAudioTrack->start();
+ result = mAudioTrack->start();
+ if (result == DEAD_OBJECT) {
+ LOGW("obtainBuffer() dead IAudioTrack: creating a new one");
+ result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount,
+ mFrameCount, mFlags, mSharedBuffer, getOutput());
+ if (result == NO_ERROR) {
+ cblk = mCblk;
+ cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ }
+ }
cblk->lock.lock();
- timeout = 1;
}
cblk->waitTimeMs = 0;
}
if (--waitCount == 0) {
+ cblk->lock.unlock();
return TIMED_OUT;
}
}
@@ -669,6 +716,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
start_loop_here:
framesAvail = cblk->framesAvailable_l();
}
+ cblk->lock.unlock();
}
cblk->waitTimeMs = 0;
@@ -684,11 +732,6 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
framesReq = bufferEnd - u;
}
- LOGW_IF(timeout,
- "*** SERIOUS WARNING *** obtainBuffer() timed out "
- "but didn't need to be locked. We recovered, but "
- "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
-
audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
audioBuffer->channelCount = mChannelCount;
audioBuffer->frameCount = framesReq;
@@ -991,7 +1034,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
// Mark that we have read the first buffer so that next time stepUser() is called
// we switch to normal obtainBuffer() timeout period
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
- bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
+ bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
}
// It is possible that we receive a flush()
// while the mixer is processing a block: in this case,