diff options
Diffstat (limited to 'services/audioflinger/Tracks.cpp')
-rw-r--r-- | services/audioflinger/Tracks.cpp | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index dc9f249..da2d634 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -903,9 +903,14 @@ status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& times mPreviousTimestampValid = false; return INVALID_OPERATION; } + // FIXME Not accurate under dynamic changes of sample rate and speed. + // Do not use track's mSampleRate as it is not current for mixer tracks. + uint32_t sampleRate = mAudioTrackServerProxy->getSampleRate(); + float speed, pitch; + mAudioTrackServerProxy->getPlaybackRate(&speed, &pitch); uint32_t unpresentedFrames = - ((int64_t) playbackThread->mLatchQ.mUnpresentedFrames * mSampleRate) / - playbackThread->mSampleRate; + ((double) playbackThread->mLatchQ.mUnpresentedFrames * sampleRate * speed) + / playbackThread->mSampleRate; // FIXME Since we're using a raw pointer as the key, it is theoretically possible // for a brand new track to share the same address as a recently destroyed // track, and thus for us to get the frames released of the wrong track. @@ -1861,13 +1866,14 @@ void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue() AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread, + audio_stream_type_t streamType, uint32_t sampleRate, audio_channel_mask_t channelMask, audio_format_t format, size_t frameCount, void *buffer, IAudioFlinger::track_flags_t flags) - : Track(playbackThread, NULL, AUDIO_STREAM_PATCH, + : Track(playbackThread, NULL, streamType, sampleRate, format, channelMask, frameCount, buffer, 0, 0, getuid(), flags, TYPE_PATCH), mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)) @@ -1989,29 +1995,30 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( ((flags & IAudioFlinger::TRACK_FAST) ? ALLOC_PIPE : ALLOC_CBLK) : ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE), type), - mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0), - // See real initialization of mRsmpInFront at RecordThread::start() - mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) + mOverflow(false), + mFramesToDrop(0) { if (mCblk == NULL) { return; } + mRecordBufferConverter = new RecordBufferConverter( + thread->mChannelMask, thread->mFormat, thread->mSampleRate, + channelMask, format, sampleRate); + // Check if the RecordBufferConverter construction was successful. + // If not, don't continue with construction. + // + // NOTE: It would be extremely rare that the record track cannot be created + // for the current device, but a pending or future device change would make + // the record track configuration valid. + if (mRecordBufferConverter->initCheck() != NO_ERROR) { + ALOGE("RecordTrack unable to create record buffer converter"); + return; + } + mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, mFrameSize, !isExternalTrack()); - - 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(AUDIO_FORMAT_PCM_16_BIT, - thread->mChannelCount, sampleRate); - // source SR - mResampler->setSampleRate(thread->mSampleRate); - mResampler->setVolume(AudioMixer::UNITY_GAIN_FLOAT, AudioMixer::UNITY_GAIN_FLOAT); - mResamplerBufferProvider = new ResamplerBufferProvider(this); - } + mResamplerBufferProvider = new ResamplerBufferProvider(this); if (flags & IAudioFlinger::TRACK_FAST) { ALOG_ASSERT(thread->mFastTrackAvail); @@ -2022,11 +2029,19 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { ALOGV("%s", __func__); - delete mResampler; - delete[] mRsmpOutBuffer; + delete mRecordBufferConverter; delete mResamplerBufferProvider; } +status_t AudioFlinger::RecordThread::RecordTrack::initCheck() const +{ + status_t status = TrackBase::initCheck(); + if (status == NO_ERROR && mServerProxy == 0) { + status = BAD_VALUE; + } + return status; +} + // AudioBufferProvider interface status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts __unused) |