diff options
author | John Grossman <johngro@google.com> | 2012-02-08 16:37:41 -0800 |
---|---|---|
committer | John Grossman <johngro@google.com> | 2012-02-16 13:45:11 -0800 |
commit | 4ff14bae91075eb274eb1c2975982358946e7e63 (patch) | |
tree | e9e54fddb9832d30b69c2a11c9ed2884397f2f95 /media | |
parent | 951bd8d1ad9581a414e171ad8605a9515d0ad667 (diff) | |
download | frameworks_av-4ff14bae91075eb274eb1c2975982358946e7e63.zip frameworks_av-4ff14bae91075eb274eb1c2975982358946e7e63.tar.gz frameworks_av-4ff14bae91075eb274eb1c2975982358946e7e63.tar.bz2 |
Upintegrate Audio Flinger changes from ICS_AAH
Bring in changes to audio flinger made to support timed audio tracks
and HW master volume control.
Change-Id: Ide52d48809bdbed13acf35fd59b24637e35064ae
Signed-off-by: John Grossman <johngro@google.com>
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 81 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 5 | ||||
-rw-r--r-- | media/libmedia/IAudioTrack.cpp | 81 |
3 files changed, 161 insertions, 6 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index aead9a1..74c97ed 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -80,7 +80,9 @@ status_t AudioTrack::getMinFrameCount( AudioTrack::AudioTrack() : mStatus(NO_INIT), - mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) + mIsTimed(false), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), + mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) { } @@ -96,7 +98,9 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId) : mStatus(NO_INIT), - mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) + mIsTimed(false), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), + mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -134,7 +138,9 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId) : mStatus(NO_INIT), - mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) + mIsTimed(false), + mPreviousPriority(ANDROID_PRIORITY_NORMAL), + mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT) { mStatus = set(streamType, sampleRate, format, channelMask, 0, flags, cbf, user, notificationFrames, @@ -540,6 +546,10 @@ status_t AudioTrack::setSampleRate(int rate) { int afSamplingRate; + if (mIsTimed) { + return INVALID_OPERATION; + } + if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { return NO_INIT; } @@ -553,6 +563,10 @@ status_t AudioTrack::setSampleRate(int rate) uint32_t AudioTrack::getSampleRate() const { + if (mIsTimed) { + return INVALID_OPERATION; + } + AutoMutex lock(mLock); return mCblk->sampleRate; } @@ -578,6 +592,10 @@ status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCou return NO_ERROR; } + if (mIsTimed) { + return INVALID_OPERATION; + } + if (loopStart >= loopEnd || loopEnd - loopStart > cblk->frameCount || cblk->server > loopStart) { @@ -641,6 +659,8 @@ status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const status_t AudioTrack::setPosition(uint32_t position) { + if (mIsTimed) return INVALID_OPERATION; + AutoMutex lock(mLock); if (!stopped_l()) return INVALID_OPERATION; @@ -791,6 +811,7 @@ status_t AudioTrack::createTrack_l( ((uint16_t)flags) << 16, sharedBuffer, output, + mIsTimed, &mSessionId, &status); @@ -957,6 +978,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) { if (mSharedBuffer != 0) return INVALID_OPERATION; + if (mIsTimed) return INVALID_OPERATION; if (ssize_t(userSize) < 0) { // Sanity-check: user is most-likely passing an error code, and it would @@ -1013,6 +1035,59 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) // ------------------------------------------------------------------------- +TimedAudioTrack::TimedAudioTrack() { + mIsTimed = true; +} + +status_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer) +{ + status_t result = UNKNOWN_ERROR; + + // If the track is not invalid already, try to allocate a buffer. alloc + // fails indicating that the server is dead, flag the track as invalid so + // we can attempt to restore in in just a bit. + if (!(mCblk->flags & CBLK_INVALID_MSK)) { + result = mAudioTrack->allocateTimedBuffer(size, buffer); + if (result == DEAD_OBJECT) { + android_atomic_or(CBLK_INVALID_ON, &mCblk->flags); + } + } + + // If the track is invalid at this point, attempt to restore it. and try the + // allocation one more time. + if (mCblk->flags & CBLK_INVALID_MSK) { + mCblk->lock.lock(); + result = restoreTrack_l(mCblk, false); + mCblk->lock.unlock(); + + if (result == OK) + result = mAudioTrack->allocateTimedBuffer(size, buffer); + } + + return result; +} + +status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer, + int64_t pts) +{ + // restart track if it was disabled by audioflinger due to previous underrun + if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) { + android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags); + ALOGW("queueTimedBuffer() track %p disabled, restarting", this); + mAudioTrack->start(0); + } + + return mAudioTrack->queueTimedBuffer(buffer, pts); +} + +status_t TimedAudioTrack::setMediaTimeTransform(const LinearTransform& xform, + TargetTimeline target) +{ + return mAudioTrack->setMediaTimeTransform(xform, target); +} + +// ------------------------------------------------------------------------- + bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) { Buffer audioBuffer; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 4507e5d..ebadbfa 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -90,6 +90,7 @@ public: uint32_t flags, const sp<IMemory>& sharedBuffer, audio_io_handle_t output, + bool isTimed, int *sessionId, status_t *status) { @@ -105,6 +106,7 @@ public: data.writeInt32(flags); data.writeStrongBinder(sharedBuffer->asBinder()); data.writeInt32((int32_t) output); + data.writeInt32(isTimed); int lSessionId = 0; if (sessionId != NULL) { lSessionId = *sessionId; @@ -689,11 +691,12 @@ status_t BnAudioFlinger::onTransact( uint32_t flags = data.readInt32(); sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder()); audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); + bool isTimed = data.readInt32(); int sessionId = data.readInt32(); status_t status; sp<IAudioTrack> track = createTrack(pid, (audio_stream_type_t) streamType, sampleRate, format, - channelCount, bufferCount, flags, buffer, output, &sessionId, &status); + channelCount, bufferCount, flags, buffer, output, isTimed, &sessionId, &status); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(track->asBinder()); diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index a7958de..28ebbbf 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -35,7 +35,10 @@ enum { FLUSH, MUTE, PAUSE, - ATTACH_AUX_EFFECT + ATTACH_AUX_EFFECT, + ALLOCATE_TIMED_BUFFER, + QUEUE_TIMED_BUFFER, + SET_MEDIA_TIME_TRANSFORM, }; class BpAudioTrack : public BpInterface<IAudioTrack> @@ -114,6 +117,52 @@ public: } return status; } + + virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + data.writeInt32(size); + status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER, + data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + if (status == NO_ERROR) { + *buffer = interface_cast<IMemory>(reply.readStrongBinder()); + } + } + return status; + } + + virtual status_t queueTimedBuffer(const sp<IMemory>& buffer, + int64_t pts) { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + data.writeStrongBinder(buffer->asBinder()); + data.writeInt64(pts); + status_t status = remote()->transact(QUEUE_TIMED_BUFFER, + data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + } + return status; + } + + virtual status_t setMediaTimeTransform(const LinearTransform& xform, + int target) { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + data.writeInt64(xform.a_zero); + data.writeInt64(xform.b_zero); + data.writeInt32(xform.a_to_b_numer); + data.writeInt32(xform.a_to_b_denom); + data.writeInt32(target); + status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM, + data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); @@ -159,10 +208,38 @@ status_t BnAudioTrack::onTransact( reply->writeInt32(attachAuxEffect(data.readInt32())); return NO_ERROR; } break; + case ALLOCATE_TIMED_BUFFER: { + CHECK_INTERFACE(IAudioTrack, data, reply); + sp<IMemory> buffer; + status_t status = allocateTimedBuffer(data.readInt32(), &buffer); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeStrongBinder(buffer->asBinder()); + } + return NO_ERROR; + } break; + case QUEUE_TIMED_BUFFER: { + CHECK_INTERFACE(IAudioTrack, data, reply); + sp<IMemory> buffer = interface_cast<IMemory>( + data.readStrongBinder()); + uint64_t pts = data.readInt64(); + reply->writeInt32(queueTimedBuffer(buffer, pts)); + return NO_ERROR; + } break; + case SET_MEDIA_TIME_TRANSFORM: { + CHECK_INTERFACE(IAudioTrack, data, reply); + LinearTransform xform; + xform.a_zero = data.readInt64(); + xform.b_zero = data.readInt64(); + xform.a_to_b_numer = data.readInt32(); + xform.a_to_b_denom = data.readInt32(); + int target = data.readInt32(); + reply->writeInt32(setMediaTimeTransform(xform, target)); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } } }; // namespace android - |