Loading media/libaaudio/src/client/AudioEndpoint.cpp +15 −32 Original line number Diff line number Diff line Loading @@ -32,19 +32,12 @@ using namespace aaudio; #define RIDICULOUSLY_LARGE_FRAME_SIZE 4096 AudioEndpoint::AudioEndpoint() : mUpCommandQueue(nullptr) , mDataQueue(nullptr) , mFreeRunning(false) : mFreeRunning(false) , mDataReadCounter(0) , mDataWriteCounter(0) { } AudioEndpoint::~AudioEndpoint() { delete mDataQueue; delete mUpCommandQueue; } // TODO Consider moving to a method in RingBufferDescriptor static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type, const RingBufferDescriptor *descriptor) { Loading Loading @@ -144,7 +137,7 @@ aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDesc return AAUDIO_ERROR_INTERNAL; } mUpCommandQueue = new FifoBuffer( mUpCommandQueue = std::make_unique<FifoBuffer>( descriptor->bytesPerFrame, descriptor->capacityInFrames, descriptor->readCounterAddress, Loading Loading @@ -173,7 +166,7 @@ aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDesc ? &mDataWriteCounter : descriptor->writeCounterAddress; mDataQueue = new FifoBuffer( mDataQueue = std::make_unique<FifoBuffer>( descriptor->bytesPerFrame, descriptor->capacityInFrames, readCounterAddress, Loading @@ -194,18 +187,15 @@ int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) { return mDataQueue->getEmptyRoomAvailable(wrappingBuffer); } int32_t AudioEndpoint::getEmptyFramesAvailable() { int32_t AudioEndpoint::getEmptyFramesAvailable() { return mDataQueue->getEmptyFramesAvailable(); } int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) { int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) { return mDataQueue->getFullDataAvailable(wrappingBuffer); } int32_t AudioEndpoint::getFullFramesAvailable() { int32_t AudioEndpoint::getFullFramesAvailable() { return mDataQueue->getFullFramesAvailable(); } Loading @@ -217,29 +207,24 @@ void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) { mDataQueue->advanceReadIndex(deltaFrames); } void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) { void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) { mDataQueue->setReadCounter(framesRead); } fifo_counter_t AudioEndpoint::getDataReadCounter() { fifo_counter_t AudioEndpoint::getDataReadCounter() const { return mDataQueue->getReadCounter(); } void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) { void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) { mDataQueue->setWriteCounter(framesRead); } fifo_counter_t AudioEndpoint::getDataWriteCounter() { fifo_counter_t AudioEndpoint::getDataWriteCounter() const { return mDataQueue->getWriteCounter(); } int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames, int32_t *actualFrames) { int32_t *actualFrames) { if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) { requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN; } Loading @@ -248,19 +233,17 @@ int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames, return AAUDIO_OK; } int32_t AudioEndpoint::getBufferSizeInFrames() const { int32_t AudioEndpoint::getBufferSizeInFrames() const { return mDataQueue->getThreshold(); } int32_t AudioEndpoint::getBufferCapacityInFrames() const { int32_t AudioEndpoint::getBufferCapacityInFrames() const { return (int32_t)mDataQueue->getBufferCapacityInFrames(); } void AudioEndpoint::dump() const { ALOGD("data readCounter = %lld", (long long) mDataQueue->getReadCounter()); ALOGD("data writeCounter = %lld", (long long) mDataQueue->getWriteCounter()); ALOGD("data readCounter = %lld", (long long) getDataReadCounter()); ALOGD("data writeCounter = %lld", (long long) getDataWriteCounter()); } void AudioEndpoint::eraseDataMemory() { Loading media/libaaudio/src/client/AudioEndpoint.h +4 −5 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ class AudioEndpoint { public: AudioEndpoint(); virtual ~AudioEndpoint(); /** * Configure based on the EndPointDescriptor_t. Loading Loading @@ -67,11 +66,11 @@ public: */ void setDataReadCounter(android::fifo_counter_t framesRead); android::fifo_counter_t getDataReadCounter(); android::fifo_counter_t getDataReadCounter() const; void setDataWriteCounter(android::fifo_counter_t framesWritten); android::fifo_counter_t getDataWriteCounter(); android::fifo_counter_t getDataWriteCounter() const; /** * The result is not valid until after configure() is called. Loading @@ -94,8 +93,8 @@ public: void dump() const; private: android::FifoBuffer *mUpCommandQueue; android::FifoBuffer *mDataQueue; std::unique_ptr<android::FifoBuffer> mUpCommandQueue; std::unique_ptr<android::FifoBuffer> mDataQueue; bool mFreeRunning; android::fifo_counter_t mDataReadCounter; // only used if free-running android::fifo_counter_t mDataWriteCounter; // only used if free-running Loading media/libaaudio/src/client/AudioStreamInternal.cpp +38 −23 Original line number Diff line number Diff line Loading @@ -58,7 +58,6 @@ using namespace aaudio; AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService) : AudioStream() , mClockModel() , mAudioEndpoint() , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) , mInService(inService) , mServiceInterface(serviceInterface) Loading @@ -74,7 +73,6 @@ AudioStreamInternal::~AudioStreamInternal() { aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { aaudio_result_t result = AAUDIO_OK; int32_t capacity; int32_t framesPerBurst; int32_t framesPerHardwareBurst; AAudioStreamRequest request; Loading Loading @@ -173,7 +171,8 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { } // Configure endpoint based on descriptor. result = mAudioEndpoint.configure(&mEndpointDescriptor, getDirection()); mAudioEndpoint = std::make_unique<AudioEndpoint>(); result = mAudioEndpoint->configure(&mEndpointDescriptor, getDirection()); if (result != AAUDIO_OK) { goto error; } Loading Loading @@ -201,9 +200,10 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { } mFramesPerBurst = framesPerBurst; // only save good value capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames; if (capacity < mFramesPerBurst || capacity > MAX_BUFFER_CAPACITY_IN_FRAMES) { ALOGE("%s - bufferCapacity out of range = %d", __func__, capacity); mBufferCapacityInFrames = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames; if (mBufferCapacityInFrames < mFramesPerBurst || mBufferCapacityInFrames > MAX_BUFFER_CAPACITY_IN_FRAMES) { ALOGE("%s - bufferCapacity out of range = %d", __func__, mBufferCapacityInFrames); result = AAUDIO_ERROR_OUT_OF_RANGE; goto error; } Loading Loading @@ -239,7 +239,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { // You can use this offset to reduce glitching. // You can also use this offset to force glitching. By iterating over multiple // values you can reveal the distribution of the hardware timing jitter. if (mAudioEndpoint.isFreeRunning()) { // MMAP? if (mAudioEndpoint->isFreeRunning()) { // MMAP? int32_t offsetMicros = (getDirection() == AAUDIO_DIRECTION_OUTPUT) ? AAudioProperty_getOutputMMapOffsetMicros() : AAudioProperty_getInputMMapOffsetMicros(); Loading @@ -251,7 +251,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { mTimeOffsetNanos = offsetMicros * AAUDIO_NANOS_PER_MICROSECOND; } setBufferSize(capacity / 2); // Default buffer size to match Q setBufferSize(mBufferCapacityInFrames / 2); // Default buffer size to match Q setState(AAUDIO_STREAM_STATE_OPEN); Loading Loading @@ -280,6 +280,11 @@ aaudio_result_t AudioStreamInternal::release_l() { mServiceInterface.closeStream(serviceStreamHandle); mCallbackBuffer.reset(); // Update local frame counters so we can query them after releasing the endpoint. getFramesRead(); getFramesWritten(); mAudioEndpoint.reset(); result = mEndPointParcelable.close(); aaudio_result_t result2 = AudioStream::release_l(); return (result != AAUDIO_OK) ? result : result2; Loading Loading @@ -538,7 +543,7 @@ aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *mes case AAUDIO_SERVICE_EVENT_DISCONNECTED: // Prevent hardware from looping on old data and making buzzing sounds. if (getDirection() == AAUDIO_DIRECTION_OUTPUT) { mAudioEndpoint.eraseDataMemory(); mAudioEndpoint->eraseDataMemory(); } result = AAUDIO_ERROR_DISCONNECTED; setState(AAUDIO_STREAM_STATE_DISCONNECTED); Loading @@ -564,7 +569,10 @@ aaudio_result_t AudioStreamInternal::drainTimestampsFromService() { while (result == AAUDIO_OK) { AAudioServiceMessage message; if (mAudioEndpoint.readUpCommand(&message) != 1) { if (!mAudioEndpoint) { break; } if (mAudioEndpoint->readUpCommand(&message) != 1) { break; // no command this time, no problem } switch (message.what) { Loading Loading @@ -592,7 +600,10 @@ aaudio_result_t AudioStreamInternal::processCommands() { while (result == AAUDIO_OK) { AAudioServiceMessage message; if (mAudioEndpoint.readUpCommand(&message) != 1) { if (!mAudioEndpoint) { break; } if (mAudioEndpoint->readUpCommand(&message) != 1) { break; // no command this time, no problem } switch (message.what) { Loading Loading @@ -625,7 +636,7 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames const char * fifoName = "aaRdy"; ATRACE_BEGIN(traceName); if (ATRACE_ENABLED()) { int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable(); ATRACE_INT(fifoName, fullFrames); } Loading Loading @@ -654,7 +665,7 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames if (timeoutNanoseconds == 0) { break; // don't block } else if (wakeTimeNanos != 0) { if (!mAudioEndpoint.isFreeRunning()) { if (!mAudioEndpoint->isFreeRunning()) { // If there is software on the other end of the FIFO then it may get delayed. // So wake up just a little after we expect it to be ready. wakeTimeNanos += mWakeupDelayNanos; Loading @@ -679,12 +690,12 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames ALOGW("processData(): past deadline by %d micros", (int)((wakeTimeNanos - deadlineNanos) / AAUDIO_NANOS_PER_MICROSECOND)); mClockModel.dump(); mAudioEndpoint.dump(); mAudioEndpoint->dump(); break; } if (ATRACE_ENABLED()) { int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable(); ATRACE_INT(fifoName, fullFrames); int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos; ATRACE_INT("aaSlpNs", (int32_t)sleepForNanos); Loading @@ -696,7 +707,7 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames } if (ATRACE_ENABLED()) { int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable(); ATRACE_INT(fifoName, fullFrames); } Loading Loading @@ -730,11 +741,15 @@ aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) { adjustedFrames = std::min(maximumSize, adjustedFrames); } if (mAudioEndpoint) { // Clip against the actual size from the endpoint. int32_t actualFrames = 0; mAudioEndpoint.setBufferSizeInFrames(maximumSize, &actualFrames); // Set to maximum size so we can write extra data when ready in order to reduce glitches. // The amount we keep in the buffer is controlled by mBufferSizeInFrames. mAudioEndpoint->setBufferSizeInFrames(maximumSize, &actualFrames); // actualFrames should be <= actual maximum size of endpoint adjustedFrames = std::min(actualFrames, adjustedFrames); } mBufferSizeInFrames = adjustedFrames; ALOGV("%s(%d) returns %d", __func__, requestedFrames, adjustedFrames); Loading @@ -746,7 +761,7 @@ int32_t AudioStreamInternal::getBufferSize() const { } int32_t AudioStreamInternal::getBufferCapacity() const { return mAudioEndpoint.getBufferCapacityInFrames(); return mBufferCapacityInFrames; } int32_t AudioStreamInternal::getFramesPerBurst() const { Loading @@ -759,5 +774,5 @@ aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { } bool AudioStreamInternal::isClockModelInControl() const { return isActive() && mAudioEndpoint.isFreeRunning() && mClockModel.isRunning(); return isActive() && mAudioEndpoint->isFreeRunning() && mClockModel.isRunning(); } media/libaaudio/src/client/AudioStreamInternal.h +7 −1 Original line number Diff line number Diff line Loading @@ -155,7 +155,8 @@ protected: IsochronousClockModel mClockModel; // timing model for chasing the HAL AudioEndpoint mAudioEndpoint; // source for reads or sink for writes std::unique_ptr<AudioEndpoint> mAudioEndpoint; // source for reads or sink for writes aaudio_handle_t mServiceStreamHandle; // opaque handle returned from service int32_t mFramesPerBurst = MIN_FRAMES_PER_BURST; // frames per HAL transfer Loading @@ -178,6 +179,9 @@ protected: float mStreamVolume = 1.0f; int64_t mLastFramesWritten = 0; int64_t mLastFramesRead = 0; private: /* * Asynchronous write with data conversion. Loading Loading @@ -207,6 +211,8 @@ private: int32_t mDeviceChannelCount = 0; int32_t mBufferSizeInFrames = 0; // local threshold to control latency int32_t mBufferCapacityInFrames = 0; }; Loading media/libaaudio/src/client/AudioStreamInternalCapture.cpp +22 −19 Original line number Diff line number Diff line Loading @@ -42,8 +42,8 @@ AudioStreamInternalCapture::AudioStreamInternalCapture(AAudioServiceInterface & AudioStreamInternalCapture::~AudioStreamInternalCapture() {} void AudioStreamInternalCapture::advanceClientToMatchServerPosition() { int64_t readCounter = mAudioEndpoint.getDataReadCounter(); int64_t writeCounter = mAudioEndpoint.getDataWriteCounter(); int64_t readCounter = mAudioEndpoint->getDataReadCounter(); int64_t writeCounter = mAudioEndpoint->getDataWriteCounter(); // Bump offset so caller does not see the retrograde motion in getFramesRead(). int64_t offset = readCounter - writeCounter; Loading @@ -53,7 +53,7 @@ void AudioStreamInternalCapture::advanceClientToMatchServerPosition() { // Force readCounter to match writeCounter. // This is because we cannot change the write counter in the hardware. mAudioEndpoint.setDataReadCounter(writeCounter); mAudioEndpoint->setDataReadCounter(writeCounter); } // Write the data, block if needed and timeoutMillis > 0 Loading Loading @@ -86,7 +86,7 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t } // If we have gotten this far then we have at least one timestamp from server. if (mAudioEndpoint.isFreeRunning()) { if (mAudioEndpoint->isFreeRunning()) { //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter"); // Update data queue based on the timing model. // Jitter in the DSP can cause late writes to the FIFO. Loading @@ -95,7 +95,7 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t // that the DSP could have written the data. int64_t estimatedRemoteCounter = mClockModel.convertLatestTimeToPosition(currentNanoTime); // TODO refactor, maybe use setRemoteCounter() mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter); mAudioEndpoint->setDataWriteCounter(estimatedRemoteCounter); } // This code assumes that we have already received valid timestamps. Loading @@ -108,8 +108,8 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t // If the capture buffer is full beyond capacity then consider it an overrun. // For shared streams, the xRunCount is passed up from the service. if (mAudioEndpoint.isFreeRunning() && mAudioEndpoint.getFullFramesAvailable() > mAudioEndpoint.getBufferCapacityInFrames()) { if (mAudioEndpoint->isFreeRunning() && mAudioEndpoint->getFullFramesAvailable() > mAudioEndpoint->getBufferCapacityInFrames()) { mXRunCount++; if (ATRACE_ENABLED()) { ATRACE_INT("aaOverRuns", mXRunCount); Loading Loading @@ -143,7 +143,7 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t // Calculate frame position based off of the readCounter because // the writeCounter might have just advanced in the background, // causing us to sleep until a later burst. int64_t nextPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst; int64_t nextPosition = mAudioEndpoint->getDataReadCounter() + mFramesPerBurst; wakeTime = mClockModel.convertPositionToLatestTime(nextPosition); } break; Loading @@ -166,7 +166,7 @@ aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer, uint8_t *destination = (uint8_t *) buffer; int32_t framesLeft = numFrames; mAudioEndpoint.getFullFramesAvailable(&wrappingBuffer); mAudioEndpoint->getFullFramesAvailable(&wrappingBuffer); // Read data in one or two parts. for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) { Loading Loading @@ -208,26 +208,29 @@ aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer, } int32_t framesProcessed = numFrames - framesLeft; mAudioEndpoint.advanceReadIndex(framesProcessed); mAudioEndpoint->advanceReadIndex(framesProcessed); //ALOGD("readNowWithConversion() returns %d", framesProcessed); return framesProcessed; } int64_t AudioStreamInternalCapture::getFramesWritten() { if (mAudioEndpoint) { const int64_t framesWrittenHardware = isClockModelInControl() ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) : mAudioEndpoint.getDataWriteCounter(); : mAudioEndpoint->getDataWriteCounter(); // Add service offset and prevent retrograde motion. mLastFramesWritten = std::max(mLastFramesWritten, framesWrittenHardware + mFramesOffsetFromService); } return mLastFramesWritten; } int64_t AudioStreamInternalCapture::getFramesRead() { int64_t frames = mAudioEndpoint.getDataReadCounter() + mFramesOffsetFromService; //ALOGD("getFramesRead() returns %lld", (long long)frames); return frames; if (mAudioEndpoint) { mLastFramesRead = mAudioEndpoint->getDataReadCounter() + mFramesOffsetFromService; } return mLastFramesRead; } // Read data from the stream and pass it to the callback for processing. Loading Loading
media/libaaudio/src/client/AudioEndpoint.cpp +15 −32 Original line number Diff line number Diff line Loading @@ -32,19 +32,12 @@ using namespace aaudio; #define RIDICULOUSLY_LARGE_FRAME_SIZE 4096 AudioEndpoint::AudioEndpoint() : mUpCommandQueue(nullptr) , mDataQueue(nullptr) , mFreeRunning(false) : mFreeRunning(false) , mDataReadCounter(0) , mDataWriteCounter(0) { } AudioEndpoint::~AudioEndpoint() { delete mDataQueue; delete mUpCommandQueue; } // TODO Consider moving to a method in RingBufferDescriptor static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type, const RingBufferDescriptor *descriptor) { Loading Loading @@ -144,7 +137,7 @@ aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDesc return AAUDIO_ERROR_INTERNAL; } mUpCommandQueue = new FifoBuffer( mUpCommandQueue = std::make_unique<FifoBuffer>( descriptor->bytesPerFrame, descriptor->capacityInFrames, descriptor->readCounterAddress, Loading Loading @@ -173,7 +166,7 @@ aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDesc ? &mDataWriteCounter : descriptor->writeCounterAddress; mDataQueue = new FifoBuffer( mDataQueue = std::make_unique<FifoBuffer>( descriptor->bytesPerFrame, descriptor->capacityInFrames, readCounterAddress, Loading @@ -194,18 +187,15 @@ int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) { return mDataQueue->getEmptyRoomAvailable(wrappingBuffer); } int32_t AudioEndpoint::getEmptyFramesAvailable() { int32_t AudioEndpoint::getEmptyFramesAvailable() { return mDataQueue->getEmptyFramesAvailable(); } int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) { int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) { return mDataQueue->getFullDataAvailable(wrappingBuffer); } int32_t AudioEndpoint::getFullFramesAvailable() { int32_t AudioEndpoint::getFullFramesAvailable() { return mDataQueue->getFullFramesAvailable(); } Loading @@ -217,29 +207,24 @@ void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) { mDataQueue->advanceReadIndex(deltaFrames); } void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) { void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) { mDataQueue->setReadCounter(framesRead); } fifo_counter_t AudioEndpoint::getDataReadCounter() { fifo_counter_t AudioEndpoint::getDataReadCounter() const { return mDataQueue->getReadCounter(); } void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) { void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) { mDataQueue->setWriteCounter(framesRead); } fifo_counter_t AudioEndpoint::getDataWriteCounter() { fifo_counter_t AudioEndpoint::getDataWriteCounter() const { return mDataQueue->getWriteCounter(); } int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames, int32_t *actualFrames) { int32_t *actualFrames) { if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) { requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN; } Loading @@ -248,19 +233,17 @@ int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames, return AAUDIO_OK; } int32_t AudioEndpoint::getBufferSizeInFrames() const { int32_t AudioEndpoint::getBufferSizeInFrames() const { return mDataQueue->getThreshold(); } int32_t AudioEndpoint::getBufferCapacityInFrames() const { int32_t AudioEndpoint::getBufferCapacityInFrames() const { return (int32_t)mDataQueue->getBufferCapacityInFrames(); } void AudioEndpoint::dump() const { ALOGD("data readCounter = %lld", (long long) mDataQueue->getReadCounter()); ALOGD("data writeCounter = %lld", (long long) mDataQueue->getWriteCounter()); ALOGD("data readCounter = %lld", (long long) getDataReadCounter()); ALOGD("data writeCounter = %lld", (long long) getDataWriteCounter()); } void AudioEndpoint::eraseDataMemory() { Loading
media/libaaudio/src/client/AudioEndpoint.h +4 −5 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ class AudioEndpoint { public: AudioEndpoint(); virtual ~AudioEndpoint(); /** * Configure based on the EndPointDescriptor_t. Loading Loading @@ -67,11 +66,11 @@ public: */ void setDataReadCounter(android::fifo_counter_t framesRead); android::fifo_counter_t getDataReadCounter(); android::fifo_counter_t getDataReadCounter() const; void setDataWriteCounter(android::fifo_counter_t framesWritten); android::fifo_counter_t getDataWriteCounter(); android::fifo_counter_t getDataWriteCounter() const; /** * The result is not valid until after configure() is called. Loading @@ -94,8 +93,8 @@ public: void dump() const; private: android::FifoBuffer *mUpCommandQueue; android::FifoBuffer *mDataQueue; std::unique_ptr<android::FifoBuffer> mUpCommandQueue; std::unique_ptr<android::FifoBuffer> mDataQueue; bool mFreeRunning; android::fifo_counter_t mDataReadCounter; // only used if free-running android::fifo_counter_t mDataWriteCounter; // only used if free-running Loading
media/libaaudio/src/client/AudioStreamInternal.cpp +38 −23 Original line number Diff line number Diff line Loading @@ -58,7 +58,6 @@ using namespace aaudio; AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface &serviceInterface, bool inService) : AudioStream() , mClockModel() , mAudioEndpoint() , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) , mInService(inService) , mServiceInterface(serviceInterface) Loading @@ -74,7 +73,6 @@ AudioStreamInternal::~AudioStreamInternal() { aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { aaudio_result_t result = AAUDIO_OK; int32_t capacity; int32_t framesPerBurst; int32_t framesPerHardwareBurst; AAudioStreamRequest request; Loading Loading @@ -173,7 +171,8 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { } // Configure endpoint based on descriptor. result = mAudioEndpoint.configure(&mEndpointDescriptor, getDirection()); mAudioEndpoint = std::make_unique<AudioEndpoint>(); result = mAudioEndpoint->configure(&mEndpointDescriptor, getDirection()); if (result != AAUDIO_OK) { goto error; } Loading Loading @@ -201,9 +200,10 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { } mFramesPerBurst = framesPerBurst; // only save good value capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames; if (capacity < mFramesPerBurst || capacity > MAX_BUFFER_CAPACITY_IN_FRAMES) { ALOGE("%s - bufferCapacity out of range = %d", __func__, capacity); mBufferCapacityInFrames = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames; if (mBufferCapacityInFrames < mFramesPerBurst || mBufferCapacityInFrames > MAX_BUFFER_CAPACITY_IN_FRAMES) { ALOGE("%s - bufferCapacity out of range = %d", __func__, mBufferCapacityInFrames); result = AAUDIO_ERROR_OUT_OF_RANGE; goto error; } Loading Loading @@ -239,7 +239,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { // You can use this offset to reduce glitching. // You can also use this offset to force glitching. By iterating over multiple // values you can reveal the distribution of the hardware timing jitter. if (mAudioEndpoint.isFreeRunning()) { // MMAP? if (mAudioEndpoint->isFreeRunning()) { // MMAP? int32_t offsetMicros = (getDirection() == AAUDIO_DIRECTION_OUTPUT) ? AAudioProperty_getOutputMMapOffsetMicros() : AAudioProperty_getInputMMapOffsetMicros(); Loading @@ -251,7 +251,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { mTimeOffsetNanos = offsetMicros * AAUDIO_NANOS_PER_MICROSECOND; } setBufferSize(capacity / 2); // Default buffer size to match Q setBufferSize(mBufferCapacityInFrames / 2); // Default buffer size to match Q setState(AAUDIO_STREAM_STATE_OPEN); Loading Loading @@ -280,6 +280,11 @@ aaudio_result_t AudioStreamInternal::release_l() { mServiceInterface.closeStream(serviceStreamHandle); mCallbackBuffer.reset(); // Update local frame counters so we can query them after releasing the endpoint. getFramesRead(); getFramesWritten(); mAudioEndpoint.reset(); result = mEndPointParcelable.close(); aaudio_result_t result2 = AudioStream::release_l(); return (result != AAUDIO_OK) ? result : result2; Loading Loading @@ -538,7 +543,7 @@ aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *mes case AAUDIO_SERVICE_EVENT_DISCONNECTED: // Prevent hardware from looping on old data and making buzzing sounds. if (getDirection() == AAUDIO_DIRECTION_OUTPUT) { mAudioEndpoint.eraseDataMemory(); mAudioEndpoint->eraseDataMemory(); } result = AAUDIO_ERROR_DISCONNECTED; setState(AAUDIO_STREAM_STATE_DISCONNECTED); Loading @@ -564,7 +569,10 @@ aaudio_result_t AudioStreamInternal::drainTimestampsFromService() { while (result == AAUDIO_OK) { AAudioServiceMessage message; if (mAudioEndpoint.readUpCommand(&message) != 1) { if (!mAudioEndpoint) { break; } if (mAudioEndpoint->readUpCommand(&message) != 1) { break; // no command this time, no problem } switch (message.what) { Loading Loading @@ -592,7 +600,10 @@ aaudio_result_t AudioStreamInternal::processCommands() { while (result == AAUDIO_OK) { AAudioServiceMessage message; if (mAudioEndpoint.readUpCommand(&message) != 1) { if (!mAudioEndpoint) { break; } if (mAudioEndpoint->readUpCommand(&message) != 1) { break; // no command this time, no problem } switch (message.what) { Loading Loading @@ -625,7 +636,7 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames const char * fifoName = "aaRdy"; ATRACE_BEGIN(traceName); if (ATRACE_ENABLED()) { int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable(); ATRACE_INT(fifoName, fullFrames); } Loading Loading @@ -654,7 +665,7 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames if (timeoutNanoseconds == 0) { break; // don't block } else if (wakeTimeNanos != 0) { if (!mAudioEndpoint.isFreeRunning()) { if (!mAudioEndpoint->isFreeRunning()) { // If there is software on the other end of the FIFO then it may get delayed. // So wake up just a little after we expect it to be ready. wakeTimeNanos += mWakeupDelayNanos; Loading @@ -679,12 +690,12 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames ALOGW("processData(): past deadline by %d micros", (int)((wakeTimeNanos - deadlineNanos) / AAUDIO_NANOS_PER_MICROSECOND)); mClockModel.dump(); mAudioEndpoint.dump(); mAudioEndpoint->dump(); break; } if (ATRACE_ENABLED()) { int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable(); ATRACE_INT(fifoName, fullFrames); int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos; ATRACE_INT("aaSlpNs", (int32_t)sleepForNanos); Loading @@ -696,7 +707,7 @@ aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames } if (ATRACE_ENABLED()) { int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable(); ATRACE_INT(fifoName, fullFrames); } Loading Loading @@ -730,11 +741,15 @@ aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) { adjustedFrames = std::min(maximumSize, adjustedFrames); } if (mAudioEndpoint) { // Clip against the actual size from the endpoint. int32_t actualFrames = 0; mAudioEndpoint.setBufferSizeInFrames(maximumSize, &actualFrames); // Set to maximum size so we can write extra data when ready in order to reduce glitches. // The amount we keep in the buffer is controlled by mBufferSizeInFrames. mAudioEndpoint->setBufferSizeInFrames(maximumSize, &actualFrames); // actualFrames should be <= actual maximum size of endpoint adjustedFrames = std::min(actualFrames, adjustedFrames); } mBufferSizeInFrames = adjustedFrames; ALOGV("%s(%d) returns %d", __func__, requestedFrames, adjustedFrames); Loading @@ -746,7 +761,7 @@ int32_t AudioStreamInternal::getBufferSize() const { } int32_t AudioStreamInternal::getBufferCapacity() const { return mAudioEndpoint.getBufferCapacityInFrames(); return mBufferCapacityInFrames; } int32_t AudioStreamInternal::getFramesPerBurst() const { Loading @@ -759,5 +774,5 @@ aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { } bool AudioStreamInternal::isClockModelInControl() const { return isActive() && mAudioEndpoint.isFreeRunning() && mClockModel.isRunning(); return isActive() && mAudioEndpoint->isFreeRunning() && mClockModel.isRunning(); }
media/libaaudio/src/client/AudioStreamInternal.h +7 −1 Original line number Diff line number Diff line Loading @@ -155,7 +155,8 @@ protected: IsochronousClockModel mClockModel; // timing model for chasing the HAL AudioEndpoint mAudioEndpoint; // source for reads or sink for writes std::unique_ptr<AudioEndpoint> mAudioEndpoint; // source for reads or sink for writes aaudio_handle_t mServiceStreamHandle; // opaque handle returned from service int32_t mFramesPerBurst = MIN_FRAMES_PER_BURST; // frames per HAL transfer Loading @@ -178,6 +179,9 @@ protected: float mStreamVolume = 1.0f; int64_t mLastFramesWritten = 0; int64_t mLastFramesRead = 0; private: /* * Asynchronous write with data conversion. Loading Loading @@ -207,6 +211,8 @@ private: int32_t mDeviceChannelCount = 0; int32_t mBufferSizeInFrames = 0; // local threshold to control latency int32_t mBufferCapacityInFrames = 0; }; Loading
media/libaaudio/src/client/AudioStreamInternalCapture.cpp +22 −19 Original line number Diff line number Diff line Loading @@ -42,8 +42,8 @@ AudioStreamInternalCapture::AudioStreamInternalCapture(AAudioServiceInterface & AudioStreamInternalCapture::~AudioStreamInternalCapture() {} void AudioStreamInternalCapture::advanceClientToMatchServerPosition() { int64_t readCounter = mAudioEndpoint.getDataReadCounter(); int64_t writeCounter = mAudioEndpoint.getDataWriteCounter(); int64_t readCounter = mAudioEndpoint->getDataReadCounter(); int64_t writeCounter = mAudioEndpoint->getDataWriteCounter(); // Bump offset so caller does not see the retrograde motion in getFramesRead(). int64_t offset = readCounter - writeCounter; Loading @@ -53,7 +53,7 @@ void AudioStreamInternalCapture::advanceClientToMatchServerPosition() { // Force readCounter to match writeCounter. // This is because we cannot change the write counter in the hardware. mAudioEndpoint.setDataReadCounter(writeCounter); mAudioEndpoint->setDataReadCounter(writeCounter); } // Write the data, block if needed and timeoutMillis > 0 Loading Loading @@ -86,7 +86,7 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t } // If we have gotten this far then we have at least one timestamp from server. if (mAudioEndpoint.isFreeRunning()) { if (mAudioEndpoint->isFreeRunning()) { //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter"); // Update data queue based on the timing model. // Jitter in the DSP can cause late writes to the FIFO. Loading @@ -95,7 +95,7 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t // that the DSP could have written the data. int64_t estimatedRemoteCounter = mClockModel.convertLatestTimeToPosition(currentNanoTime); // TODO refactor, maybe use setRemoteCounter() mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter); mAudioEndpoint->setDataWriteCounter(estimatedRemoteCounter); } // This code assumes that we have already received valid timestamps. Loading @@ -108,8 +108,8 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t // If the capture buffer is full beyond capacity then consider it an overrun. // For shared streams, the xRunCount is passed up from the service. if (mAudioEndpoint.isFreeRunning() && mAudioEndpoint.getFullFramesAvailable() > mAudioEndpoint.getBufferCapacityInFrames()) { if (mAudioEndpoint->isFreeRunning() && mAudioEndpoint->getFullFramesAvailable() > mAudioEndpoint->getBufferCapacityInFrames()) { mXRunCount++; if (ATRACE_ENABLED()) { ATRACE_INT("aaOverRuns", mXRunCount); Loading Loading @@ -143,7 +143,7 @@ aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t // Calculate frame position based off of the readCounter because // the writeCounter might have just advanced in the background, // causing us to sleep until a later burst. int64_t nextPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst; int64_t nextPosition = mAudioEndpoint->getDataReadCounter() + mFramesPerBurst; wakeTime = mClockModel.convertPositionToLatestTime(nextPosition); } break; Loading @@ -166,7 +166,7 @@ aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer, uint8_t *destination = (uint8_t *) buffer; int32_t framesLeft = numFrames; mAudioEndpoint.getFullFramesAvailable(&wrappingBuffer); mAudioEndpoint->getFullFramesAvailable(&wrappingBuffer); // Read data in one or two parts. for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) { Loading Loading @@ -208,26 +208,29 @@ aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer, } int32_t framesProcessed = numFrames - framesLeft; mAudioEndpoint.advanceReadIndex(framesProcessed); mAudioEndpoint->advanceReadIndex(framesProcessed); //ALOGD("readNowWithConversion() returns %d", framesProcessed); return framesProcessed; } int64_t AudioStreamInternalCapture::getFramesWritten() { if (mAudioEndpoint) { const int64_t framesWrittenHardware = isClockModelInControl() ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) : mAudioEndpoint.getDataWriteCounter(); : mAudioEndpoint->getDataWriteCounter(); // Add service offset and prevent retrograde motion. mLastFramesWritten = std::max(mLastFramesWritten, framesWrittenHardware + mFramesOffsetFromService); } return mLastFramesWritten; } int64_t AudioStreamInternalCapture::getFramesRead() { int64_t frames = mAudioEndpoint.getDataReadCounter() + mFramesOffsetFromService; //ALOGD("getFramesRead() returns %lld", (long long)frames); return frames; if (mAudioEndpoint) { mLastFramesRead = mAudioEndpoint->getDataReadCounter() + mFramesOffsetFromService; } return mLastFramesRead; } // Read data from the stream and pass it to the callback for processing. Loading