Loading include/media/AudioTrack.h +24 −2 Original line number Original line Diff line number Diff line Loading @@ -320,6 +320,25 @@ public: uint32_t channelCount() const { return mChannelCount; } uint32_t channelCount() const { return mChannelCount; } size_t frameCount() const { return mFrameCount; } size_t frameCount() const { return mFrameCount; } /* Return effective size of audio buffer that an application writes to * or a negative error if the track is uninitialized. */ ssize_t getBufferSizeInFrames(); /* Set the effective size of audio buffer that an application writes to. * This is used to determine the amount of available room in the buffer, * which determines when a write will block. * This allows an application to raise and lower the audio latency. * The requested size may be adjusted so that it is * greater or equal to the absolute minimum and * less than or equal to the getBufferCapacityInFrames(). * It may also be adjusted slightly for internal reasons. * * Return the final size or a negative error if the track is unitialized * or does not support variable sizes. */ ssize_t setBufferSizeInFrames(size_t size); /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */ /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */ sp<IMemory> sharedBuffer() const { return mSharedBuffer; } sp<IMemory> sharedBuffer() const { return mSharedBuffer; } Loading Loading @@ -818,8 +837,11 @@ protected: mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it uint32_t mOriginalSampleRate; uint32_t mOriginalSampleRate; AudioPlaybackRate mPlaybackRate; AudioPlaybackRate mPlaybackRate; size_t mFrameCount; // corresponds to current IAudioTrack, value is // reported back by AudioFlinger to the client // Corresponds to current IAudioTrack, value is reported back by AudioFlinger to the client. // This allocated buffer size is maintained by the proxy. size_t mFrameCount; // maximum size of buffer size_t mReqFrameCount; // frame count to request the first or next time size_t mReqFrameCount; // frame count to request the first or next time // a new IAudioTrack is needed, non-decreasing // a new IAudioTrack is needed, non-decreasing Loading include/private/media/AudioTrackShared.h +12 −1 Original line number Original line Diff line number Diff line Loading @@ -204,6 +204,8 @@ public: size_t mNonContig; // number of additional non-contiguous frames available size_t mNonContig; // number of additional non-contiguous frames available }; }; size_t frameCount() const { return mFrameCount; } protected: protected: // These refer to shared memory, and are virtual addresses with respect to the current process. // These refer to shared memory, and are virtual addresses with respect to the current process. // They may have different virtual addresses within the other process. // They may have different virtual addresses within the other process. Loading Loading @@ -305,6 +307,15 @@ public: return mEpoch; return mEpoch; } } size_t getBufferSizeInFrames() const { return mBufferSizeInFrames; } // See documentation for AudioTrack.setBufferSizeInFrames() size_t setBufferSizeInFrames(size_t requestedSize); protected: // This is set by AudioTrack.setBufferSizeInFrames(). // A write will not fill the buffer above this limit. size_t mBufferSizeInFrames; // effective size of the buffer private: private: Modulo<uint32_t> mEpoch; Modulo<uint32_t> mEpoch; }; }; Loading media/libmedia/AudioTrack.cpp +25 −0 Original line number Original line Diff line number Diff line Loading @@ -860,6 +860,31 @@ const AudioPlaybackRate& AudioTrack::getPlaybackRate() const return mPlaybackRate; return mPlaybackRate; } } ssize_t AudioTrack::getBufferSizeInFrames() { AutoMutex lock(mLock); if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) { return NO_INIT; } return mProxy->getBufferSizeInFrames(); } ssize_t AudioTrack::setBufferSizeInFrames(size_t bufferSizeInFrames) { AutoMutex lock(mLock); if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) { return NO_INIT; } // Reject if timed track or compressed audio. if (mIsTimed || !audio_is_linear_pcm(mFormat)) { return INVALID_OPERATION; } // TODO also need to inform the server side (through mAudioTrack) that // the buffer count is reduced, otherwise the track may never start // because the server thinks it is never filled. return mProxy->setBufferSizeInFrames(bufferSizeInFrames); } status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) { { if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { Loading media/libmedia/AudioTrackShared.cpp +30 −7 Original line number Original line Diff line number Diff line Loading @@ -66,7 +66,9 @@ Proxy::Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, bool clientInServer) size_t frameSize, bool isOut, bool clientInServer) : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), mEpoch(0) : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer) , mBufferSizeInFrames(frameCount) , mEpoch(0) { { } } Loading Loading @@ -151,6 +153,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); front = cblk->u.mStreaming.mFront; front = cblk->u.mStreaming.mFront; } } // write to rear, read from front ssize_t filled = rear - front; ssize_t filled = rear - front; // pipe should not be overfull // pipe should not be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { if (!(0 <= filled && (size_t) filled <= mFrameCount)) { Loading @@ -166,11 +169,17 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques cblk->u.mStreaming.mFront = rear; cblk->u.mStreaming.mFront = rear; (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); } } // don't allow filling pipe beyond the nominal size // Don't allow filling pipe beyond the user settable size. size_t avail = mIsOut ? mFrameCount - filled : filled; // The calculation for avail can go negative if the buffer size if (avail > 0) { // is suddenly dropped below the amount already in the buffer. // So use a signed calculation to prevent a numeric overflow abort. ssize_t adjustableSize = (ssize_t) mBufferSizeInFrames; ssize_t avail = (mIsOut) ? adjustableSize - filled : filled; if (avail < 0) { avail = 0; } else if (avail > 0) { // 'avail' may be non-contiguous, so return only the first contiguous chunk // 'avail' may be non-contiguous, so return only the first contiguous chunk size_t part1; ssize_t part1; if (mIsOut) { if (mIsOut) { rear &= mFrameCountP2 - 1; rear &= mFrameCountP2 - 1; part1 = mFrameCountP2 - rear; part1 = mFrameCountP2 - rear; Loading @@ -181,10 +190,10 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques if (part1 > avail) { if (part1 > avail) { part1 = avail; part1 = avail; } } if (part1 > buffer->mFrameCount) { if (part1 > (ssize_t) buffer->mFrameCount) { part1 = buffer->mFrameCount; part1 = buffer->mFrameCount; } } buffer->mFrameCount = part1; buffer->mFrameCount = (size_t) part1; buffer->mRaw = part1 > 0 ? buffer->mRaw = part1 > 0 ? &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; buffer->mNonContig = avail - part1; buffer->mNonContig = avail - part1; Loading Loading @@ -347,6 +356,20 @@ size_t ClientProxy::getMisalignment() (mFrameCountP2 - 1); (mFrameCountP2 - 1); } } size_t ClientProxy::setBufferSizeInFrames(size_t size) { // TODO set minimum to 2X the fast mixer buffer size. size_t minimum = 128 * 2; // arbitrary size_t maximum = frameCount(); if (size < minimum) { size = minimum; } else if (size > maximum) { size = maximum; } mBufferSizeInFrames = size; return size; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void AudioTrackClientProxy::flush() void AudioTrackClientProxy::flush() Loading Loading
include/media/AudioTrack.h +24 −2 Original line number Original line Diff line number Diff line Loading @@ -320,6 +320,25 @@ public: uint32_t channelCount() const { return mChannelCount; } uint32_t channelCount() const { return mChannelCount; } size_t frameCount() const { return mFrameCount; } size_t frameCount() const { return mFrameCount; } /* Return effective size of audio buffer that an application writes to * or a negative error if the track is uninitialized. */ ssize_t getBufferSizeInFrames(); /* Set the effective size of audio buffer that an application writes to. * This is used to determine the amount of available room in the buffer, * which determines when a write will block. * This allows an application to raise and lower the audio latency. * The requested size may be adjusted so that it is * greater or equal to the absolute minimum and * less than or equal to the getBufferCapacityInFrames(). * It may also be adjusted slightly for internal reasons. * * Return the final size or a negative error if the track is unitialized * or does not support variable sizes. */ ssize_t setBufferSizeInFrames(size_t size); /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */ /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */ sp<IMemory> sharedBuffer() const { return mSharedBuffer; } sp<IMemory> sharedBuffer() const { return mSharedBuffer; } Loading Loading @@ -818,8 +837,11 @@ protected: mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it uint32_t mOriginalSampleRate; uint32_t mOriginalSampleRate; AudioPlaybackRate mPlaybackRate; AudioPlaybackRate mPlaybackRate; size_t mFrameCount; // corresponds to current IAudioTrack, value is // reported back by AudioFlinger to the client // Corresponds to current IAudioTrack, value is reported back by AudioFlinger to the client. // This allocated buffer size is maintained by the proxy. size_t mFrameCount; // maximum size of buffer size_t mReqFrameCount; // frame count to request the first or next time size_t mReqFrameCount; // frame count to request the first or next time // a new IAudioTrack is needed, non-decreasing // a new IAudioTrack is needed, non-decreasing Loading
include/private/media/AudioTrackShared.h +12 −1 Original line number Original line Diff line number Diff line Loading @@ -204,6 +204,8 @@ public: size_t mNonContig; // number of additional non-contiguous frames available size_t mNonContig; // number of additional non-contiguous frames available }; }; size_t frameCount() const { return mFrameCount; } protected: protected: // These refer to shared memory, and are virtual addresses with respect to the current process. // These refer to shared memory, and are virtual addresses with respect to the current process. // They may have different virtual addresses within the other process. // They may have different virtual addresses within the other process. Loading Loading @@ -305,6 +307,15 @@ public: return mEpoch; return mEpoch; } } size_t getBufferSizeInFrames() const { return mBufferSizeInFrames; } // See documentation for AudioTrack.setBufferSizeInFrames() size_t setBufferSizeInFrames(size_t requestedSize); protected: // This is set by AudioTrack.setBufferSizeInFrames(). // A write will not fill the buffer above this limit. size_t mBufferSizeInFrames; // effective size of the buffer private: private: Modulo<uint32_t> mEpoch; Modulo<uint32_t> mEpoch; }; }; Loading
media/libmedia/AudioTrack.cpp +25 −0 Original line number Original line Diff line number Diff line Loading @@ -860,6 +860,31 @@ const AudioPlaybackRate& AudioTrack::getPlaybackRate() const return mPlaybackRate; return mPlaybackRate; } } ssize_t AudioTrack::getBufferSizeInFrames() { AutoMutex lock(mLock); if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) { return NO_INIT; } return mProxy->getBufferSizeInFrames(); } ssize_t AudioTrack::setBufferSizeInFrames(size_t bufferSizeInFrames) { AutoMutex lock(mLock); if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) { return NO_INIT; } // Reject if timed track or compressed audio. if (mIsTimed || !audio_is_linear_pcm(mFormat)) { return INVALID_OPERATION; } // TODO also need to inform the server side (through mAudioTrack) that // the buffer count is reduced, otherwise the track may never start // because the server thinks it is never filled. return mProxy->setBufferSizeInFrames(bufferSizeInFrames); } status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) { { if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) { Loading
media/libmedia/AudioTrackShared.cpp +30 −7 Original line number Original line Diff line number Diff line Loading @@ -66,7 +66,9 @@ Proxy::Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, bool clientInServer) size_t frameSize, bool isOut, bool clientInServer) : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), mEpoch(0) : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer) , mBufferSizeInFrames(frameCount) , mEpoch(0) { { } } Loading Loading @@ -151,6 +153,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); front = cblk->u.mStreaming.mFront; front = cblk->u.mStreaming.mFront; } } // write to rear, read from front ssize_t filled = rear - front; ssize_t filled = rear - front; // pipe should not be overfull // pipe should not be overfull if (!(0 <= filled && (size_t) filled <= mFrameCount)) { if (!(0 <= filled && (size_t) filled <= mFrameCount)) { Loading @@ -166,11 +169,17 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques cblk->u.mStreaming.mFront = rear; cblk->u.mStreaming.mFront = rear; (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); } } // don't allow filling pipe beyond the nominal size // Don't allow filling pipe beyond the user settable size. size_t avail = mIsOut ? mFrameCount - filled : filled; // The calculation for avail can go negative if the buffer size if (avail > 0) { // is suddenly dropped below the amount already in the buffer. // So use a signed calculation to prevent a numeric overflow abort. ssize_t adjustableSize = (ssize_t) mBufferSizeInFrames; ssize_t avail = (mIsOut) ? adjustableSize - filled : filled; if (avail < 0) { avail = 0; } else if (avail > 0) { // 'avail' may be non-contiguous, so return only the first contiguous chunk // 'avail' may be non-contiguous, so return only the first contiguous chunk size_t part1; ssize_t part1; if (mIsOut) { if (mIsOut) { rear &= mFrameCountP2 - 1; rear &= mFrameCountP2 - 1; part1 = mFrameCountP2 - rear; part1 = mFrameCountP2 - rear; Loading @@ -181,10 +190,10 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques if (part1 > avail) { if (part1 > avail) { part1 = avail; part1 = avail; } } if (part1 > buffer->mFrameCount) { if (part1 > (ssize_t) buffer->mFrameCount) { part1 = buffer->mFrameCount; part1 = buffer->mFrameCount; } } buffer->mFrameCount = part1; buffer->mFrameCount = (size_t) part1; buffer->mRaw = part1 > 0 ? buffer->mRaw = part1 > 0 ? &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; buffer->mNonContig = avail - part1; buffer->mNonContig = avail - part1; Loading Loading @@ -347,6 +356,20 @@ size_t ClientProxy::getMisalignment() (mFrameCountP2 - 1); (mFrameCountP2 - 1); } } size_t ClientProxy::setBufferSizeInFrames(size_t size) { // TODO set minimum to 2X the fast mixer buffer size. size_t minimum = 128 * 2; // arbitrary size_t maximum = frameCount(); if (size < minimum) { size = minimum; } else if (size > maximum) { size = maximum; } mBufferSizeInFrames = size; return size; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void AudioTrackClientProxy::flush() void AudioTrackClientProxy::flush() Loading