diff options
Diffstat (limited to 'media/libmedia/AudioTrack.cpp')
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 266 |
1 files changed, 218 insertions, 48 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index fa52fa9..a2172c9 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -2,6 +2,10 @@ ** ** Copyright 2007, The Android Open Source Project ** +** Copyright (c) 2012, The Linux Foundation. All rights reserved. +** Not a Contribution, Apache license notifications and license are retained +** for attribution purposes only. + ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at @@ -96,6 +100,10 @@ AudioTrack::AudioTrack() mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) +#ifdef QCOM_HARDWARE + ,mAudioFlinger(NULL), + mObserver(NULL) +#endif { } @@ -114,6 +122,10 @@ AudioTrack::AudioTrack( mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) +#ifdef QCOM_HARDWARE + ,mAudioFlinger(NULL), + mObserver(NULL) +#endif { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -135,6 +147,10 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) +#ifdef QCOM_HARDWARE + ,mAudioFlinger(NULL), + mObserver(NULL) +#endif { mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format, (audio_channel_mask_t) channelMask, @@ -157,6 +173,10 @@ AudioTrack::AudioTrack( mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) +#ifdef QCOM_HARDWARE + ,mAudioFlinger(NULL), + mObserver(NULL) +#endif { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, @@ -177,9 +197,22 @@ AudioTrack::~AudioTrack() mAudioTrackThread->requestExitAndWait(); mAudioTrackThread.clear(); } +#ifdef QCOM_HARDWARE + if (mAudioTrack != 0) { + mAudioTrack.clear(); + AudioSystem::releaseAudioSessionId(mSessionId); + } + + if (mDirectTrack != 0) { + mDirectTrack.clear(); + } +#else mAudioTrack.clear(); +#endif IPCThreadState::self()->flushCommands(); +#ifndef QCOM_HARDWARE AudioSystem::releaseAudioSessionId(mSessionId); +#endif } } @@ -252,12 +285,24 @@ status_t AudioTrack::set( flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); } +#ifdef QCOM_ENHANCED_AUDIO + if ((streamType == AUDIO_STREAM_VOICE_CALL) + && (channelMask == AUDIO_CHANNEL_OUT_MONO) + && ((sampleRate == 8000 || sampleRate == 16000))) + { + ALOGD("Turn on Direct Output for VOIP RX"); + flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_VOIP_RX|AUDIO_OUTPUT_FLAG_DIRECT); + } +#endif + if (!audio_is_output_channel(channelMask)) { ALOGE("Invalid channel mask %#x", channelMask); return BAD_VALUE; } uint32_t channelCount = popcount(channelMask); + ALOGV("AudioTrack getOutput streamType %d, sampleRate %d, format %d, channelMask %d, flags %x", + streamType, sampleRate, format, channelMask, flags); audio_io_handle_t output = AudioSystem::getOutput( streamType, sampleRate, format, channelMask, @@ -278,46 +323,86 @@ status_t AudioTrack::set( mFlags = flags; mCbf = cbf; - if (cbf != NULL) { - mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); - mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/); - } - - // create the IAudioTrack - status_t status = createTrack_l(streamType, - sampleRate, - format, - channelMask, - frameCount, - flags, - sharedBuffer, - output); +#ifdef QCOM_HARDWARE + if (flags & AUDIO_OUTPUT_FLAG_LPA || flags & AUDIO_OUTPUT_FLAG_TUNNEL) { + ALOGV("Creating Direct Track"); + const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); + if (audioFlinger == 0) { + ALOGE("Could not get audioflinger"); + return NO_INIT; + } + mAudioFlinger = audioFlinger; + status_t status = NO_ERROR; + mAudioDirectOutput = output; + mDirectTrack = audioFlinger->createDirectTrack( getpid(), + sampleRate, + channelMask, + mAudioDirectOutput, + &mSessionId, + this, + streamType, + &status); + if(status != NO_ERROR) { + ALOGE("createDirectTrack returned with status %d", status); + return status; + } + mAudioTrack = NULL; + mSharedBuffer = NULL; + } + else { +#endif + if (cbf != NULL) { + mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); + mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/); + } + // create the IAudioTrack + status_t status = createTrack_l(streamType, + sampleRate, + format, + channelMask, + frameCount, + flags, + sharedBuffer, + output); - if (status != NO_ERROR) { - if (mAudioTrackThread != 0) { - mAudioTrackThread->requestExit(); - mAudioTrackThread.clear(); + if (status != NO_ERROR) { + if (mAudioTrackThread != 0) { + mAudioTrackThread->requestExit(); + mAudioTrackThread.clear(); + } + return status; } - return status; +#ifdef QCOM_HARDWARE + AudioSystem::acquireAudioSessionId(mSessionId); + mAudioDirectOutput = -1; + mDirectTrack = NULL; + mSharedBuffer = sharedBuffer; } - + mUserData = user; +#endif mStatus = NO_ERROR; mStreamType = streamType; mFormat = format; mChannelMask = channelMask; mChannelCount = channelCount; - mSharedBuffer = sharedBuffer; + mMuted = false; mActive = false; - mUserData = user; + mLoopCount = 0; mMarkerPosition = 0; mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; mFlushed = false; + +#ifndef QCOM_HARDWARE + mSharedBuffer = sharedBuffer; + mUserData = user; AudioSystem::acquireAudioSessionId(mSessionId); +#endif + mRestoreStatus = NO_ERROR; return NO_ERROR; } @@ -331,6 +416,11 @@ status_t AudioTrack::initCheck() const uint32_t AudioTrack::latency() const { +#ifdef QCOM_HARDWARE + if(mAudioDirectOutput != -1) { + return mAudioFlinger->latency(mAudioDirectOutput); + } +#endif return mLatency; } @@ -351,6 +441,11 @@ int AudioTrack::channelCount() const uint32_t AudioTrack::frameCount() const { +#ifdef QCOM_HARDWARE + if(mAudioDirectOutput != -1) { + return mAudioFlinger->frameCount(mAudioDirectOutput); + } +#endif return mCblk->frameCount; } @@ -372,6 +467,16 @@ sp<IMemory>& AudioTrack::sharedBuffer() void AudioTrack::start() { +#ifdef QCOM_HARDWARE + if (mDirectTrack != NULL) { + if(mActive == 0) { + mActive = 1; + mDirectTrack->start(); + } + return; + } +#endif + sp<AudioTrackThread> t = mAudioTrackThread; ALOGV("start %p", this); @@ -436,26 +541,35 @@ void AudioTrack::stop() AutoMutex lock(mLock); if (mActive) { - mActive = false; - mCblk->cv.signal(); - mAudioTrack->stop(); - // Cancel loops (If we are in the middle of a loop, playback - // would not stop until loopCount reaches 0). - setLoop_l(0, 0, 0); - // the playback head position will reset to 0, so if a marker is set, we need - // to activate it again - mMarkerReached = false; - // Force flush if a shared buffer is used otherwise audioflinger - // will not stop before end of buffer is reached. - if (mSharedBuffer != 0) { - flush_l(); - } - if (t != 0) { - t->pause(); - } else { - setpriority(PRIO_PROCESS, 0, mPreviousPriority); - set_sched_policy(0, mPreviousSchedulingGroup); +#ifdef QCOM_HARDWARE + if(mDirectTrack != NULL) { + mActive = false; + mDirectTrack->stop(); + } else if (mAudioTrack != NULL) { +#endif + mActive = false; + mCblk->cv.signal(); + mAudioTrack->stop(); + // Cancel loops (If we are in the middle of a loop, playback + // would not stop until loopCount reaches 0). + setLoop_l(0, 0, 0); + // the playback head position will reset to 0, so if a marker is set, we need + // to activate it again + mMarkerReached = false; + // Force flush if a shared buffer is used otherwise audioflinger + // will not stop before end of buffer is reached. + if (mSharedBuffer != 0) { + flush_l(); + } + if (t != 0) { + t->pause(); + } else { + setpriority(PRIO_PROCESS, 0, mPreviousPriority); + set_sched_policy(0, mPreviousSchedulingGroup); + } +#ifdef QCOM_HARDWARE } +#endif } } @@ -469,7 +583,12 @@ bool AudioTrack::stopped() const void AudioTrack::flush() { AutoMutex lock(mLock); - flush_l(); +#ifdef QCOM_HARDWARE + if(mDirectTrack != NULL) { + mDirectTrack->flush(); + } else +#endif + flush_l(); } // must be called with mLock held @@ -497,14 +616,28 @@ void AudioTrack::pause() AutoMutex lock(mLock); if (mActive) { mActive = false; - mCblk->cv.signal(); - mAudioTrack->pause(); +#ifdef QCOM_HARDWARE + if(mDirectTrack != NULL) { + ALOGV("mDirectTrack pause"); + mDirectTrack->pause(); + } else { +#endif + mCblk->cv.signal(); + mAudioTrack->pause(); +#ifdef QCOM_HARDWARE + } +#endif } } void AudioTrack::mute(bool e) { - mAudioTrack->mute(e); +#ifdef QCOM_HARDWARE + if(mDirectTrack != NULL) { + mDirectTrack->mute(e); + } else +#endif + mAudioTrack->mute(e); mMuted = e; } @@ -522,8 +655,13 @@ status_t AudioTrack::setVolume(float left, float right) AutoMutex lock(mLock); mVolume[LEFT] = left; mVolume[RIGHT] = right; - - mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); +#ifdef QCOM_HARDWARE + if(mDirectTrack != NULL) { + ALOGV("mDirectTrack->setVolume(left = %f , right = %f)", left,right); + mDirectTrack->setVolume(left, right); + } else +#endif + mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); return NO_ERROR; } @@ -540,6 +678,11 @@ void AudioTrack::getVolume(float* left, float* right) const status_t AudioTrack::setAuxEffectSendLevel(float level) { +#ifdef QCOM_HARDWARE + if (mDirectTrack != NULL) { + return NO_ERROR; + } +#endif ALOGV("setAuxEffectSendLevel(%f)", level); if (level < 0.0f || level > 1.0f) { return BAD_VALUE; @@ -586,6 +729,11 @@ uint32_t AudioTrack::getSampleRate() const } AutoMutex lock(mLock); +#ifdef QCOM_HARDWARE + if(mAudioDirectOutput != -1) { + return mAudioFlinger->sampleRate(mAudioDirectOutput); + } +#endif return mCblk->sampleRate; } @@ -1076,7 +1224,12 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) ssize_t AudioTrack::write(const void* buffer, size_t userSize) { - +#ifdef QCOM_HARDWARE + if (mDirectTrack != NULL) { + mDirectTrack->write(buffer,userSize); + return userSize; + } +#endif if (mSharedBuffer != 0) return INVALID_OPERATION; if (mIsTimed) return INVALID_OPERATION; @@ -1456,6 +1609,23 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const return NO_ERROR; } +#ifdef QCOM_HARDWARE +void AudioTrack::notify(int msg) { + if (msg == EVENT_UNDERRUN) { + ALOGV("Posting event underrun to Audio Sink."); + mCbf(EVENT_UNDERRUN, mUserData, 0); + } +} + +status_t AudioTrack::getTimeStamp(uint64_t *tstamp) { + if (mDirectTrack != NULL) { + *tstamp = mDirectTrack->getTimeStamp(); + ALOGV("Timestamp %lld ", *tstamp); + } + return NO_ERROR; +} +#endif + // ========================================================================= AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava) |