diff options
| -rw-r--r-- | media/libmedia/AudioTrack.cpp | 128 | ||||
| -rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 38 |
2 files changed, 112 insertions, 54 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b1be8b1..cd419bd 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -54,6 +54,12 @@ status_t AudioTrack::getMinFrameCount( audio_stream_type_t streamType, uint32_t sampleRate) { + // FIXME merge with similar code in createTrack_l(), except we're missing + // some information here that is available in createTrack_l(): + // audio_io_handle_t output + // audio_format_t format + // audio_channel_mask_t channelMask + // audio_output_flags_t flags int afSampleRate; if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; @@ -201,11 +207,11 @@ status_t AudioTrack::set( streamType = AUDIO_STREAM_MUSIC; } - int afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { - return NO_INIT; - } if (sampleRate == 0) { + int afSampleRate; + if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { + return NO_INIT; + } sampleRate = afSampleRate; } @@ -223,6 +229,12 @@ status_t AudioTrack::set( return BAD_VALUE; } + // AudioFlinger does not currently support 8-bit data in shared memory + if (format == AUDIO_FORMAT_PCM_8_BIT && sharedBuffer != 0) { + ALOGE("8-bit data in shared memory is not supported"); + return BAD_VALUE; + } + // force direct flag if format is not linear PCM if (!audio_is_linear_pcm(format)) { flags = (audio_output_flags_t) @@ -744,14 +756,6 @@ status_t AudioTrack::createTrack_l( return NO_INIT; } - int afSampleRate; - if (AudioSystem::getSamplingRate(output, streamType, &afSampleRate) != NO_ERROR) { - return NO_INIT; - } - int afFrameCount; - if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) { - return NO_INIT; - } uint32_t afLatency; if (AudioSystem::getLatency(output, streamType, &afLatency) != NO_ERROR) { return NO_INIT; @@ -768,14 +772,57 @@ status_t AudioTrack::createTrack_l( ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client"); flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); } - ALOGV("createTrack_l() output %d afFrameCount %d afLatency %d", output, afFrameCount, afLatency); + ALOGV("createTrack_l() output %d afLatency %d", output, afLatency); mNotificationFramesAct = mNotificationFramesReq; + if (!audio_is_linear_pcm(format)) { + if (sharedBuffer != 0) { + // Same comment as below about ignoring frameCount parameter for set() frameCount = sharedBuffer->size(); + } else if (frameCount == 0) { + int afFrameCount; + if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) { + return NO_INIT; + } + frameCount = afFrameCount; } - } else { + + } else if (sharedBuffer != 0) { + + // Ensure that buffer alignment matches channelCount + int channelCount = popcount(channelMask); + // 8-bit data in shared memory is not currently supported by AudioFlinger + size_t alignment = /* format == AUDIO_FORMAT_PCM_8_BIT ? 1 : */ 2; + if (channelCount > 1) { + // More than 2 channels does not require stronger alignment than stereo + alignment <<= 1; + } + if (((uint32_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { + ALOGE("Invalid buffer alignment: address %p, channelCount %d", + sharedBuffer->pointer(), channelCount); + return BAD_VALUE; + } + + // When initializing a shared buffer AudioTrack via constructors, + // there's no frameCount parameter. + // But when initializing a shared buffer AudioTrack via set(), + // there _is_ a frameCount parameter. We silently ignore it. + frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); + + } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { + + // FIXME move these calculations and associated checks to server + int afSampleRate; + if (AudioSystem::getSamplingRate(output, streamType, &afSampleRate) != NO_ERROR) { + return NO_INIT; + } + int afFrameCount; + if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) { + return NO_INIT; + } + // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); if (minBufCount < 2) minBufCount = 2; @@ -784,38 +831,27 @@ status_t AudioTrack::createTrack_l( ALOGV("minFrameCount: %d, afFrameCount=%d, minBufCount=%d, sampleRate=%d, afSampleRate=%d" ", afLatency=%d", minFrameCount, afFrameCount, minBufCount, sampleRate, afSampleRate, afLatency); -#define MIN_FRAME_COUNT_FAST 128 // FIXME hard-coded - if ((flags & AUDIO_OUTPUT_FLAG_FAST) && (minFrameCount > MIN_FRAME_COUNT_FAST)) { - minFrameCount = MIN_FRAME_COUNT_FAST; - } - if (sharedBuffer == 0) { - if (frameCount == 0) { - frameCount = minFrameCount; - } - if (mNotificationFramesAct == 0) { - mNotificationFramesAct = frameCount/2; - } - // Make sure that application is notified with sufficient margin - // before underrun - if (mNotificationFramesAct > (uint32_t)frameCount/2) { - mNotificationFramesAct = frameCount/2; - } - if (frameCount < minFrameCount) { - // not ALOGW because it happens all the time when playing key clicks over A2DP - ALOGV("Minimum buffer size corrected from %d to %d", - frameCount, minFrameCount); - frameCount = minFrameCount; - } - } else { - // Ensure that buffer alignment matches channelCount - int channelCount = popcount(channelMask); - if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { - ALOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); - return BAD_VALUE; - } - frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); + if (frameCount == 0) { + frameCount = minFrameCount; + } + if (mNotificationFramesAct == 0) { + mNotificationFramesAct = frameCount/2; + } + // Make sure that application is notified with sufficient margin + // before underrun + if (mNotificationFramesAct > (uint32_t)frameCount/2) { + mNotificationFramesAct = frameCount/2; } + if (frameCount < minFrameCount) { + // not ALOGW because it happens all the time when playing key clicks over A2DP + ALOGV("Minimum buffer size corrected from %d to %d", + frameCount, minFrameCount); + frameCount = minFrameCount; + } + + } else { + // For fast tracks, the frame count calculations and checks are done by server } IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; @@ -864,6 +900,9 @@ status_t AudioTrack::createTrack_l( } else { ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", mCblk->frameCount); } + if (sharedBuffer == 0) { + mNotificationFramesAct = mCblk->frameCount/2; + } } if (sharedBuffer == 0) { mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); @@ -879,6 +918,7 @@ status_t AudioTrack::createTrack_l( mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; mRemainingFrames = mNotificationFramesAct; + // FIXME don't believe this lie mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate; return NO_ERROR; } diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 6eeda9a..1c277ce 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1623,8 +1623,8 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0; // client expresses a preference for FAST, but we get the final say - if ((flags & IAudioFlinger::TRACK_FAST) && - !( + if (flags & IAudioFlinger::TRACK_FAST) { + if ( // not timed (!isTimed) && // either of these use cases: @@ -1633,11 +1633,11 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac ( (sharedBuffer != 0) ) || - // use case 2: callback handler and frame count at least as large as HAL + // use case 2: callback handler and frame count is default or at least as large as HAL ( (tid != -1) && - // FIXME supported frame counts should not be hard-coded - frameCount >= (int) mFrameCount // FIXME int cast is due to wrong parameter type + ((frameCount == 0) || + (frameCount >= (int) mFrameCount)) // FIXME int cast is due to wrong parameter type ) ) && // PCM data @@ -1655,17 +1655,35 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac (mFastTrackAvailMask != 0) // FIXME test that MixerThread for this fast track has a capable output HAL // FIXME add a permission test also? - ) ) { - ALOGW("AUDIO_POLICY_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d " + ) { + ALOGI("AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%d mFrameCount=%d", + frameCount, mFrameCount); + // if frameCount not specified, then it defaults to fast mixer (HAL) frame count + if (frameCount == 0) { + frameCount = mFrameCount; + } + } else { + ALOGW("AUDIO_OUTPUT_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d " "mFrameCount=%d format=%d isLinear=%d channelMask=%d sampleRate=%d mSampleRate=%d " "hasFastMixer=%d tid=%d fastTrackAvailMask=%#x", isTimed, sharedBuffer.get(), frameCount, mFrameCount, format, audio_is_linear_pcm(format), channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask); flags &= ~IAudioFlinger::TRACK_FAST; - if (0 < frameCount && frameCount < (int) mNormalFrameCount) { - frameCount = mNormalFrameCount; - } + // For compatibility with AudioTrack calculation, buffer depth is forced + // to be at least 2 x the normal mixer frame count and cover audio hardware latency. + // This is probably too conservative, but legacy application code may depend on it. + // If you change this calculation, also review the start threshold which is related. + uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream); + uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); + if (minBufCount < 2) { + minBufCount = 2; + } + int minFrameCount = mNormalFrameCount * minBufCount; + if (frameCount < minFrameCount) { + frameCount = minFrameCount; + } + } } if (mType == DIRECT) { |
