美文网首页
Android P 倍速播放的一个数据缓存大小问题

Android P 倍速播放的一个数据缓存大小问题

作者: Nothing_655f | 来源:发表于2022-04-22 18:57 被阅读0次

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大

相关文章

网友评论

      本文标题:Android P 倍速播放的一个数据缓存大小问题

      本文链接:https://www.haomeiwen.com/subject/ivinertx.html