summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libmedia/AudioTrack.cpp128
-rw-r--r--services/audioflinger/AudioFlinger.cpp38
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) {