Android オーディオ サブシステム (3) ------AudioTrack プロセス分析

こんにちは!カイトさんのブログはこちら

私とのコミュニケーションを歓迎します。


Android N の例を次に示します。


オーディオフリンガー
AudioTrack を理解する前に、AudioTrack、PlaybackThread、および出力ストリーム デバイス間の対応を簡単に説明するインターネットの写真を見つけました。1対1の対応です(OffloadThreadはcompress_offloadデバイスにのみオーディオデータを出力し、MixerThread(FastMixerを使用)はlow_latencyデバイスにのみオーディオデータを出力します)

AudioTrack、PlaybackThread、および出力ストリーム デバイスの関係図から、AudioTrack がオーディオ ストリーム データを対応する PlaybackThread に送信し、アプリケーション プロセスがこれらのオーディオ ストリームを制御したい場合 (たとえば、start() の再生の開始、停止) を確認できます。再生停止()、一時停止再生一時停止()、どうすればいいですか? アプリケーション プロセスと AudioFlinger は同じプロセス上にないことに注意してください。これには、AudioFlinger がオーディオ ストリーム管理機能を提供し、アプリケーション プロセスがプロセス間で AudioFlinger のオーディオ ストリーム ステータスを制御できるようにする一連の通信インターフェイスを提供する必要があります。

AudioFlinger オーディオ ストリーム管理は、AudioFlinger::PlaybackThread::Track によって実装されます。トラックと AudioTrack は 1 対 1 の関係にあります。アプリケーションでは、AudioTrack が作成されるたびに、AudioFlinger 側でトラックが作成されます。それに対応する AudioFlinger の PlaybackThread;

PlaybackThread と AudioTrack/Track は 1 対多の関係にあり、1 つの PlaybackThread で複数のトラックをハングアップできます。Track と AudioTrack の間で、オーディオ データは共有メモリを介して送信されます。これは 2 つの状況に分けることができます
着信音やシステム通知など、メモリをほとんど必要としない再生操作に適しています。
2.MODE_STREAM: ストリーム モードは、ネットワーク ベースのオーディオ ストリーム再生に似ており、オーディオ データは最後まで要件に厳密に従って複数回レシーバに渡されます。これは通常、オーディオ ファイルが大きい場合に適用されます。オーディオ プロパティの要件が高く、サンプリング レートが高く深度が大きいデータなどです。

  • AudioFlinger::PlaybackThread : 再生スレッドの基本クラス、異なる出力識別子を持つオーディオ ストリームは異なるタイプの PlaybackThread インスタンスに対応します
  • AudioFlinger::PlaybackThread::Track : オーディオ ストリーム管理クラス。AudioTrack と AudioFlinger 間のデータ交換用の匿名共有メモリを作成します。
  • AudioFlinger::TrackHandle: The Track object is only responsible for the audio stream management business. 外部へのクロスプロセス Binder 呼び出しインターフェイスを提供せず、アプリケーション プロセスがオーディオ ストリームを制御する必要があるため、オブジェクトが必要です。 Track のクロスプロセス通信をプロキシする. この役割は TrackHandle であり、それを通じて AudioTrack は Track と相互作用する.
  • AudioTrack: Android オーディオ システムによって提供される API クラスで、オーディオ ストリーム データ出力を担当します。各オーディオ ストリームは AudioTrack インスタンスに対応し、異なる出力識別子を持つ AudioTrack は異なる AudioFlinger::PlaybackThread と一致します。
  • AudioTrack::AudioTrackThread : データ送信モードが TRANSFER_CALLBACK の場合、このスレッドを作成する必要があります. ユーザー プロセスから積極的にデータを要求し、audioCallback コールバック関数を呼び出してバッファに入力します. データ送信モードが TRANSFER_SYNC の場合、これがスレッドを作成する必要はありません. ユーザー プロセスは引き続き AudioTrack.write() を呼び出してデータをバッファーに入れるため; データ転送モードが TRANSFER_SHARED の場合, ユーザー プロセスが匿名共有メモリを作成し、一度に再生する音声データをこの匿名共有メモリにコピーします

