diff options
Diffstat (limited to 'media/libmedia/AudioTrack.cpp')
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 213 |
1 files changed, 112 insertions, 101 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d51cd69..8c33f41 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1,4 +1,4 @@ -/* //device/extlibs/pv/android/AudioTrack.cpp +/* frameworks/base/media/libmedia/AudioTrack.cpp ** ** Copyright 2007, The Android Open Source Project ** @@ -38,12 +38,12 @@ #include <utils/Atomic.h> #include <cutils/bitops.h> +#include <cutils/compiler.h> #include <system/audio.h> #include <system/audio_policy.h> -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) +#include <audio_utils/primitives.h> namespace android { // --------------------------------------------------------------------------- @@ -51,7 +51,7 @@ namespace android { // static status_t AudioTrack::getMinFrameCount( int* frameCount, - int streamType, + audio_stream_type_t streamType, uint32_t sampleRate) { int afSampleRate; @@ -79,14 +79,15 @@ status_t AudioTrack::getMinFrameCount( // --------------------------------------------------------------------------- AudioTrack::AudioTrack() - : mStatus(NO_INIT) + : mStatus(NO_INIT), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) { } AudioTrack::AudioTrack( - int streamType, + audio_stream_type_t streamType, uint32_t sampleRate, - int format, + audio_format_t format, int channelMask, int frameCount, uint32_t flags, @@ -94,7 +95,8 @@ AudioTrack::AudioTrack( void* user, int notificationFrames, int sessionId) - : mStatus(NO_INIT) + : mStatus(NO_INIT), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -106,13 +108,33 @@ AudioTrack::AudioTrack( uint32_t sampleRate, int format, int channelMask, + int frameCount, + uint32_t flags, + callback_t cbf, + void* user, + int notificationFrames, + int sessionId) + : mStatus(NO_INIT), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) +{ + mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format, channelMask, + frameCount, flags, cbf, user, notificationFrames, + 0, false, sessionId); +} + +AudioTrack::AudioTrack( + audio_stream_type_t streamType, + uint32_t sampleRate, + audio_format_t format, + int channelMask, const sp<IMemory>& sharedBuffer, uint32_t flags, callback_t cbf, void* user, int notificationFrames, int sessionId) - : mStatus(NO_INIT) + : mStatus(NO_INIT), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) { mStatus = set(streamType, sampleRate, format, channelMask, 0, flags, cbf, user, notificationFrames, @@ -139,9 +161,9 @@ AudioTrack::~AudioTrack() } status_t AudioTrack::set( - int streamType, + audio_stream_type_t streamType, uint32_t sampleRate, - int format, + audio_format_t format, int channelMask, int frameCount, uint32_t flags, @@ -178,7 +200,7 @@ status_t AudioTrack::set( sampleRate = afSampleRate; } // these below should probably come from the audioFlinger too... - if (format == 0) { + if (format == AUDIO_FORMAT_DEFAULT) { format = AUDIO_FORMAT_PCM_16_BIT; } if (channelMask == 0) { @@ -203,8 +225,8 @@ status_t AudioTrack::set( uint32_t channelCount = popcount(channelMask); audio_io_handle_t output = AudioSystem::getOutput( - (audio_stream_type_t)streamType, - sampleRate,format, channelMask, + streamType, + sampleRate, format, channelMask, (audio_policy_output_flags_t)flags); if (output == 0) { @@ -214,7 +236,7 @@ status_t AudioTrack::set( mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; - mSendLevel = 0; + mSendLevel = 0.0f; mFrameCount = frameCount; mNotificationFramesReq = notificationFrames; mSessionId = sessionId; @@ -223,7 +245,7 @@ status_t AudioTrack::set( // create the IAudioTrack status_t status = createTrack_l(streamType, sampleRate, - (uint32_t)format, + format, (uint32_t)channelMask, frameCount, flags, @@ -235,23 +257,19 @@ status_t AudioTrack::set( return status; } - if (cbf != 0) { + if (cbf != NULL) { mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); - if (mAudioTrackThread == 0) { - ALOGE("Could not create callback thread"); - return NO_INIT; - } } mStatus = NO_ERROR; mStreamType = streamType; - mFormat = (uint32_t)format; + mFormat = format; mChannelMask = (uint32_t)channelMask; mChannelCount = channelCount; mSharedBuffer = sharedBuffer; mMuted = false; - mActive = 0; + mActive = false; mCbf = cbf; mUserData = user; mLoopCount = 0; @@ -278,12 +296,12 @@ uint32_t AudioTrack::latency() const return mLatency; } -int AudioTrack::streamType() const +audio_stream_type_t AudioTrack::streamType() const { return mStreamType; } -int AudioTrack::format() const +audio_format_t AudioTrack::format() const { return mFormat; } @@ -298,7 +316,7 @@ uint32_t AudioTrack::frameCount() const return mCblk->frameCount; } -int AudioTrack::frameSize() const +size_t AudioTrack::frameSize() const { if (audio_is_linear_pcm(mFormat)) { return channelCount()*audio_bytes_per_sample(mFormat); @@ -337,18 +355,20 @@ void AudioTrack::start() sp <IMemory> iMem = mCblkMemory; audio_track_cblk_t* cblk = mCblk; - if (mActive == 0) { + if (!mActive) { mFlushed = false; - mActive = 1; + mActive = true; mNewPosition = cblk->server + mUpdatePeriod; cblk->lock.lock(); cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; cblk->waitTimeMs = 0; android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags); if (t != 0) { - t->run("AudioTrackThread", ANDROID_PRIORITY_AUDIO); + t->run("AudioTrackThread", ANDROID_PRIORITY_AUDIO); } else { - setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO); + mPreviousPriority = getpriority(PRIO_PROCESS, 0); + mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0); + androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); } ALOGV("start %p before lock cblk %p", this, mCblk); @@ -366,11 +386,12 @@ void AudioTrack::start() cblk->lock.unlock(); if (status != NO_ERROR) { ALOGV("start() failed"); - mActive = 0; + mActive = false; if (t != 0) { t->requestExit(); } else { - setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); + setpriority(PRIO_PROCESS, 0, mPreviousPriority); + androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup); } } } @@ -390,8 +411,8 @@ void AudioTrack::stop() } AutoMutex lock(mLock); - if (mActive == 1) { - mActive = 0; + if (mActive) { + mActive = false; mCblk->cv.signal(); mAudioTrack->stop(); // Cancel loops (If we are in the middle of a loop, playback @@ -408,7 +429,8 @@ void AudioTrack::stop() if (t != 0) { t->requestExit(); } else { - setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); + setpriority(PRIO_PROCESS, 0, mPreviousPriority); + androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup); } } @@ -419,7 +441,8 @@ void AudioTrack::stop() bool AudioTrack::stopped() const { - return !mActive; + AutoMutex lock(mLock); + return stopped_l(); } void AudioTrack::flush() @@ -451,8 +474,8 @@ void AudioTrack::pause() { ALOGV("pause"); AutoMutex lock(mLock); - if (mActive == 1) { - mActive = 0; + if (mActive) { + mActive = false; mAudioTrack->pause(); } } @@ -470,7 +493,7 @@ bool AudioTrack::muted() const status_t AudioTrack::setVolume(float left, float right) { - if (left > 1.0f || right > 1.0f) { + if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) { return BAD_VALUE; } @@ -478,8 +501,7 @@ status_t AudioTrack::setVolume(float left, float right) mVolume[LEFT] = left; mVolume[RIGHT] = right; - // write must be atomic - mCblk->volumeLR = (uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000); + mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); return NO_ERROR; } @@ -497,14 +519,14 @@ void AudioTrack::getVolume(float* left, float* right) status_t AudioTrack::setAuxEffectSendLevel(float level) { ALOGV("setAuxEffectSendLevel(%f)", level); - if (level > 1.0f) { + if (level < 0.0f || level > 1.0f) { return BAD_VALUE; } AutoMutex lock(mLock); mSendLevel = level; - mCblk->sendLevel = uint16_t(level * 0x1000); + mCblk->setSendLevel(level); return NO_ERROR; } @@ -582,13 +604,13 @@ status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCou status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount) { AutoMutex lock(mLock); - if (loopStart != 0) { + if (loopStart != NULL) { *loopStart = mCblk->loopStart; } - if (loopEnd != 0) { + if (loopEnd != NULL) { *loopEnd = mCblk->loopEnd; } - if (loopCount != 0) { + if (loopCount != NULL) { if (mCblk->loopCount < 0) { *loopCount = -1; } else { @@ -601,7 +623,7 @@ status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCo status_t AudioTrack::setMarkerPosition(uint32_t marker) { - if (mCbf == 0) return INVALID_OPERATION; + if (mCbf == NULL) return INVALID_OPERATION; mMarkerPosition = marker; mMarkerReached = false; @@ -611,7 +633,7 @@ status_t AudioTrack::setMarkerPosition(uint32_t marker) status_t AudioTrack::getMarkerPosition(uint32_t *marker) { - if (marker == 0) return BAD_VALUE; + if (marker == NULL) return BAD_VALUE; *marker = mMarkerPosition; @@ -620,7 +642,7 @@ status_t AudioTrack::getMarkerPosition(uint32_t *marker) status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) { - if (mCbf == 0) return INVALID_OPERATION; + if (mCbf == NULL) return INVALID_OPERATION; uint32_t curPosition; getPosition(&curPosition); @@ -632,7 +654,7 @@ status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) { - if (updatePeriod == 0) return BAD_VALUE; + if (updatePeriod == NULL) return BAD_VALUE; *updatePeriod = mUpdatePeriod; @@ -642,9 +664,10 @@ status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) status_t AudioTrack::setPosition(uint32_t position) { AutoMutex lock(mLock); - Mutex::Autolock _l(mCblk->lock); - if (!stopped()) return INVALID_OPERATION; + if (!stopped_l()) return INVALID_OPERATION; + + Mutex::Autolock _l(mCblk->lock); if (position > mCblk->user) return BAD_VALUE; @@ -656,7 +679,7 @@ status_t AudioTrack::setPosition(uint32_t position) status_t AudioTrack::getPosition(uint32_t *position) { - if (position == 0) return BAD_VALUE; + if (position == NULL) return BAD_VALUE; AutoMutex lock(mLock); *position = mFlushed ? 0 : mCblk->server; @@ -667,7 +690,7 @@ status_t AudioTrack::reload() { AutoMutex lock(mLock); - if (!stopped()) return INVALID_OPERATION; + if (!stopped_l()) return INVALID_OPERATION; flush_l(); @@ -685,7 +708,7 @@ audio_io_handle_t AudioTrack::getOutput() // must be called with mLock held audio_io_handle_t AudioTrack::getOutput_l() { - return AudioSystem::getOutput((audio_stream_type_t)mStreamType, + return AudioSystem::getOutput(mStreamType, mCblk->sampleRate, mFormat, mChannelMask, (audio_policy_output_flags_t)mFlags); } @@ -708,9 +731,9 @@ status_t AudioTrack::attachAuxEffect(int effectId) // must be called with mLock held status_t AudioTrack::createTrack_l( - int streamType, + audio_stream_type_t streamType, uint32_t sampleRate, - uint32_t format, + audio_format_t format, uint32_t channelMask, int frameCount, uint32_t flags, @@ -802,9 +825,7 @@ status_t AudioTrack::createTrack_l( ALOGE("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()); android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags); @@ -816,8 +837,8 @@ status_t AudioTrack::createTrack_l( mCblk->stepUser(mCblk->frameCount); } - mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000); - mCblk->sendLevel = uint16_t(mSendLevel * 0x1000); + mCblk->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000)); + mCblk->setSendLevel(mSendLevel); mAudioTrack->attachAuxEffect(mAuxEffectId); mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; @@ -829,7 +850,7 @@ status_t AudioTrack::createTrack_l( status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { AutoMutex lock(mLock); - int active; + bool active; status_t result = NO_ERROR; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = audioBuffer->frameCount; @@ -851,12 +872,12 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) goto start_loop_here; while (framesAvail == 0) { active = mActive; - if (UNLIKELY(!active)) { + if (CC_UNLIKELY(!active)) { ALOGV("Not active and NO_MORE_BUFFERS"); cblk->lock.unlock(); return NO_MORE_BUFFERS; } - if (UNLIKELY(!waitCount)) { + if (CC_UNLIKELY(!waitCount)) { cblk->lock.unlock(); return WOULD_BLOCK; } @@ -865,7 +886,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); cblk->lock.unlock(); mLock.lock(); - if (mActive == 0) { + if (!mActive) { return status_t(STOPPED); } cblk->lock.lock(); @@ -874,7 +895,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) if (cblk->flags & CBLK_INVALID_MSK) { goto create_new_track; } - if (__builtin_expect(result!=NO_ERROR, false)) { + if (CC_UNLIKELY(result != NO_ERROR)) { cblk->waitTimeMs += waitTimeMs; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { // timing out when a loop has been set and we have already written upto loop end @@ -978,7 +999,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) ssize_t written = 0; const int8_t *src = (const int8_t *)buffer; Buffer audioBuffer; - size_t frameSz = (size_t)frameSize(); + size_t frameSz = frameSize(); do { audioBuffer.frameCount = userSize/frameSz; @@ -998,12 +1019,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) { // Divide capacity by 2 to take expansion into account toWrite = audioBuffer.size>>1; - // 8 to 16 bit conversion - int count = toWrite; - int16_t *dst = (int16_t *)(audioBuffer.i8); - while(count--) { - *dst++ = (int16_t)(*src++^0x80) << 8; - } + memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) src, toWrite); } else { toWrite = audioBuffer.size; memcpy(audioBuffer.i8, src, toWrite); @@ -1032,10 +1048,11 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) sp <IAudioTrack> audioTrack = mAudioTrack; sp <IMemory> iMem = mCblkMemory; audio_track_cblk_t* cblk = mCblk; + bool active = mActive; mLock.unlock(); // Manage underrun callback - if (mActive && (cblk->framesAvailable() == cblk->frameCount)) { + if (active && (cblk->framesAvailable() == cblk->frameCount)) { ALOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { mCbf(EVENT_UNDERRUN, mUserData, 0); @@ -1123,19 +1140,14 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) if (writtenSize > reqSize) writtenSize = reqSize; if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) { - // 8 to 16 bit conversion - const int8_t *src = audioBuffer.i8 + writtenSize-1; - int count = writtenSize; - int16_t *dst = audioBuffer.i16 + writtenSize-1; - while(count--) { - *dst-- = (int16_t)(*src--^0x80) << 8; - } + // 8 to 16 bit conversion, note that source and destination are the same address + memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) audioBuffer.i8, writtenSize); writtenSize <<= 1; } audioBuffer.size = writtenSize; // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for - // 8 bit PCM data: in this case, mCblk->frameSize is based on a sampel size of + // 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of // 16 bit. audioBuffer.frameCount = writtenSize/mCblk->frameSize; @@ -1307,15 +1319,15 @@ void AudioTrack::AudioTrackThread::onFirstRef() audio_track_cblk_t::audio_track_cblk_t() : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0), - userBase(0), serverBase(0), buffers(0), frameCount(0), - loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), - sendLevel(0), flags(0) + userBase(0), serverBase(0), buffers(NULL), frameCount(0), + loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000), + mSendLevel(0), flags(0) { } uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) { - uint32_t u = this->user; + uint32_t u = user; u += frameCount; // Ensure that user is never ahead of server for AudioRecord @@ -1324,16 +1336,16 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; } - } else if (u > this->server) { - ALOGW("stepServer occured after track reset"); - u = this->server; + } else if (u > server) { + ALOGW("stepServer occurred after track reset"); + u = server; } if (u >= userBase + this->frameCount) { userBase += this->frameCount; } - this->user = u; + user = u; // Clear flow control error condition as new data has been written/read to/from buffer. if (flags & CBLK_UNDERRUN_MSK) { @@ -1350,7 +1362,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) return false; } - uint32_t s = this->server; + uint32_t s = server; s += frameCount; if (flags & CBLK_DIRECTION_MSK) { @@ -1363,9 +1375,9 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) // while the mixer is processing a block: in this case, // stepServer() is called After the flush() has reset u & s and // we have s > u - if (s > this->user) { - ALOGW("stepServer occured after track reset"); - s = this->user; + if (s > user) { + ALOGW("stepServer occurred after track reset"); + s = user; } } @@ -1381,7 +1393,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) serverBase += this->frameCount; } - this->server = s; + server = s; if (!(flags & CBLK_INVALID_MSK)) { cv.signal(); @@ -1392,7 +1404,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) void* audio_track_cblk_t::buffer(uint32_t offset) const { - return (int8_t *)this->buffers + (offset - userBase) * this->frameSize; + return (int8_t *)buffers + (offset - userBase) * frameSize; } uint32_t audio_track_cblk_t::framesAvailable() @@ -1403,8 +1415,8 @@ uint32_t audio_track_cblk_t::framesAvailable() uint32_t audio_track_cblk_t::framesAvailable_l() { - uint32_t u = this->user; - uint32_t s = this->server; + uint32_t u = user; + uint32_t s = server; if (flags & CBLK_DIRECTION_MSK) { uint32_t limit = (s < loopStart) ? s : loopStart; @@ -1416,8 +1428,8 @@ uint32_t audio_track_cblk_t::framesAvailable_l() uint32_t audio_track_cblk_t::framesReady() { - uint32_t u = this->user; - uint32_t s = this->server; + uint32_t u = user; + uint32_t s = server; if (flags & CBLK_DIRECTION_MSK) { if (u < loopEnd) { @@ -1462,4 +1474,3 @@ bool audio_track_cblk_t::tryLock() // ------------------------------------------------------------------------- }; // namespace android - |