Audio笔记之AudioFlinger::createTrack

本文深入探讨了 Android AudioFlinger 中的 `createTrack` 函数,该函数用于创建音频轨道。内容涉及参数检查、会话ID管理、效果链迁移以及同步事件处理等关键步骤,展示了音频服务如何确保正确的音频会话配置和管理。
摘要由CSDN通过智能技术生成
sp<IAudioTrack> AudioFlinger::createTrack(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t frameCount,
        IAudioFlinger::track_flags_t *flags,
        const sp<IMemory>& sharedBuffer,
        audio_io_handle_t output,
        pid_t tid,
        int *sessionId,
        status_t *status)
{
    sp<PlaybackThread::Track> track;
    sp<TrackHandle> trackHandle;
    sp<Client> client;
    status_t lStatus;
    int lSessionId;

    // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
    // but if someone uses binder directly they could bypass that and cause us to crash
    if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
        ALOGE("createTrack() invalid stream type %d", streamType);
        lStatus = BAD_VALUE;
        goto Exit;
    }

    // client is responsible for conversion of 8-bit PCM to 16-bit PCM,
    // and we don't yet support 8.24 or 32-bit PCM
    if (audio_is_linear_pcm(format) && format != AUDIO_FORMAT_PCM_16_BIT) {
        ALOGE("createTrack() invalid format %d", format);
        lStatus = BAD_VALUE;
        goto Exit;
    }

    {
        Mutex::Autolock _l(mLock);
        PlaybackThread *thread = checkPlaybackThread_l(output);
        PlaybackThread *effectThread = NULL;
        if (thread == NULL) {
            ALOGE("no playback thread found for output handle %d", output);
            lStatus = BAD_VALUE;
            goto Exit;
        }

        pid_t pid = IPCThreadState::self()->getCallingPid();
        client = registerPid_l(pid);

        ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
        //当sessionId==0时,重新生成ID,由此区分MixChain和NoramChain
        //即不会出现sessionId为0的track,由此可以保留sessionId为0的MixChain保存
        //auxiliary类型的effect
        if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
            // check if an effect chain with the same session ID is present on another
            // output thread and move it here.
            // 查找其它线程中中是否有相同的sessionId的Chain,将其移到本线程中
            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
                if (mPlaybackThreads.keyAt(i) != output) {
                    uint32_t sessions = t->hasAudioSession(*sessionId);
                    if (sessions & PlaybackThread::EFFECT_SESSION) {
                        effectThread = t.get();
                        break;
                    }
                }
            }
            lSessionId = *sessionId;
        } else {
            // if no audio session id is provided, create one here
            lSessionId = nextUniqueId();
            if (sessionId != NULL) {
                *sessionId = lSessionId;
            }
        }
        ALOGV("createTrack() lSessionId: %d", lSessionId);

        track = thread->createTrack_l(client, streamType, sampleRate, format,
                channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);

        // move effect chain to this output thread if an effect on same session was waiting
        // for a track to be created
        // 将Chain切换到本线程中
        if (lStatus == NO_ERROR && effectThread != NULL) {
            Mutex::Autolock _dl(thread->mLock);
            Mutex::Autolock _sl(effectThread->mLock);
            moveEffectChain_l(lSessionId, effectThread, thread, true);
        }

        // Look for sync events awaiting for a session to be used.
        for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
            if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
                if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
                    if (lStatus == NO_ERROR) {
                        (void) track->setSyncEvent(mPendingSyncEvents[i]);
                    } else {
                        mPendingSyncEvents[i]->cancel();
                    }
                    mPendingSyncEvents.removeAt(i);
                    i--;
                }
            }
        }
    }
    if (lStatus == NO_ERROR) {
        trackHandle = new TrackHandle(track);
    } else {
        // remove local strong reference to Client before deleting the Track so that the Client
        // destructor is called by the TrackBase destructor with mLock held
        client.clear();
        track.clear();
    }

Exit:
    if (status != NULL) {
        *status = lStatus;
    }
    return trackHandle;
}

//0、判断是否是fast track模式,来设置输入缓冲区的大小
//1、根据该thread的类型判断输入参数的合法性,
//      具体有MIXER、DIRECT、DUPLICATING、RECORD、OFFLOAD五种类型
//2、构造track,根据是否限时,分为track和timetrack,将其添加到mTracks
//3、如果获得该会话对应EffectChain的input buffer,作为track的main buffer
//      后续由track处理之后的数据交由EffectChain继续处理
//4、根据seesionId关联track与对应的EffectChain,设置track的mMainBuff
//5、如果是Fast track,发送配置event消息
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
        const sp<AudioFlinger::Client>& client,
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t frameCount,
        const sp<IMemory>& sharedBuffer,
        int sessionId,
        IAudioFlinger::track_flags_t *flags,
        pid_t tid,
        int uid,
        status_t *status)
{
    sp<Track> track;
    status_t lStatus;

    bool isTimed = (*flags & IAudioFlinger::TRACK_TIMED) != 0;

    // client expresses a preference for FAST, but we get the final say
    if (*flags & IAudioFlinger::TRACK_FAST) {

    // 需要满足以下条件才会创建fast track,否则创建norm track,并将TRACK_FASTD对应的为位设置为0
    //1、不限时
    //2、属于static类型的track,或者使用输入缓冲区大于等于物理缓冲区的两倍,或者输入缓冲区为0
    //3、属于PCM类型
    //4、属于单声道或者立体声道
    //5、已经构造FastMixer对象,可以对track进行fast mix
    //6、有足够的Fast track使用(总计8个),
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值