ソース コードに Audiotrack のアプリケーション例があり、左右のステレオ チャンネルの最大音量をテストするために使用されます。

//frameworks/base/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/audio/MediaAudioTrackTest.java
    public void testSetStereoVolumeMax() throws Exception {
    
    
        // constants for test
        final String TEST_NAME = "testSetStereoVolumeMax";
        final int TEST_SR = 22050;
        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
        final int TEST_MODE = AudioTrack.MODE_STREAM;
        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;

        //-------- initialization --------------
        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
                minBuffSize, TEST_MODE);
        byte data[] = new byte[minBuffSize/2];
        //--------    test        --------------
        track.write(data, 0, data.length);
        track.write(data, 0, data.length);
        track.play();
        float maxVol = AudioTrack.getMaxVolume();//获取最大音量值
        assertTrue(TEST_NAME, track.setStereoVolume(maxVol, maxVol) == AudioTrack.SUCCESS);
        //-------- tear down      --------------
        track.release();
    }

このデモには、AudioTrack の一般的な操作が含まれています。
ステップ 1: getMinBufferSize、最小バッファー サイズを計算する
ステップ 2: audiotrack オブジェクトを作成する ステップ
3: オーディオ データを書き込むための書き込み
ステップ 4: 再生を開始してオーディオを再生する
ステップ 5: リリースして再生を終了する

//@AudioTrack.cpp
AudioTrack::AudioTrack(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t frameCount,
        audio_output_flags_t flags,
        callback_t cbf,
        void* user,
        int32_t notificationFrames,
        audio_session_t sessionId,
        transfer_type transferType,
        const audio_offload_info_t *offloadInfo,
        int uid,
        pid_t pid,
        const audio_attributes_t* pAttributes,
        bool doNotReconnect,
        float maxRequiredSpeed)
    : mStatus(NO_INIT),
      mState(STATE_STOPPED),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousSchedulingGroup(SP_DEFAULT),
      mPausedPosition(0),
      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
    
    
    mStatus = set(streamType, sampleRate, format, channelMask,
            frameCount, flags, cbf, user, notificationFrames,
            0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
            offloadInfo, uid, pid, pAttributes, doNotReconnect, maxRequiredSpeed);
}
status_t AudioTrack::set(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t frameCount,
        audio_output_flags_t flags,
        callback_t cbf,
        void* user,
        int32_t notificationFrames,
        const sp<IMemory>& sharedBuffer,
        bool threadCanCallJava,
        audio_session_t sessionId,
        transfer_type transferType,
        const audio_offload_info_t *offloadInfo,
        int uid,
        pid_t pid,
        const audio_attributes_t* pAttributes,
        bool doNotReconnect,
        float maxRequiredSpeed)
{
    
    
	//......
	// handle default values first.
    if (streamType == AUDIO_STREAM_DEFAULT) {
    
    
        streamType = AUDIO_STREAM_MUSIC;//default则默认为AUDIO_STREAM_MUSIC
    }
    if (pAttributes == NULL) {
    
    
    	//不会超过AUDIO_STREAM_PUBLIC_CNT,一共有13种类型可选择
        if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
    
    
            ALOGE("Invalid stream type %d", streamType);
            return BAD_VALUE;
        }
        //mStreamType赋值,createTrack_l里会用到
        mStreamType = streamType;
    } else {
    
    
        // stream type shouldn't be looked at, this track has audio attributes
        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
        //mStreamType赋值,createTrack_l里会用到
        mStreamType = AUDIO_STREAM_DEFAULT;
        if ((mAttributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
    
    
            flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
        }
        if ((mAttributes.flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
    
    
            flags = (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_FAST);
        }
    }
	//......	
	//mFlags赋值,createTrack_l里会用到
    mOrigFlags = mFlags = flags;
    mCbf = cbf;
    if (cbf != NULL) {
    
    
        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
        mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
        // thread begins in paused state, and will not reference us until start()
    }
    // create the IAudioTrack
    status_t status = createTrack_l();
}
  • 1. 最初に streamType を決定し、AudioTrack メンバー mStreamType に値を割り当てます。
  • 2. AudioTrack メンバー mFlags に値を割り当てます。フラグは AudioTrack の構築時に渡されます。
  • 3. cbf (audioCallback コールバック関数) が空でない場合、audioTrackThread スレッドを作成して audioCallback コールバック関数を処理します (MODE_STREAM モードでは、cbf は空です);
  • 4.実行しますが、すぐには実行されません。開始されるまで一時停止します (スレッドは一時停止状態で開始され、start() まで参照されません);
  • 5. createTrack_l メソッドを呼び出して IAudioTrack を作成します。
status_t AudioTrack::createTrack_l()
{
    
    
	const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();

	status = AudioSystem::getOutputForAttr(attr, &output,
                                           mSessionId, &streamType, mClientUid,
                                           mSampleRate, mFormat, mChannelMask,
                                           mFlags, mSelectedDeviceId, mOffloadInfo);

    sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
                                                      mSampleRate,
                                                      mFormat,
                                                      mChannelMask,
                                                      &temp,
                                                      &flags,
                                                      mSharedBuffer,
                                                      output,
                                                      mClientPid,
                                                      tid,
                                                      &mSessionId,
                                                      mClientUid,
                                                      &status);
	// update proxy
	//用于管理共享内存
    if (mSharedBuffer == 0) {
    
    //MODE_STREAM
        mStaticProxy.clear();
        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
    } else {
    
    //MODE_STATIC
        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
        mProxy = mStaticProxy;
    }

}
  • 1. audioFlinger を取得する
  • 2. getOutputForAttr は、AudioTrack によって渡されたサウンド タイプに従って属性を設定し、サウンド属性に従ってそのグループ/カテゴリを決定し、デバイスを見つけ、最後にデバイスに従って対応する出力を見つけます。(デバイスは複数の出力に対応する場合があります(各サウンドカードは出力に対応します)が、選択されるのは 1 つだけです)
  • 3. AudioFlinger::PlaybackThread::Track を作成します。(AudioTrack 作成プロセス中に、出力を選択します。出力は再生デバイスに対応し、PlaybackThread にも対応します。アプリケーションの AudioTrack は PlaybackThread のトラックに対応します)。
  • 4. AudioTrackClientProxy/StaticAudioTrackClientProxy を作成して、共有メモリを管理します。(APP の AudioTrack <==> スレッドのトラックは、共有メモリを介してデータを転送します)

