Android11 AudioTrack和Track建立联系

发布于:2024-06-04 ⋅ 阅读:(51) ⋅ 点赞:(0)

应用程序创建AudioTrack时,导致AudioFlinger在播放线程中,创建Track和其对应。那它们之间是通过什么来建立联系传递数据的?答案是共享内存。
创建Track时,导致其父类TrackBase的构造函数被调用

//frameworks/av/services/audioflinger/Tracks.cpp
AudioFlinger::ThreadBase::TrackBase::TrackBase(/*省略*/){
	//省略
	 size_t size = sizeof(audio_track_cblk_t);//大小为audio_track_cblk_t
    if (buffer == NULL && alloc == ALLOC_CBLK) {//如果客户端没有申请过共享内存
      	//省略
        size += bufferSize;//大小要加上buffer的大小
    }
	
	/*开始申请了*/
	if (client != 0) {
        mCblkMemory = client->heap()->allocate(size);
        if (mCblkMemory == 0 ||
                (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
        	//省略
            return;
        }
    } else {
        mCblk = (audio_track_cblk_t *) malloc(size);
        //省略
    }

	if (mCblk != NULL) {
        new(mCblk) audio_track_cblk_t();
        switch (alloc) {

		//省略
		case ALLOC_CBLK:
            // clear all buffers
            if (buffer == NULL) {//由AudioFlinger申请的共享内存
                mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);//要加上audio_track_cblk_t,才是指向的真实buffer
                memset(mBuffer, 0, bufferSize);
            } else {
                mBuffer = buffer;//由客户端申请的内存,mBuffer 直接指向它
            }
            break;

		}
	}
}

可以看出,共享内存可以由客户端申请,也可以由AudioFlinger申请。
客户端已经申请了buffer:
AudioFlinger这边,只会申请audio_track_cblk_t头部信息,不会再去申请buffer了,而是直接将mBuffer 指向客户端申请的buffer

客户端没有申请buffer:
AudioFlinger这边除了申请audio_track_cblk_t外,还会去申请buffer,并且将mBuffer 指向自己申请的这块buffer

管理共享内存

共享内存创建好之后,客户端和AudioFlinger都需要管理这块内存。AudioFlinger通过mServerProxy来管理

//frameworks/av/services/audioflinger/Tracks.cpp
if (sharedBuffer == 0) {
        mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize, !isExternalTrack(), sampleRate);
    } else {
        mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize, sampleRate);
    }
    mServerProxy = mAudioTrackServerProxy;

对于是客户端创建的内存,使用 StaticAudioTrackServerProxy 来管理,对于AudioFlinger创建的内存,使用AudioTrackServerProxy来管理。

客户端通过mProxy来管理

//frameworks/av/media/libaudioclient/AudioTrack.cpp
//省略
sp<IMemory> iMem = track->getCblk();//获取内存地址,包含了audio_track_cblk_t头部地址
void *iMemPointer = iMem->unsecurePointer();//指向它

audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
mCblk = cblk;

void* buffers;
if (mSharedBuffer == 0) {//AudioFlinger申请的内存
        buffers = cblk + 1;//指向buffer
} else {
	buffers = mSharedBuffer->unsecurePointer();
}

 // update proxy
    if (mSharedBuffer == 0) {
        mStaticProxy.clear();
        mProxy = new AudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
    } else {
        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
        mProxy = mStaticProxy;
    }

对于是客户端创建的内存,客户端使用 StaticAudioTrackClientProxy来管理,对于AudioFlinger创建的内存,使用AudioTrackClientProxy来管理。

总结
AudioTrack和Track之间通过共享内存来建立联系,这个内存可以由客户端的AudioTrack创建,也可以由AudioFlinger的Track创建。但是audio_track_cblk_t一定是由Track创建的。客户端和AudioFlinger分别通过mProxy 和mServerProxy 来管理这块内存。

在这里插入图片描述