Android P 倍速播放的一个数据缓存大小问题
背景:1倍速以上播放的时候没有效果,平台是Android P
错误log 的打印比较明显,buffer大小不够,这里主要是跟下这个buffer的计算逻辑
04-19 15:05:09.110 3151 4918 D AudioTrack: isSampleRateSpeedAllowed_l denied mAfLatency:148 mAfFrameCount:1152 mAfSampleRate:48000 sampleRate:48000 speed:2.000000 mFrameCount:6924 < minFrameCount:13836
04-19 15:05:09.110 3151 4918 W AudioTrack: setPlaybackRate(2.000000, 1.000000) failed (buffer size)
可以看到倍速播放需要的帧缓存buffer数目不够,所以要看下这个 mFrameCount 是如何计算的
bool AudioTrack::isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed)
{
updateLatency_l();
// applicable for mixing tracks only (not offloaded or direct)
if (mStaticProxy != 0) {
return true; // static tracks do not have issues with buffer sizing.
}
const size_t minFrameCount =
AudioSystem::calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate,
sampleRate, speed /*, 0 mNotificationsPerBufferReq*/);
const bool allowed = mFrameCount >= minFrameCount;
ALOGD_IF(!allowed,
"isSampleRateSpeedAllowed_l denied "
"mAfLatency:%u mAfFrameCount:%zu mAfSampleRate:%u sampleRate:%u speed:%f "
"mFrameCount:%zu < minFrameCount:%zu",
mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed,
mFrameCount, minFrameCount);
return allowed;
}
mFrameCount是在 status_t AudioTrack::createTrack_l()函数如下部分赋值的
sp<IAudioTrack> track = audioFlinger->createTrack(input,
output,
&status);
if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("AudioFlinger could not create track, status: %d output %d", status, output.outputId);
if (status == NO_ERROR) {
status = NO_INIT;
}
goto exit;
}
ALOG_ASSERT(track != 0);
mFrameCount = output.frameCount;
接下接看 AudioFlinger::createTrack,这里的计算逻辑是先赋值一个input.frameCount,然后在 AudioFlinger::PlaybackThread::createTrack_l 进一步计算
output.sampleRate = input.config.sample_rate;
output.frameCount = input.frameCount;
output.notificationFrameCount = input.notificationFrameCount;
output.flags = input.flags;
track = thread->createTrack_l(client, streamType, input.attr, &output.sampleRate,
input.config.format, input.config.channel_mask,
&output.frameCount, &output.notificationFrameCount,
input.notificationsPerBuffer, input.speed,
input.sharedBuffer, sessionId, &output.flags,
input.clientInfo.clientTid, clientUid, &lStatus, portId);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
output.afFrameCount = thread->frameCount();
output.afSampleRate = thread->sampleRate();
output.afLatencyMs = thread->latency();
这里面有几个计算逻辑,不一一看了,直接看对应的case了
// For normal PCM streaming tracks, update minimum frame count.
// 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 = latency_l();
if (latencyMs == 0) {
ALOGE("Error when retrieving output stream latency");
lStatus = UNKNOWN_ERROR;
goto Exit;
}
minFrameCount = AudioSystem::calculateMinFrameCount(latencyMs, mNormalFrameCount,
mSampleRate, sampleRate, speed /*, 0 mNotificationsPerBufferReq*/);
// frameCount 要足够大
if (frameCount < minFrameCount) {
frameCount = minFrameCount;
}
倍速的时候也是通过AudioSystem::calculateMinFrameCount 来判断frame count 是否满足条件的,player初始化的时候speed 是为 1.0 的,所以需要input的这个frame count 需要比 1.0 calculateMinFrameCount大,而同样的,如果需要做倍速播放的化,input.framecount 要比 x.0 speed calculateMinFrameCount大