次の関数呼び出しスタックは次のとおりです。

AudioTrack::createTrack_l
	AudioSystem::getOutputForAttr
		AudioPolicyService::getOutputForAttr
			AudioPolicyManager::getOutputForAttr
				AudioPolicyManager::getOutputForDevice
					AudioPolicyService::AudioPolicyClient::openOutput
						af->openOutput
	AudioFlinger::createTrack
		AudioFlinger::PlaybackThread::createTrack_l
			AudioFlinger::PlaybackThread::Track::Track
				AudioFlinger::ThreadBase::TrackBase::TrackBase
				new AudioTrackServerProxy/StaticAudioTrackServerProxy
		new TrackHandle
	new AudioTrackClientProxy/StaticAudioTrackClientProxy

AudioSystem::getOutputForAttr を見てください。

//@AudioTrack.cpp
status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
                                        audio_io_handle_t *output,
                                        audio_session_t session,
                                        audio_stream_type_t *stream,
                                        uid_t uid,
                                        uint32_t samplingRate,
                                        audio_format_t format,
                                        audio_channel_mask_t channelMask,
                                        audio_output_flags_t flags,
                                        audio_port_handle_t selectedDeviceId,
                                        const audio_offload_info_t *offloadInfo)
{
    
    
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return NO_INIT;
    return aps->getOutputForAttr(attr, output, session, stream, uid,
                                 samplingRate, format, channelMask,
                                 flags, selectedDeviceId, offloadInfo);
}
//@AudioPolicyInterfaceImpl.cpp
status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
                                              uid_t uid,
                                              uint32_t samplingRate,
                                              audio_format_t format,
                                              audio_channel_mask_t channelMask,
                                              audio_output_flags_t flags,
                                              audio_port_handle_t selectedDeviceId,
                                              const audio_offload_info_t *offloadInfo)
{
    
    
    if (mAudioPolicyManager == NULL) {
    
    
        return NO_INIT;
    }
    ALOGV("getOutput()");
    Mutex::Autolock _l(mLock);

    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate,
                                    format, channelMask, flags, selectedDeviceId, offloadInfo);
}
//@AudioPolicyManager.cpp
status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
                                              uid_t uid,
                                              uint32_t samplingRate,
                                              audio_format_t format,
                                              audio_channel_mask_t channelMask,
                                              audio_output_flags_t flags,
                                              audio_port_handle_t selectedDeviceId,
                                              const audio_offload_info_t *offloadInfo)
{
    
    
    audio_attributes_t attributes;
    if (attr != NULL) {
    
    
        if (!isValidAttributes(attr)) {
    
    
            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                  attr->usage, attr->content_type, attr->flags,
                  attr->tags);
            return BAD_VALUE;
        }
        attributes = *attr;
    } else {
    
    
        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
    
    
            ALOGE("getOutputForAttr():  invalid stream type");
            return BAD_VALUE;
        }
        stream_type_to_audio_attributes(*stream, &attributes);
    }
	//根据attributes获取策略strategy,即获取类别/组
	routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
	//根据strategy获取device,即根据类别/组获取播放设备(耳机、蓝牙、外放喇叭)
    audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
	//哪些output上有对应当device
	*output = getOutputForDevice(device, session, *stream,
                                 samplingRate, format, channelMask,
                                 flags, offloadInfo);
}
//@AudioPolicyManager.cpp
audio_io_handle_t AudioPolicyManager::getOutputForDevice(
        audio_devices_t device,
        audio_session_t session,
        audio_stream_type_t stream,
        uint32_t samplingRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        audio_output_flags_t flags,
        const audio_offload_info_t *offloadInfo)
{
    
    
	audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
	//......
	status = mpClientInterface->openOutput(profile->getModuleHandle(),
                                               &output,
                                               &config,
                                               &outputDesc->mDevice,
                                               address,
                                               &outputDesc->mLatency,
                                               outputDesc->mFlags);
	//......
	return output;
}
//@AudioPolicyClientImpl.cpp
status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t module,
                                                           audio_io_handle_t *output,
                                                           audio_config_t *config,
                                                           audio_devices_t *devices,
                                                           const String8& address,
                                                           uint32_t *latencyMs,
                                                           audio_output_flags_t flags)
{
    
    
    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
    //af即AudioFlinger,这里即是AudioFlinger::openOutput
    return af->openOutput(module, output, config, devices, address, latencyMs, flags);
}

