Merge "docs: fix some broken links" into eclair
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 2024cc0..ecfe1e0 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -932,6 +932,8 @@
result.append(buffer);
snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
result.append(buffer);
+ snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
+ result.append(buffer);
write(fd, result.string(), result.size());
dumpBase(fd, args);
@@ -1344,7 +1346,7 @@
if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
!track->isPaused())
{
- //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+ //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
// compute volume for this track
int16_t left, right;
@@ -1400,7 +1402,7 @@
track->mRetryCount = kMaxTrackRetries;
mixerStatus = MIXER_TRACKS_READY;
} else {
- //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+ //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
if (track->isStopped()) {
track->reset();
}
@@ -1914,7 +1916,7 @@
// ----------------------------------------------------------------------------
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
- : MixerThread(audioFlinger, mainThread->getOutput(), id)
+ : MixerThread(audioFlinger, mainThread->getOutput(), id), mWaitTimeMs(UINT_MAX)
{
mType = PlaybackThread::DUPLICATING;
addOutputTrack(mainThread);
@@ -1952,6 +1954,7 @@
if (checkForNewParameters_l()) {
mixBufferSize = mFrameCount*mFrameSize;
+ updateWaitTime();
activeSleepTime = activeSleepTimeUs();
idleSleepTime = idleSleepTimeUs();
}
@@ -2003,7 +2006,11 @@
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
// mix buffers...
- mAudioMixer->process(curBuf);
+ if (outputsReady(outputTracks)) {
+ mAudioMixer->process(curBuf);
+ } else {
+ memset(curBuf, 0, mixBufferSize);
+ }
sleepTime = 0;
writeFrames = mFrameCount;
} else {
@@ -2054,6 +2061,7 @@
{
int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
+ this,
mSampleRate,
mFormat,
mChannelCount,
@@ -2062,6 +2070,7 @@
thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
mOutputTracks.add(outputTrack);
LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+ updateWaitTime();
}
}
@@ -2072,12 +2081,50 @@
if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
mOutputTracks[i]->destroy();
mOutputTracks.removeAt(i);
+ updateWaitTime();
return;
}
}
LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
}
+void AudioFlinger::DuplicatingThread::updateWaitTime()
+{
+ mWaitTimeMs = UINT_MAX;
+ for (size_t i = 0; i < mOutputTracks.size(); i++) {
+ sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
+ if (strong != NULL) {
+ uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
+ if (waitTimeMs < mWaitTimeMs) {
+ mWaitTimeMs = waitTimeMs;
+ }
+ }
+ }
+}
+
+
+bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
+{
+ for (size_t i = 0; i < outputTracks.size(); i++) {
+ sp <ThreadBase> thread = outputTracks[i]->thread().promote();
+ if (thread == 0) {
+ LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
+ return false;
+ }
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ if (playbackThread->standby() && !playbackThread->isSuspended()) {
+ LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
+ return false;
+ }
+ }
+ return true;
+}
+
+uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
+{
+ return (mWaitTimeMs * 1000) / 2;
+}
+
// ----------------------------------------------------------------------------
// TrackBase constructor must be called with AudioFlinger::mLock held
@@ -2616,12 +2663,13 @@
AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
const wp<ThreadBase>& thread,
+ DuplicatingThread *sourceThread,
uint32_t sampleRate,
int format,
int channelCount,
int frameCount)
: Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
- mActive(false)
+ mActive(false), mSourceThread(sourceThread)
{
PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
@@ -2630,10 +2678,9 @@
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
mCblk->volume[0] = mCblk->volume[1] = 0x1000;
mOutBuffer.frameCount = 0;
- mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
playbackThread->mTracks.add(this);
- LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
- mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
+ LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
+ mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
} else {
LOGW("Error creating output track on thread %p", playbackThread);
}
@@ -2673,7 +2720,7 @@
inBuffer.frameCount = frames;
inBuffer.i16 = data;
- uint32_t waitTimeLeftMs = mWaitTimeMs;
+ uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
if (!mActive && frames != 0) {
start();
@@ -2712,12 +2759,11 @@
mOutBuffer.frameCount = pInBuffer->frameCount;
nsecs_t startTime = systemTime();
if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
- LOGV ("OutputTrack::write() %p no more output buffers", this);
+ LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
outputBufferFull = true;
break;
}
uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
- LOGV("OutputTrack::write() to thread %p waitTimeMs %d waitTimeLeftMs %d", mThread.unsafe_get(), waitTimeMs, waitTimeLeftMs);
if (waitTimeLeftMs >= waitTimeMs) {
waitTimeLeftMs -= waitTimeMs;
} else {
@@ -2738,7 +2784,7 @@
mBufferQueue.removeAt(0);
delete [] pInBuffer->mBuffer;
delete pInBuffer;
- LOGV("OutputTrack::write() %p released overflow buffer %d", this, mBufferQueue.size());
+ LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
} else {
break;
}
@@ -2747,16 +2793,19 @@
// If we could not write all frames, allocate a buffer and queue it for next time.
if (inBuffer.frameCount) {
- if (mBufferQueue.size() < kMaxOverFlowBuffers) {
- pInBuffer = new Buffer;
- pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
- pInBuffer->frameCount = inBuffer.frameCount;
- pInBuffer->i16 = pInBuffer->mBuffer;
- memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
- mBufferQueue.add(pInBuffer);
- LOGV("OutputTrack::write() %p adding overflow buffer %d", this, mBufferQueue.size());
- } else {
- LOGW("OutputTrack::write() %p no more overflow buffers", this);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0 && !thread->standby()) {
+ if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+ pInBuffer = new Buffer;
+ pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
+ pInBuffer->frameCount = inBuffer.frameCount;
+ pInBuffer->i16 = pInBuffer->mBuffer;
+ memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
+ mBufferQueue.add(pInBuffer);
+ LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
+ } else {
+ LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
+ }
}
}
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 8c29da8..12c90eb 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <limits.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioFlingerClient.h>
@@ -208,6 +209,7 @@
class PlaybackThread;
class MixerThread;
class DirectOutputThread;
+ class DuplicatingThread;
class Track;
class RecordTrack;
@@ -324,6 +326,7 @@
void sendConfigEvent_l(int event, int param = 0);
void processConfigEvents();
int id() const { return mId;}
+ bool standby() { return mStandby; }
mutable Mutex mLock;
@@ -452,6 +455,7 @@
};
OutputTrack( const wp<ThreadBase>& thread,
+ DuplicatingThread *sourceThread,
uint32_t sampleRate,
int format,
int channelCount,
@@ -471,13 +475,12 @@
void clearBufferQueue();
// Maximum number of pending buffers allocated by OutputTrack::write()
- static const uint8_t kMaxOverFlowBuffers = 3;
+ static const uint8_t kMaxOverFlowBuffers = 10;
Vector < Buffer* > mBufferQueue;
AudioBufferProvider::Buffer mOutBuffer;
- uint32_t mWaitTimeMs;
bool mActive;
-
+ DuplicatingThread* mSourceThread;
}; // end of OutputTrack
PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
@@ -520,6 +523,7 @@
virtual int type() const { return mType; }
void suspend() { mSuspended++; }
void restore() { if (mSuspended) mSuspended--; }
+ bool isSuspended() { return (mSuspended != 0); }
virtual String8 getParameters(const String8& keys);
virtual void audioConfigChanged(int event, int param = 0);
@@ -635,9 +639,16 @@
virtual bool threadLoop();
void addOutputTrack(MixerThread* thread);
void removeOutputTrack(MixerThread* thread);
+ uint32_t waitTimeMs() { return mWaitTimeMs; }
+ protected:
+ virtual uint32_t activeSleepTimeUs();
private:
+ bool outputsReady(SortedVector< sp<OutputTrack> > &outputTracks);
+ void updateWaitTime();
+
SortedVector < sp<OutputTrack> > mOutputTracks;
+ uint32_t mWaitTimeMs;
};
PlaybackThread *checkPlaybackThread_l(int output) const;