Loading include/media/AudioTrack.h +27 −5 Original line number Diff line number Diff line Loading @@ -186,8 +186,21 @@ public: * and inform of marker, position updates, etc. * user: Context for use by the callback receiver. * notificationFrames: The callback function is called each time notificationFrames PCM * frames have been consumed from track input buffer. * This is expressed in units of frames at the initial source sample rate. * frames have been consumed from track input buffer by server. * Zero means to use a default value, which is typically: * - fast tracks: HAL buffer size, even if track frameCount is larger * - normal tracks: 1/2 of track frameCount * A positive value means that many frames at initial source sample rate. * A negative value for this parameter specifies the negative of the * requested number of notifications (sub-buffers) in the entire buffer. * For fast tracks, the FastMixer will process one sub-buffer at a time. * The size of each sub-buffer is determined by the HAL. * To get "double buffering", for example, one should pass -2. * The minimum number of sub-buffers is 1 (expressed as -1), * and the maximum number of sub-buffers is 8 (expressed as -8). * Negative is only permitted for fast tracks, and if frameCount is zero. * TODO It is ugly to overload a parameter in this way depending on * whether it is positive, negative, or zero. Consider splitting apart. * sessionId: Specific session ID, or zero to use default. * transferType: How data is transferred to AudioTrack. * offloadInfo: If not NULL, provides offload parameters for Loading Loading @@ -216,7 +229,7 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, void* user = NULL, uint32_t notificationFrames = 0, int32_t notificationFrames = 0, audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, Loading Loading @@ -246,7 +259,7 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, void* user = NULL, uint32_t notificationFrames = 0, int32_t notificationFrames = 0, audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, Loading Loading @@ -290,7 +303,7 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, void* user = NULL, uint32_t notificationFrames = 0, int32_t notificationFrames = 0, const sp<IMemory>& sharedBuffer = 0, bool threadCanCallJava = false, audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, Loading Loading @@ -335,6 +348,8 @@ public: uint32_t channelCount() const { return mChannelCount; } size_t frameCount() const { return mFrameCount; } // TODO consider notificationFrames() if needed /* Return effective size of audio buffer that an application writes to * or a negative error if the track is uninitialized. */ Loading Loading @@ -977,9 +992,16 @@ protected: void* mUserData; // for notification APIs // next 2 fields are const after constructor or set() uint32_t mNotificationFramesReq; // requested number of frames between each // notification callback, // at initial source sample rate uint32_t mNotificationsPerBufferReq; // requested number of notifications per buffer, // currently only used for fast tracks with // default track buffer size uint32_t mNotificationFramesAct; // actual number of frames between each // notification callback, // at initial source sample rate Loading media/libmedia/AudioTrack.cpp +88 −30 Original line number Diff line number Diff line Loading @@ -90,16 +90,24 @@ static inline float adjustPitch(float pitch) // TODO: Move to a common library static size_t calculateMinFrameCount( uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate, uint32_t sampleRate, float speed) uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/) { // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate); if (minBufCount < 2) { minBufCount = 2; } #if 0 // The notificationsPerBufferReq parameter is not yet used for non-fast tracks, // but keeping the code here to make it easier to add later. if (minBufCount < notificationsPerBufferReq) { minBufCount = notificationsPerBufferReq; } #endif ALOGV("calculateMinFrameCount afLatency %u afFrameCount %u afSampleRate %u " "sampleRate %u speed %f minBufCount: %u", afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount); "sampleRate %u speed %f minBufCount: %u" /*" notificationsPerBufferReq %u"*/, afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount /*, notificationsPerBufferReq*/); return minBufCount * sourceFramesNeededWithTimestretch( sampleRate, afFrameCount, afSampleRate, speed); } Loading Loading @@ -144,7 +152,8 @@ status_t AudioTrack::getMinFrameCount( // When called from createTrack, speed is 1.0f (normal speed). // This is rechecked again on setting playback rate (TODO: on setting sample rate, too). *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f); *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f /*, 0 notificationsPerBufferReq*/); // The formula above should always produce a non-zero value under normal circumstances: // AudioTrack.SAMPLE_RATE_HZ_MIN <= sampleRate <= AudioTrack.SAMPLE_RATE_HZ_MAX. Loading Loading @@ -184,7 +193,7 @@ AudioTrack::AudioTrack( audio_output_flags_t flags, callback_t cbf, void* user, uint32_t notificationFrames, int32_t notificationFrames, audio_session_t sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, Loading Loading @@ -215,7 +224,7 @@ AudioTrack::AudioTrack( audio_output_flags_t flags, callback_t cbf, void* user, uint32_t notificationFrames, int32_t notificationFrames, audio_session_t sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, Loading Loading @@ -274,7 +283,7 @@ status_t AudioTrack::set( audio_output_flags_t flags, callback_t cbf, void* user, uint32_t notificationFrames, int32_t notificationFrames, const sp<IMemory>& sharedBuffer, bool threadCanCallJava, audio_session_t sessionId, Loading @@ -287,7 +296,7 @@ status_t AudioTrack::set( float maxRequiredSpeed) { ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "flags #%x, notificationFrames %u, sessionId %d, transferType %d, uid %d, pid %d", "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d", streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames, sessionId, transferType, uid, pid); Loading Loading @@ -443,7 +452,29 @@ status_t AudioTrack::set( mSendLevel = 0.0f; // mFrameCount is initialized in createTrack_l mReqFrameCount = frameCount; if (notificationFrames >= 0) { mNotificationFramesReq = notificationFrames; mNotificationsPerBufferReq = 0; } else { if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { ALOGE("notificationFrames=%d not permitted for non-fast track", notificationFrames); return BAD_VALUE; } if (frameCount > 0) { ALOGE("notificationFrames=%d not permitted with non-zero frameCount=%zu", notificationFrames, frameCount); return BAD_VALUE; } mNotificationFramesReq = 0; const uint32_t minNotificationsPerBuffer = 1; const uint32_t maxNotificationsPerBuffer = 8; mNotificationsPerBufferReq = min(maxNotificationsPerBuffer, max((uint32_t) -notificationFrames, minNotificationsPerBuffer)); ALOGW_IF(mNotificationsPerBufferReq != (uint32_t) -notificationFrames, "notificationFrames=%d clamped to the range -%u to -%u", notificationFrames, minNotificationsPerBuffer, maxNotificationsPerBuffer); } mNotificationFramesAct = 0; if (sessionId == AUDIO_SESSION_ALLOCATE) { mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION); Loading Loading @@ -1231,6 +1262,15 @@ status_t AudioTrack::createTrack_l() goto release; } // TODO consider making this a member variable if there are other uses for it later size_t afFrameCountHAL; status = AudioSystem::getFrameCountHAL(output, &afFrameCountHAL); if (status != NO_ERROR) { ALOGE("getFrameCountHAL(output=%d) status %d", output, status); goto release; } ALOG_ASSERT(afFrameCountHAL > 0); status = AudioSystem::getSamplingRate(output, &mAfSampleRate); if (status != NO_ERROR) { ALOGE("getSamplingRate(output=%d) status %d", output, status); Loading Loading @@ -1303,20 +1343,32 @@ status_t AudioTrack::createTrack_l() // there _is_ a frameCount parameter. We silently ignore it. frameCount = mSharedBuffer->size() / mFrameSize; } else { // For fast tracks the frame count calculations and checks are done by server if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) { size_t minFrameCount = 0; // For fast tracks the frame count calculations and checks are mostly done by server, // but we try to respect the application's request for notifications per buffer. if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { if (mNotificationsPerBufferReq > 0) { // Avoid possible arithmetic overflow during multiplication. // mNotificationsPerBuffer is clamped to a small integer earlier, so it is unlikely. if (mNotificationsPerBufferReq > SIZE_MAX / afFrameCountHAL) { ALOGE("Requested notificationPerBuffer=%u ignored for HAL frameCount=%zu", mNotificationsPerBufferReq, afFrameCountHAL); } else { minFrameCount = afFrameCountHAL * mNotificationsPerBufferReq; } } } else { // for normal tracks precompute the frame count based on speed. const float speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f : max(mMaxRequiredSpeed, mPlaybackRate.mSpeed); const size_t minFrameCount = calculateMinFrameCount( minFrameCount = calculateMinFrameCount( mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate, speed); speed /*, 0 mNotificationsPerBufferReq*/); } if (frameCount < minFrameCount) { frameCount = minFrameCount; } } } IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; Loading Loading @@ -1408,22 +1460,26 @@ status_t AudioTrack::createTrack_l() } // Make sure that application is notified with sufficient margin before underrun. // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where // n = 1 fast track with single buffering; nBuffering is ignored // n = 2 fast track with double buffering // n = 2 normal track, (including those with sample rate conversion) // n >= 3 very high latency or very small notification interval (unused). // FIXME Move the computation from client side to server side, // and allow nBuffering to be larger than 1 for OpenSL ES, like it can be for Java. // The client can divide the AudioTrack buffer into sub-buffers, // and expresses its desire to server as the notification frame count. if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) { size_t maxNotificationFrames = frameCount; if (!(trackFlags & IAudioFlinger::TRACK_FAST)) { const uint32_t nBuffering = 2; maxNotificationFrames /= nBuffering; size_t maxNotificationFrames; if (trackFlags & IAudioFlinger::TRACK_FAST) { // notify every HAL buffer, regardless of the size of the track buffer maxNotificationFrames = afFrameCountHAL; } else { // For normal tracks, use double-buffering const int nBuffering = 2; maxNotificationFrames = frameCount / nBuffering; } if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) { if (mNotificationFramesAct == 0) { ALOGD("Client defaulted notificationFrames to %zu for frameCount %zu", maxNotificationFrames, frameCount); } else { ALOGW("Client adjusted notificationFrames from %u to %zu for frameCount %zu", mNotificationFramesAct, maxNotificationFrames, frameCount); } mNotificationFramesAct = (uint32_t) maxNotificationFrames; } } Loading Loading @@ -2043,6 +2099,7 @@ nsecs_t AudioTrack::processAudioBuffer() const nsecs_t datans = mRemainingFrames <= avail ? 0 : framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed); // audio flinger thread buffer size (TODO: adjust for fast tracks) // FIXME: use mAfFrameCountHAL instead of mAfFrameCount below for fast tracks. const nsecs_t afns = framesToNanoseconds(mAfFrameCount, mAfSampleRate, speed); // add a half the AudioFlinger buffer time to avoid soaking CPU if datans is 0. myns = datans + (afns / 2); Loading Loading @@ -2203,7 +2260,8 @@ bool AudioTrack::isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) co return true; // static tracks do not have issues with buffer sizing. } const size_t minFrameCount = calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed); calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed /*, 0 mNotificationsPerBufferReq*/); ALOGV("isSampleRateSpeedAllowed_l mFrameCount %zu minFrameCount %zu", mFrameCount, minFrameCount); return mFrameCount >= minFrameCount; Loading services/audioflinger/Threads.cpp +3 −7 Original line number Diff line number Diff line Loading @@ -182,13 +182,9 @@ static const int kPriorityAudioApp = 2; static const int kPriorityFastMixer = 3; static const int kPriorityFastCapture = 3; // IAudioFlinger::createTrack() reports back to client the total size of shared memory area // for the track. The client then sub-divides this into smaller buffers for its use. // Currently the client uses N-buffering by default, but doesn't tell us about the value of N. // So for now we just assume that client is double-buffered for fast tracks. // FIXME It would be better for client to tell AudioFlinger the value of N, // so AudioFlinger could allocate the right amount of memory. // See the client's minBufCount and mNotificationFramesAct calculations for details. // IAudioFlinger::createTrack() has an in/out parameter 'pFrameCount' for the total size of the // track buffer in shared memory. Zero on input means to use a default value. For fast tracks, // AudioFlinger derives the default from HAL buffer size and 'fast track multiplier'. // This is the default value, if not specified by property. static const int kFastTrackMultiplier = 2; Loading Loading
include/media/AudioTrack.h +27 −5 Original line number Diff line number Diff line Loading @@ -186,8 +186,21 @@ public: * and inform of marker, position updates, etc. * user: Context for use by the callback receiver. * notificationFrames: The callback function is called each time notificationFrames PCM * frames have been consumed from track input buffer. * This is expressed in units of frames at the initial source sample rate. * frames have been consumed from track input buffer by server. * Zero means to use a default value, which is typically: * - fast tracks: HAL buffer size, even if track frameCount is larger * - normal tracks: 1/2 of track frameCount * A positive value means that many frames at initial source sample rate. * A negative value for this parameter specifies the negative of the * requested number of notifications (sub-buffers) in the entire buffer. * For fast tracks, the FastMixer will process one sub-buffer at a time. * The size of each sub-buffer is determined by the HAL. * To get "double buffering", for example, one should pass -2. * The minimum number of sub-buffers is 1 (expressed as -1), * and the maximum number of sub-buffers is 8 (expressed as -8). * Negative is only permitted for fast tracks, and if frameCount is zero. * TODO It is ugly to overload a parameter in this way depending on * whether it is positive, negative, or zero. Consider splitting apart. * sessionId: Specific session ID, or zero to use default. * transferType: How data is transferred to AudioTrack. * offloadInfo: If not NULL, provides offload parameters for Loading Loading @@ -216,7 +229,7 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, void* user = NULL, uint32_t notificationFrames = 0, int32_t notificationFrames = 0, audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, Loading Loading @@ -246,7 +259,7 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, void* user = NULL, uint32_t notificationFrames = 0, int32_t notificationFrames = 0, audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, Loading Loading @@ -290,7 +303,7 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, void* user = NULL, uint32_t notificationFrames = 0, int32_t notificationFrames = 0, const sp<IMemory>& sharedBuffer = 0, bool threadCanCallJava = false, audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, Loading Loading @@ -335,6 +348,8 @@ public: uint32_t channelCount() const { return mChannelCount; } size_t frameCount() const { return mFrameCount; } // TODO consider notificationFrames() if needed /* Return effective size of audio buffer that an application writes to * or a negative error if the track is uninitialized. */ Loading Loading @@ -977,9 +992,16 @@ protected: void* mUserData; // for notification APIs // next 2 fields are const after constructor or set() uint32_t mNotificationFramesReq; // requested number of frames between each // notification callback, // at initial source sample rate uint32_t mNotificationsPerBufferReq; // requested number of notifications per buffer, // currently only used for fast tracks with // default track buffer size uint32_t mNotificationFramesAct; // actual number of frames between each // notification callback, // at initial source sample rate Loading
media/libmedia/AudioTrack.cpp +88 −30 Original line number Diff line number Diff line Loading @@ -90,16 +90,24 @@ static inline float adjustPitch(float pitch) // TODO: Move to a common library static size_t calculateMinFrameCount( uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate, uint32_t sampleRate, float speed) uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/) { // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate); if (minBufCount < 2) { minBufCount = 2; } #if 0 // The notificationsPerBufferReq parameter is not yet used for non-fast tracks, // but keeping the code here to make it easier to add later. if (minBufCount < notificationsPerBufferReq) { minBufCount = notificationsPerBufferReq; } #endif ALOGV("calculateMinFrameCount afLatency %u afFrameCount %u afSampleRate %u " "sampleRate %u speed %f minBufCount: %u", afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount); "sampleRate %u speed %f minBufCount: %u" /*" notificationsPerBufferReq %u"*/, afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount /*, notificationsPerBufferReq*/); return minBufCount * sourceFramesNeededWithTimestretch( sampleRate, afFrameCount, afSampleRate, speed); } Loading Loading @@ -144,7 +152,8 @@ status_t AudioTrack::getMinFrameCount( // When called from createTrack, speed is 1.0f (normal speed). // This is rechecked again on setting playback rate (TODO: on setting sample rate, too). *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f); *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f /*, 0 notificationsPerBufferReq*/); // The formula above should always produce a non-zero value under normal circumstances: // AudioTrack.SAMPLE_RATE_HZ_MIN <= sampleRate <= AudioTrack.SAMPLE_RATE_HZ_MAX. Loading Loading @@ -184,7 +193,7 @@ AudioTrack::AudioTrack( audio_output_flags_t flags, callback_t cbf, void* user, uint32_t notificationFrames, int32_t notificationFrames, audio_session_t sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, Loading Loading @@ -215,7 +224,7 @@ AudioTrack::AudioTrack( audio_output_flags_t flags, callback_t cbf, void* user, uint32_t notificationFrames, int32_t notificationFrames, audio_session_t sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, Loading Loading @@ -274,7 +283,7 @@ status_t AudioTrack::set( audio_output_flags_t flags, callback_t cbf, void* user, uint32_t notificationFrames, int32_t notificationFrames, const sp<IMemory>& sharedBuffer, bool threadCanCallJava, audio_session_t sessionId, Loading @@ -287,7 +296,7 @@ status_t AudioTrack::set( float maxRequiredSpeed) { ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "flags #%x, notificationFrames %u, sessionId %d, transferType %d, uid %d, pid %d", "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d", streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames, sessionId, transferType, uid, pid); Loading Loading @@ -443,7 +452,29 @@ status_t AudioTrack::set( mSendLevel = 0.0f; // mFrameCount is initialized in createTrack_l mReqFrameCount = frameCount; if (notificationFrames >= 0) { mNotificationFramesReq = notificationFrames; mNotificationsPerBufferReq = 0; } else { if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { ALOGE("notificationFrames=%d not permitted for non-fast track", notificationFrames); return BAD_VALUE; } if (frameCount > 0) { ALOGE("notificationFrames=%d not permitted with non-zero frameCount=%zu", notificationFrames, frameCount); return BAD_VALUE; } mNotificationFramesReq = 0; const uint32_t minNotificationsPerBuffer = 1; const uint32_t maxNotificationsPerBuffer = 8; mNotificationsPerBufferReq = min(maxNotificationsPerBuffer, max((uint32_t) -notificationFrames, minNotificationsPerBuffer)); ALOGW_IF(mNotificationsPerBufferReq != (uint32_t) -notificationFrames, "notificationFrames=%d clamped to the range -%u to -%u", notificationFrames, minNotificationsPerBuffer, maxNotificationsPerBuffer); } mNotificationFramesAct = 0; if (sessionId == AUDIO_SESSION_ALLOCATE) { mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION); Loading Loading @@ -1231,6 +1262,15 @@ status_t AudioTrack::createTrack_l() goto release; } // TODO consider making this a member variable if there are other uses for it later size_t afFrameCountHAL; status = AudioSystem::getFrameCountHAL(output, &afFrameCountHAL); if (status != NO_ERROR) { ALOGE("getFrameCountHAL(output=%d) status %d", output, status); goto release; } ALOG_ASSERT(afFrameCountHAL > 0); status = AudioSystem::getSamplingRate(output, &mAfSampleRate); if (status != NO_ERROR) { ALOGE("getSamplingRate(output=%d) status %d", output, status); Loading Loading @@ -1303,20 +1343,32 @@ status_t AudioTrack::createTrack_l() // there _is_ a frameCount parameter. We silently ignore it. frameCount = mSharedBuffer->size() / mFrameSize; } else { // For fast tracks the frame count calculations and checks are done by server if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) { size_t minFrameCount = 0; // For fast tracks the frame count calculations and checks are mostly done by server, // but we try to respect the application's request for notifications per buffer. if (mFlags & AUDIO_OUTPUT_FLAG_FAST) { if (mNotificationsPerBufferReq > 0) { // Avoid possible arithmetic overflow during multiplication. // mNotificationsPerBuffer is clamped to a small integer earlier, so it is unlikely. if (mNotificationsPerBufferReq > SIZE_MAX / afFrameCountHAL) { ALOGE("Requested notificationPerBuffer=%u ignored for HAL frameCount=%zu", mNotificationsPerBufferReq, afFrameCountHAL); } else { minFrameCount = afFrameCountHAL * mNotificationsPerBufferReq; } } } else { // for normal tracks precompute the frame count based on speed. const float speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f : max(mMaxRequiredSpeed, mPlaybackRate.mSpeed); const size_t minFrameCount = calculateMinFrameCount( minFrameCount = calculateMinFrameCount( mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate, speed); speed /*, 0 mNotificationsPerBufferReq*/); } if (frameCount < minFrameCount) { frameCount = minFrameCount; } } } IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; Loading Loading @@ -1408,22 +1460,26 @@ status_t AudioTrack::createTrack_l() } // Make sure that application is notified with sufficient margin before underrun. // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where // n = 1 fast track with single buffering; nBuffering is ignored // n = 2 fast track with double buffering // n = 2 normal track, (including those with sample rate conversion) // n >= 3 very high latency or very small notification interval (unused). // FIXME Move the computation from client side to server side, // and allow nBuffering to be larger than 1 for OpenSL ES, like it can be for Java. // The client can divide the AudioTrack buffer into sub-buffers, // and expresses its desire to server as the notification frame count. if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) { size_t maxNotificationFrames = frameCount; if (!(trackFlags & IAudioFlinger::TRACK_FAST)) { const uint32_t nBuffering = 2; maxNotificationFrames /= nBuffering; size_t maxNotificationFrames; if (trackFlags & IAudioFlinger::TRACK_FAST) { // notify every HAL buffer, regardless of the size of the track buffer maxNotificationFrames = afFrameCountHAL; } else { // For normal tracks, use double-buffering const int nBuffering = 2; maxNotificationFrames = frameCount / nBuffering; } if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) { if (mNotificationFramesAct == 0) { ALOGD("Client defaulted notificationFrames to %zu for frameCount %zu", maxNotificationFrames, frameCount); } else { ALOGW("Client adjusted notificationFrames from %u to %zu for frameCount %zu", mNotificationFramesAct, maxNotificationFrames, frameCount); } mNotificationFramesAct = (uint32_t) maxNotificationFrames; } } Loading Loading @@ -2043,6 +2099,7 @@ nsecs_t AudioTrack::processAudioBuffer() const nsecs_t datans = mRemainingFrames <= avail ? 0 : framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed); // audio flinger thread buffer size (TODO: adjust for fast tracks) // FIXME: use mAfFrameCountHAL instead of mAfFrameCount below for fast tracks. const nsecs_t afns = framesToNanoseconds(mAfFrameCount, mAfSampleRate, speed); // add a half the AudioFlinger buffer time to avoid soaking CPU if datans is 0. myns = datans + (afns / 2); Loading Loading @@ -2203,7 +2260,8 @@ bool AudioTrack::isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) co return true; // static tracks do not have issues with buffer sizing. } const size_t minFrameCount = calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed); calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed /*, 0 mNotificationsPerBufferReq*/); ALOGV("isSampleRateSpeedAllowed_l mFrameCount %zu minFrameCount %zu", mFrameCount, minFrameCount); return mFrameCount >= minFrameCount; Loading
services/audioflinger/Threads.cpp +3 −7 Original line number Diff line number Diff line Loading @@ -182,13 +182,9 @@ static const int kPriorityAudioApp = 2; static const int kPriorityFastMixer = 3; static const int kPriorityFastCapture = 3; // IAudioFlinger::createTrack() reports back to client the total size of shared memory area // for the track. The client then sub-divides this into smaller buffers for its use. // Currently the client uses N-buffering by default, but doesn't tell us about the value of N. // So for now we just assume that client is double-buffered for fast tracks. // FIXME It would be better for client to tell AudioFlinger the value of N, // so AudioFlinger could allocate the right amount of memory. // See the client's minBufCount and mNotificationFramesAct calculations for details. // IAudioFlinger::createTrack() has an in/out parameter 'pFrameCount' for the total size of the // track buffer in shared memory. Zero on input means to use a default value. For fast tracks, // AudioFlinger derives the default from HAL buffer size and 'fast track multiplier'. // This is the default value, if not specified by property. static const int kFastTrackMultiplier = 2; Loading