getOutputForAttr は、出力の出力チャンネルを取得します (出力は、プライマリ アウト、低レイテンシー アウト、オフロード、direct_pcm、a2dp 出力、usb_device 出力、dp 出力などを含む、hal 層のオーディオ チャンネルの代表として理解できます)。 AudioFlinger::openOutputのプロセスは、次の記事を参照してください: Android オーディオ サブシステム (1) ------ openOutput オープン プロセス

したがって、最終的に getOutputForAttr は attr、streamType およびその他のパラメーターを渡し、デバイスを選択して OutputFor を取得します (実際、AudioPolicyClient::openOutput は開いているデバイスを返します)。

sp<IAudioTrack> AudioFlinger::createTrack(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t *frameCount,
        audio_output_flags_t *flags,
        const sp<IMemory>& sharedBuffer,
        audio_io_handle_t output,
        pid_t pid,
        pid_t tid,
        audio_session_t *sessionId,
        int clientUid,
        status_t *status)
{
    
    
    sp<PlaybackThread::Track> track;
    sp<TrackHandle> trackHandle;
    sp<Client> client;

	PlaybackThread *thread = checkPlaybackThread_l(output);

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

	// return handle to client
    trackHandle = new TrackHandle(track);
}
  • 1. checkPlaybackThread_l を使用して、audio_io_handle_t 型パラメーターに従って、対応する PlaybackThread を見つけます (これらは対応関係です)。
  • 2. PlaybackThread::createTrack_l を呼び出して、Track オブジェクトを作成し、mTracks に追加します。トラックが構築されたら、AudioFlinger と AudioTrack 間のデータ交換用にメモリのブロックを割り当て (audio_track_cblk_t* mCblk は制御ブロック)、AudioTrackServerProxy /StaticAudioTrackServerProxy オブジェクトを作成して Buffer を管理します (PlaybackThread はそれを使用して読み取り可能なデータの場所を取得します)。バッファから)
  • 3. Track 通信エージェント TrackHandle を作成し、trackHandle に割り当てます。

