Analizo
view release on metacpan or search on metacpan
t/samples/android-framework/android-5.1.1_r38/AudioTrackShared.cpp view on Meta::CPAN
int32_t front = cblk->u.mStreaming.mFront;
android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront);
} else {
int32_t rear = cblk->u.mStreaming.mRear;
android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear);
}
cblk->mServer += stepCount;
size_t half = mFrameCount / 2;
if (half == 0) {
half = 1;
}
size_t minimum = (size_t) cblk->mMinimum;
if (minimum == 0) {
minimum = mIsOut ? half : 1;
} else if (minimum > half) {
minimum = half;
}
// FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time
if (!mIsOut || (mAvailToClient + stepCount >= minimum)) {
ALOGV("mAvailToClient=%zu stepCount=%zu minimum=%zu", mAvailToClient, stepCount, minimum);
int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
if (!(old & CBLK_FUTEX_WAKE)) {
(void) syscall(__NR_futex, &cblk->mFutex,
mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
}
}
buffer->mFrameCount = 0;
buffer->mRaw = NULL;
buffer->mNonContig = 0;
}
// ---------------------------------------------------------------------------
size_t AudioTrackServerProxy::framesReady()
{
LOG_ALWAYS_FATAL_IF(!mIsOut);
if (mIsShutdown) {
return 0;
}
audio_track_cblk_t* cblk = mCblk;
int32_t flush = cblk->u.mStreaming.mFlush;
if (flush != mFlush) {
// FIXME should return an accurate value, but over-estimate is better than under-estimate
return mFrameCount;
}
// the acquire might not be necessary since not doing a subsequent read
int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
ssize_t filled = rear - cblk->u.mStreaming.mFront;
// pipe should not already be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
mIsShutdown = true;
return 0;
}
// cache this value for later use by obtainBuffer(), with added barrier
// and racy if called by normal mixer thread
// ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer()
return filled;
}
bool AudioTrackServerProxy::setStreamEndDone() {
audio_track_cblk_t* cblk = mCblk;
bool old =
(android_atomic_or(CBLK_STREAM_END_DONE, &cblk->mFlags) & CBLK_STREAM_END_DONE) != 0;
if (!old) {
(void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
1);
}
return old;
}
void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
{
audio_track_cblk_t* cblk = mCblk;
cblk->u.mStreaming.mUnderrunFrames += frameCount;
// FIXME also wake futex so that underrun is noticed more quickly
(void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags);
}
// ---------------------------------------------------------------------------
StaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
size_t frameCount, size_t frameSize)
: AudioTrackServerProxy(cblk, buffers, frameCount, frameSize),
mObserver(&cblk->u.mStatic.mSingleStateQueue), mPosition(0),
mFramesReadySafe(frameCount), mFramesReady(frameCount),
mFramesReadyIsCalledByMultipleThreads(false)
{
mState.mLoopStart = 0;
mState.mLoopEnd = 0;
mState.mLoopCount = 0;
}
void StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads()
{
mFramesReadyIsCalledByMultipleThreads = true;
}
size_t StaticAudioTrackServerProxy::framesReady()
{
// Can't call pollPosition() from multiple threads.
if (!mFramesReadyIsCalledByMultipleThreads) {
(void) pollPosition();
}
return mFramesReadySafe;
}
ssize_t StaticAudioTrackServerProxy::pollPosition()
{
size_t position = mPosition;
StaticAudioTrackState state;
if (mObserver.poll(state)) {
bool valid = false;
size_t loopStart = state.mLoopStart;
size_t loopEnd = state.mLoopEnd;
if (state.mLoopCount == 0) {
if (loopStart > mFrameCount) {
loopStart = mFrameCount;
}
// ignore loopEnd
mPosition = position = loopStart;
mFramesReady = mFrameCount - mPosition;
mState.mLoopCount = 0;
valid = true;
} else if (state.mLoopCount >= -1) {
if (loopStart < loopEnd && loopEnd <= mFrameCount &&
loopEnd - loopStart >= MIN_LOOP) {
// If the current position is greater than the end of the loop
// we "wrap" to the loop start. This might cause an audible pop.
if (position >= loopEnd) {
mPosition = position = loopStart;
}
if (state.mLoopCount == -1) {
mFramesReady = INT64_MAX;
} else {
// mFramesReady is 64 bits to handle the effective number of frames
// that the static audio track contains, including loops.
// TODO: Later consider fixing overflow, but does not seem needed now
// as will not overflow if loopStart and loopEnd are Java "ints".
mFramesReady = int64_t(state.mLoopCount) * (loopEnd - loopStart)
+ mFrameCount - mPosition;
}
mState = state;
valid = true;
}
}
if (!valid || mPosition > mFrameCount) {
ALOGE("%s client pushed an invalid state, shutting down", __func__);
mIsShutdown = true;
return (ssize_t) NO_INIT;
}
mFramesReadySafe = clampToSize(mFramesReady);
// This may overflow, but client is not supposed to rely on it
mCblk->u.mStatic.mBufferPosition = (uint32_t) position;
}
return (ssize_t) position;
}
status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused)
{
if (mIsShutdown) {
( run in 1.114 second using v1.01-cache-2.11-cpan-d8267643d1d )