diff options
Diffstat (limited to 'services/audioflinger/Tracks.cpp')
-rw-r--r-- | services/audioflinger/Tracks.cpp | 332 |
1 files changed, 228 insertions, 104 deletions
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index cbf56b5..f698fa2 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -35,6 +35,7 @@ #include <media/nbaio/Pipe.h> #include <media/nbaio/PipeReader.h> +#include <audio_utils/minifloat.h> // ---------------------------------------------------------------------------- @@ -70,7 +71,9 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( const sp<IMemory>& sharedBuffer, int sessionId, int clientUid, - bool isOut) + IAudioFlinger::track_flags_t flags, + bool isOut, + bool useReadOnlyHeap) : RefBase(), mThread(thread), mClient(client), @@ -80,11 +83,14 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mSampleRate(sampleRate), mFormat(format), mChannelMask(channelMask), - mChannelCount(popcount(channelMask)), + mChannelCount(isOut ? + audio_channel_count_from_out_mask(channelMask) : + audio_channel_count_from_in_mask(channelMask)), mFrameSize(audio_is_linear_pcm(format) ? mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)), mFrameCount(frameCount), mSessionId(sessionId), + mFlags(flags), mIsOut(isOut), mServerProxy(NULL), mId(android_atomic_inc(&nextTrackId)), @@ -111,18 +117,17 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); size_t size = sizeof(audio_track_cblk_t); size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize; - if (sharedBuffer == 0) { + if (sharedBuffer == 0 && !useReadOnlyHeap) { size += bufferSize; } if (client != 0) { mCblkMemory = client->heap()->allocate(size); - if (mCblkMemory != 0) { - mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); - // can't assume mCblk != NULL - } else { + if (mCblkMemory == 0 || + (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL) { ALOGE("not enough memory for AudioTrack size=%u", size); client->heap()->dump("AudioTrack"); + mCblkMemory.clear(); return; } } else { @@ -134,22 +139,37 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // construct the shared structure in-place. if (mCblk != NULL) { new(mCblk) audio_track_cblk_t(); - // clear all buffers - mCblk->frameCount_ = frameCount; - if (sharedBuffer == 0) { - mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); + if (useReadOnlyHeap) { + const sp<MemoryDealer> roHeap(thread->readOnlyHeap()); + if (roHeap == 0 || + (mBufferMemory = roHeap->allocate(bufferSize)) == 0 || + (mBuffer = mBufferMemory->pointer()) == NULL) { + ALOGE("not enough memory for read-only buffer size=%zu", bufferSize); + if (roHeap != 0) { + roHeap->dump("buffer"); + } + mCblkMemory.clear(); + mBufferMemory.clear(); + return; + } memset(mBuffer, 0, bufferSize); } else { - mBuffer = sharedBuffer->pointer(); + // clear all buffers + if (sharedBuffer == 0) { + mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); + memset(mBuffer, 0, bufferSize); + } else { + mBuffer = sharedBuffer->pointer(); #if 0 - mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic + mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic #endif + } } #ifdef TEE_SINK if (mTeeSinkTrackEnabled) { NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount); - if (pipeFormat != Format_Invalid) { + if (Format_isValid(pipeFormat)) { Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat); size_t numCounterOffers = 0; const NBAIO_Format offers[1] = {pipeFormat}; @@ -184,8 +204,8 @@ AudioFlinger::ThreadBase::TrackBase::~TrackBase() } mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to if (mClient != 0) { - // Client destructor must run with AudioFlinger mutex locked - Mutex::Autolock _l(mClient->audioFlinger()->mLock); + // Client destructor must run with AudioFlinger client mutex locked + Mutex::Autolock _l(mClient->audioFlinger()->mClientLock); // If the client's reference count drops to zero, the associated destructor // must run with AudioFlinger lock held. Thus the explicit clear() rather than // relying on the automatic clear() at end of scope. @@ -276,6 +296,11 @@ status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer, if (!mTrack->isTimedTrack()) return INVALID_OPERATION; + if (buffer == 0 || buffer->pointer() == NULL) { + ALOGE("queueTimedBuffer() buffer is 0 or has NULL pointer()"); + return BAD_VALUE; + } + PlaybackThread::TimedTrack* tt = reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get()); return tt->queueTimedBuffer(buffer, pts); @@ -330,7 +355,7 @@ AudioFlinger::PlaybackThread::Track::Track( int uid, IAudioFlinger::track_flags_t flags) : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, - sessionId, uid, true /*isOut*/), + sessionId, uid, flags, true /*isOut*/), mFillingUpStatus(FS_INVALID), // mRetryCount initialized later when needed mSharedBuffer(sharedBuffer), @@ -340,46 +365,46 @@ AudioFlinger::PlaybackThread::Track::Track( mAuxBuffer(NULL), mAuxEffectId(0), mHasVolumeController(false), mPresentationCompleteFrames(0), - mFlags(flags), mFastIndex(-1), mCachedVolume(1.0), mIsInvalid(false), mAudioTrackServerProxy(NULL), - mResumeToStopping(false) + mResumeToStopping(false), + mFlushHwPending(false) { - if (mCblk != NULL) { - if (sharedBuffer == 0) { - mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount, - mFrameSize); - } else { - mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount, - mFrameSize); - } - mServerProxy = mAudioTrackServerProxy; - // to avoid leaking a track name, do not allocate one unless there is an mCblk - mName = thread->getTrackName_l(channelMask, sessionId); - if (mName < 0) { - ALOGE("no more track names available"); - return; - } - // only allocate a fast track index if we were able to allocate a normal track name - if (flags & IAudioFlinger::TRACK_FAST) { - mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads(); - ALOG_ASSERT(thread->mFastTrackAvailMask != 0); - int i = __builtin_ctz(thread->mFastTrackAvailMask); - ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks); - // FIXME This is too eager. We allocate a fast track index before the - // fast track becomes active. Since fast tracks are a scarce resource, - // this means we are potentially denying other more important fast tracks from - // being created. It would be better to allocate the index dynamically. - mFastIndex = i; - // Read the initial underruns because this field is never cleared by the fast mixer - mObservedUnderruns = thread->getFastTrackUnderruns(i); - thread->mFastTrackAvailMask &= ~(1 << i); - } + if (mCblk == NULL) { + return; + } + + if (sharedBuffer == 0) { + mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount, + mFrameSize); + } else { + mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount, + mFrameSize); + } + mServerProxy = mAudioTrackServerProxy; + + mName = thread->getTrackName_l(channelMask, sessionId); + if (mName < 0) { + ALOGE("no more track names available"); + return; + } + // only allocate a fast track index if we were able to allocate a normal track name + if (flags & IAudioFlinger::TRACK_FAST) { + mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads(); + ALOG_ASSERT(thread->mFastTrackAvailMask != 0); + int i = __builtin_ctz(thread->mFastTrackAvailMask); + ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks); + // FIXME This is too eager. We allocate a fast track index before the + // fast track becomes active. Since fast tracks are a scarce resource, + // this means we are potentially denying other more important fast tracks from + // being created. It would be better to allocate the index dynamically. + mFastIndex = i; + // Read the initial underruns because this field is never cleared by the fast mixer + mObservedUnderruns = thread->getFastTrackUnderruns(i); + thread->mFastTrackAvailMask &= ~(1 << i); } - ALOGV("Track constructor name %d, calling pid %d", mName, - IPCThreadState::self()->getCallingPid()); } AudioFlinger::PlaybackThread::Track::~Track() @@ -397,6 +422,15 @@ AudioFlinger::PlaybackThread::Track::~Track() } } +status_t AudioFlinger::PlaybackThread::Track::initCheck() const +{ + status_t status = TrackBase::initCheck(); + if (status == NO_ERROR && mName < 0) { + status = NO_MEMORY; + } + return status; +} + void AudioFlinger::PlaybackThread::Track::destroy() { // NOTE: destroyTrack_l() can remove a strong reference to this Track @@ -423,17 +457,19 @@ void AudioFlinger::PlaybackThread::Track::destroy() /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result) { - result.append(" Name Client Type Fmt Chn mask Session fCount S F SRate " + result.append(" Name Active Client Type Fmt Chn mask Session fCount S F SRate " "L dB R dB Server Main buf Aux Buf Flags UndFrmCnt\n"); } -void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) +void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active) { - uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); + gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR(); if (isFastTrack()) { - sprintf(buffer, " F %2d", mFastIndex); + sprintf(buffer, " F %2d", mFastIndex); + } else if (mName >= AudioMixer::TRACK0) { + sprintf(buffer, " %4d", mName - AudioMixer::TRACK0); } else { - sprintf(buffer, " %4d", mName - AudioMixer::TRACK0); + sprintf(buffer, " none"); } track_state state = mState; char stateChar; @@ -488,8 +524,9 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) nowInUnderrun = '?'; break; } - snprintf(&buffer[7], size-7, " %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g " + snprintf(&buffer[8], size-8, " %6s %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g " "%08X %p %p 0x%03X %9u%c\n", + active ? "yes" : "no", (mClient == 0) ? getpid_cached : mClient->pid(), mStreamType, mFormat, @@ -499,8 +536,8 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) stateChar, mFillingUpStatus, mAudioTrackServerProxy->getSampleRate(), - 20.0 * log10((vlr & 0xFFFF) / 4096.0), - 20.0 * log10((vlr >> 16) / 4096.0), + 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))), + 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))), mCblk->mServer, mMainBuffer, mAuxBuffer, @@ -515,7 +552,7 @@ uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const { // AudioBufferProvider interface status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( - AudioBufferProvider::Buffer* buffer, int64_t pts) + AudioBufferProvider::Buffer* buffer, int64_t pts __unused) { ServerProxy::Buffer buf; size_t desiredFrames = buffer->frameCount; @@ -552,7 +589,14 @@ size_t AudioFlinger::PlaybackThread::Track::framesReleased() const // Don't call for fast tracks; the framesReady() could result in priority inversion bool AudioFlinger::PlaybackThread::Track::isReady() const { - if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing() || isStopping()) { + if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) { + return true; + } + + if (isStopping()) { + if (framesReady() > 0) { + mFillingUpStatus = FS_FILLED; + } return true; } @@ -565,8 +609,8 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { return false; } -status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event, - int triggerSession) +status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused, + int triggerSession __unused) { status_t status = NO_ERROR; ALOGV("start(%d), calling pid %d session %d", @@ -589,7 +633,10 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev // here the track could be either new, or restarted // in both cases "unstop" the track - if (state == PAUSED) { + // initial state-stopping. next state-pausing. + // What if resume is called ? + + if (state == PAUSED || state == PAUSING) { if (mResumeToStopping) { // happened we need to resume to STOPPING_1 mState = TrackBase::STOPPING_1; @@ -720,6 +767,7 @@ void AudioFlinger::PlaybackThread::Track::flush() mRetryCount = PlaybackThread::kMaxTrackRetriesOffload; } + mFlushHwPending = true; mResumeToStopping = false; } else { if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED && @@ -740,11 +788,19 @@ void AudioFlinger::PlaybackThread::Track::flush() // Prevent flush being lost if the track is flushed and then resumed // before mixer thread can run. This is important when offloading // because the hardware buffer could hold a large amount of audio - playbackThread->flushOutput_l(); playbackThread->broadcast_l(); } } +// must be called with thread lock held +void AudioFlinger::PlaybackThread::Track::flushAck() +{ + if (!isOffloaded()) + return; + + mFlushHwPending = false; +} + void AudioFlinger::PlaybackThread::Track::reset() { // Do not reset twice to avoid discarding data written just after a flush and before @@ -907,27 +963,27 @@ void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_ // implement VolumeBufferProvider interface -uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR() +gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR() { // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs ALOG_ASSERT(isFastTrack() && (mCblk != NULL)); - uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); - uint32_t vl = vlr & 0xFFFF; - uint32_t vr = vlr >> 16; + gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR(); + float vl = float_from_gain(gain_minifloat_unpack_left(vlr)); + float vr = float_from_gain(gain_minifloat_unpack_right(vlr)); // track volumes come from shared memory, so can't be trusted and must be clamped - if (vl > MAX_GAIN_INT) { - vl = MAX_GAIN_INT; + if (vl > GAIN_FLOAT_UNITY) { + vl = GAIN_FLOAT_UNITY; } - if (vr > MAX_GAIN_INT) { - vr = MAX_GAIN_INT; + if (vr > GAIN_FLOAT_UNITY) { + vr = GAIN_FLOAT_UNITY; } // now apply the cached master volume and stream type volume; // this is trusted but lacks any synchronization or barrier so may be stale float v = mCachedVolume; vl *= v; vr *= v; - // re-combine into U4.16 - vlr = (vr << 16) | (vl & 0xFFFF); + // re-combine into packed minifloat + vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr)); // FIXME look at mute, pause, and stop flags return vlr; } @@ -967,6 +1023,33 @@ void AudioFlinger::PlaybackThread::Track::signal() } } +//To be called with thread lock held +bool AudioFlinger::PlaybackThread::Track::isResumePending() { + + if (mState == RESUMING) + return true; + /* Resume is pending if track was stopping before pause was called */ + if (mState == STOPPING_1 && + mResumeToStopping) + return true; + + return false; +} + +//To be called with thread lock held +void AudioFlinger::PlaybackThread::Track::resumeAck() { + + + if (mState == RESUMING) + mState = ACTIVE; + + // Other possibility of pending resume is stopping_1 state + // Do not update the state from stopping as this prevents + // drain being called. + if (mState == STOPPING_1) { + mResumeToStopping = false; + } +} // ---------------------------------------------------------------------------- sp<AudioFlinger::PlaybackThread::TimedTrack> @@ -980,7 +1063,8 @@ AudioFlinger::PlaybackThread::TimedTrack::create( size_t frameCount, const sp<IMemory>& sharedBuffer, int sessionId, - int uid) { + int uid) +{ if (!client->reserveTimedTrack()) return 0; @@ -1046,15 +1130,14 @@ status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer( mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize, "AudioFlingerTimed"); - if (mTimedMemoryDealer == NULL) + if (mTimedMemoryDealer == NULL) { return NO_MEMORY; + } } sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size); - if (newBuffer == NULL) { - newBuffer = mTimedMemoryDealer->allocate(size); - if (newBuffer == NULL) - return NO_MEMORY; + if (newBuffer == 0 || newBuffer->pointer() == NULL) { + return NO_MEMORY; } *buffer = newBuffer; @@ -1153,7 +1236,7 @@ void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l( void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l( const TimedBuffer& buf, - const char* logTag) { + const char* logTag __unused) { uint32_t bufBytes = buf.buffer()->size(); uint32_t consumedAlready = buf.position(); @@ -1464,7 +1547,7 @@ void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer( mTrimQueueHeadOnRelease = false; } } else { - LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no" + LOG_ALWAYS_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no" " buffers in the timed buffer queue"); } @@ -1505,13 +1588,13 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, " - "mCblk->frameCount_ %u, mChannelMask 0x%08x", + "frameCount %u, mChannelMask 0x%08x", mCblk, mBuffer, - mCblk->frameCount_, mChannelMask); + frameCount, mChannelMask); // since client and server are in the same process, // the buffer has the same virtual address on both sides mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize); - mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000)); + mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY); mClientProxy->setSendLevel(0.0); mClientProxy->setSampleRate(sampleRate); mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize, @@ -1722,10 +1805,6 @@ AudioFlinger::RecordHandle::~RecordHandle() { mRecordTrack->destroy(); } -sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { - return mRecordTrack->getCblk(); -} - status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event, int triggerSession) { ALOGV("RecordHandle::start()"); @@ -1749,7 +1828,7 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- -// RecordTrack constructor must be called with AudioFlinger::mLock held +// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held AudioFlinger::RecordThread::RecordTrack::RecordTrack( RecordThread *thread, const sp<Client>& client, @@ -1758,27 +1837,46 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( audio_channel_mask_t channelMask, size_t frameCount, int sessionId, - int uid) + int uid, + IAudioFlinger::track_flags_t flags) : TrackBase(thread, client, sampleRate, format, - channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/), - mOverflow(false) + channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, + flags, false /*isOut*/, + (flags & IAudioFlinger::TRACK_FAST) != 0 /*useReadOnlyHeap*/), + mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0), + // See real initialization of mRsmpInFront at RecordThread::start() + mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) { - ALOGV("RecordTrack constructor"); - if (mCblk != NULL) { - mAudioRecordServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, - mFrameSize); - mServerProxy = mAudioRecordServerProxy; + if (mCblk == NULL) { + return; + } + + mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, mFrameSize); + + uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); + // FIXME I don't understand either of the channel count checks + if (thread->mSampleRate != sampleRate && thread->mChannelCount <= FCC_2 && + channelCount <= FCC_2) { + // sink SR + mResampler = AudioResampler::create(16, thread->mChannelCount, sampleRate); + // source SR + mResampler->setSampleRate(thread->mSampleRate); + mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN); + mResamplerBufferProvider = new ResamplerBufferProvider(this); } } AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { ALOGV("%s", __func__); + delete mResampler; + delete[] mRsmpOutBuffer; + delete mResamplerBufferProvider; } // AudioBufferProvider interface status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, - int64_t pts) + int64_t pts __unused) { ServerProxy::Buffer buf; buf.mFrameCount = buffer->frameCount; @@ -1846,19 +1944,45 @@ void AudioFlinger::RecordThread::RecordTrack::invalidate() /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) { - result.append("Client Fmt Chn mask Session S Server fCount\n"); + result.append(" Active Client Fmt Chn mask Session S Server fCount Resampling\n"); } -void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) +void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bool active) { - snprintf(buffer, size, "%6u %3u %08X %7u %1d %08X %6zu\n", + snprintf(buffer, size, " %6s %6u %3u %08X %7u %1d %08X %6zu %10d\n", + active ? "yes" : "no", (mClient == 0) ? getpid_cached : mClient->pid(), mFormat, mChannelMask, mSessionId, mState, mCblk->mServer, - mFrameCount); + mFrameCount, + mResampler != NULL); + +} + +void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event) +{ + if (event == mSyncStartEvent) { + ssize_t framesToDrop = 0; + sp<ThreadBase> threadBase = mThread.promote(); + if (threadBase != 0) { + // TODO: use actual buffer filling status instead of 2 buffers when info is available + // from audio HAL + framesToDrop = threadBase->mFrameCount * 2; + } + mFramesToDrop = framesToDrop; + } +} + +void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent() +{ + if (mSyncStartEvent != 0) { + mSyncStartEvent->cancel(); + mSyncStartEvent.clear(); + } + mFramesToDrop = 0; } }; // namespace android |