ここでは、AudioTrack オブジェクトを作成すると、特定の PlaybackThread で Track オブジェクトが作成されることもわかります。これらは対応する関係です。

//@Threads.cpp
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 *pFrameCount,
        const sp<IMemory>& sharedBuffer,
        audio_session_t sessionId,
        audio_output_flags_t *flags,
        pid_t tid,
        int uid,
        status_t *status)
{
    
    
	//......
	track = new Track(this, client, streamType, sampleRate, format,
                          channelMask, frameCount, NULL, sharedBuffer,
                          sessionId, uid, *flags, TrackBase::TYPE_DEFAULT);
    //PlaybackThread中存在一个数组mTracks,其中包含一个或者多个Track
    //每一个Track都对应应用程序中创建的AudioTrack
	mTracks.add(track);
}
//@Tracks.cpp
AudioFlinger::PlaybackThread::Track::Track(
            PlaybackThread *thread,
            const sp<Client>& client,
            audio_stream_type_t streamType,
            uint32_t sampleRate,
            audio_format_t format,
            audio_channel_mask_t channelMask,
            size_t frameCount,
            void *buffer,
            const sp<IMemory>& sharedBuffer,
            audio_session_t sessionId,
            int uid,
            audio_output_flags_t flags,
            track_type type)
    :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
                  (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
                  sessionId, uid, true /*isOut*/,
                  (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
                  type),
    mFillingUpStatus(FS_INVALID),
    // mRetryCount initialized later when needed
        mSharedBuffer(sharedBuffer),
    mStreamType(streamType),
    mName(-1),  // see note below
    mMainBuffer(thread->mixBuffer()),
    mAuxBuffer(NULL),
    mAuxEffectId(0), mHasVolumeController(false),
    mPresentationCompleteFrames(0),
    mFrameMap(16 /* sink-frame-to-track-frame map memory */),
    // mSinkTimestamp
    mFastIndex(-1),
    mCachedVolume(1.0),
    mIsInvalid(false),
    mAudioTrackServerProxy(NULL),
    mResumeToStopping(false),
    mFlushHwPending(false),
    mFlags(flags)
{
    
    
	if (sharedBuffer == 0) {
    
    
        mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize, !isExternalTrack(), sampleRate);
    } else {
    
    
        mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize);
    }
    mServerProxy = mAudioTrackServerProxy;
}
//@Tracks.cpp
AudioFlinger::ThreadBase::TrackBase::TrackBase(
            ThreadBase *thread,
            const sp<Client>& client,
            uint32_t sampleRate,
            audio_format_t format,
            audio_channel_mask_t channelMask,
            size_t frameCount,
            void *buffer,
            audio_session_t sessionId,
            int clientUid,
            bool isOut,
            alloc_type alloc,
            track_type type)
    :   RefBase(),
        mThread(thread),
        mClient(client),
        mCblk(NULL),
        // mBuffer
        mState(IDLE),
        mSampleRate(sampleRate),
        mFormat(format),
        mChannelMask(channelMask),
        mChannelCount(isOut ?
                audio_channel_count_from_out_mask(channelMask) :
                audio_channel_count_from_in_mask(channelMask)),
        mFrameSize(audio_has_proportional_frames(format) ?
                mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
        mFrameCount(frameCount),
        mSessionId(sessionId),
        mIsOut(isOut),
        mServerProxy(NULL),
        mId(android_atomic_inc(&nextTrackId)),
        mTerminated(false),
        mType(type),
        mThreadIoHandle(thread->id())
{
    
    
    size_t size = sizeof(audio_track_cblk_t);
    size_t bufferSize = (buffer == NULL ? roundup(frameCount) : frameCount) * mFrameSize;
    /*如果buffer为空,并且alloc == ALLOC_CBLK*/
    if (buffer == NULL && alloc == ALLOC_CBLK) {
    
    
    	/*size为一个头部(起到控制作用),如果buffer为NULL,即应用程序没有分配,则大小增加bufferSize*/
        size += bufferSize;
    }

    if (client != 0) {
    
    
    	/*分配内存*/
        mCblkMemory = client->heap()->allocate(size);
    } else {
    
    
        // this syntax avoids calling the audio_track_cblk_t constructor twice
        mCblk = (audio_track_cblk_t *) new uint8_t[size];
        // assume mCblk != NULL
    }
    // construct the shared structure in-place.
    if (mCblk != NULL) {
    
    
        new(mCblk) audio_track_cblk_t();
        switch (alloc) {
    
    
        case ALLOC_READONLY: {
    
    
            const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
            if (roHeap == 0 ||
                    (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
                    (mBuffer = mBufferMemory->pointer()) == NULL) {
    
    
                mCblkMemory.clear();
                mBufferMemory.clear();
                return;
            }
            memset(mBuffer, 0, bufferSize);
            } break;
        case ALLOC_PIPE:
            mBufferMemory = thread->pipeMemory();
            // mBuffer is the virtual address as seen from current process (mediaserver),
            // and should normally be coming from mBufferMemory->pointer().
            // However in this case the TrackBase does not reference the buffer directly.
            // It should references the buffer via the pipe.
            // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
            mBuffer = NULL;
            break;
        case ALLOC_CBLK:
            // clear all buffers
            if (buffer == NULL) {
    
    
                mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
                memset(mBuffer, 0, bufferSize);
            } else {
    
    
                mBuffer = buffer;
            }
            break;
        case ALLOC_LOCAL:
            mBuffer = calloc(1, bufferSize);
            break;
        case ALLOC_NONE:
            mBuffer = buffer;
            break;
        }
}

上記の Track コンストラクターでは、アプリケーションが MODE_STREAM モードの場合、Buffer を管理するために AudioTrackServerProxy が作成されます。それ以外の場合は、Buffer を管理するために MODE_STATIC モードで StaticAudioTrackServerProxy が作成されます。

前に言ったように、APP が AudioTrack を作成し、次に AudioFlinger::playbackThread が対応するトラックを作成します。それらは共有メモリを介してデータを渡します:
Track は AudioTrackServerProxy/StaticAudioTrackServerProxy を使用して Buffer を管理し、対応して AudioTrack は AudioTrackClientProxy/StaticAudioTrackClientProxy を使用して AudioTrack::set の Buffer を管理します。

Track 内の AudioTrackServerProxy/StaticAudioTrackServerProxy はすべて ServerProxy から継承されます。ServerProxy は、obtainBuffer、releaseBuffer 関数を含む共有メモリの管理に使用され、playbackThread は obtiainBuffer を使用してデータを含むメモリを取得し、releaseBuffer を使用して消費後にデータを解放します。

//@AudioTrackShared.h
// Proxy used by AudioFlinger server
class ServerProxy : public Proxy {
    
    
	virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush = false);
	virtual void        releaseBuffer(Buffer* buffer);
}

Android は大きすぎ、プロセスが多すぎます。. . . . .

一般に、AudioTrack は次の 3 つのステップに単純に分けることができます。
1 AudioTrack のプロパティを使用して、AudioPolicy に従って対応する出力と PlaybackThread を見つけます。 2 PlaybackThread に
対応するトラックを作成します。
3 APP の AudioTrack と mTracks のトラックの間共有メモリの作成

おすすめ

転載: blog.csdn.net/Guet_Kite/article/details/114535241