对于AudioTrack的认识(1)

来源:互联网 发布:单片机代码工具 编辑:程序博客网 时间:2024/03/29 15:04
  AudioTrack 主要的作用是播放音频,它是通过本地代码实现的。我主要是从两个方面分析AudioTrack,一是AudioTrack的系统架构,而是AudioTrack的使用。
AudioTrack的架构。
  在android4.2.1中与 AudioTrack相关的代码分布在如下软件层中。
1. Application Framework
<1>AudioTrack.java(frameworks/base/media/java/android/media/AudioTrack.java)
   AudioTrack.java 的主要作用是向Application层提供AudioTack的API。
   AudioTrack.java 通过JNI 和AudioTrack的本地代码联系起来。AudioTrack的本地代码主要是在Libary 层。
<2>android_media_AudioTrack.cpp(frameworks/base/core/jni/android_media_AudioTrack.cpp
   在这个jni中,会调用与AudioTrack相关的本地代码,如AudioTrack.cpp,AudioSystem.cpp
2. Libaries And Android Runtime
<1>AudioTrack.cpp
   主要功能是通过 IAudioTrack来实现的。IAudioTrack和IAudioFlinger 的架构是一样的,都是基于Binder的服务架构。但是 IAudioFlinger 的实现类是 AudioFlinger.
但是 IAudioTrack的实现类不是 AudioTrack,而是 AudioFlinger 的内部类 TrackHandle,而TrackHandle 的核心则是 PlaybackThread::Track。换句话说IAudioTrack的功能是通过 PlaybackThread::Track,来实现的,PlaybackThread::Track,通过 AudioSystem.cpp调用 AudioPolicyService的功能,然后 AudioPolicyService 调用HAL 的功能。
<2>IAudioTrack.cpp
   IAudioTrack是 AudioFlinger 提供给 AudioTrack 的接口。
<3>AudioFlinger.cpp
   Audio 的核心Native Service,主要用于控制音频的输入输出,直接和HAL 通信,通过IAudioFlinger 提供调用接口。
   AudioFlinger中的内部类TrackHanler,实现了Binder 接口IAudioTrack,也可以这么说,AudioFlinger 通过 IAudioFlinger 和 IAudioTrack,提供调用接口。
<4>AudioPolicyService.cpp
   Audio 的核心 Native Service ,主要用于控制音频输入输出的策略,直接和 HAL 通信,通过IAudioPolicyService 提供调用接口。
<5>AudioSystem.cpp
   主要是一个 控制器的作用,核心功能通过调用 IAudioFlinger,IAudioPolicyService 来实现。在Application Framework 中有  AudioSystem.java 和 android_media_AudioSystem.cpp 与它的功能对应。
3. HAL 层
   这里不具体介绍Audio 的HAL 层,它会直接和 Audio Driver 交互。
AudioTrack 的初始化
1.AudioTrack::AudioTrack(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        const sp<IMemory>& sharedBuffer,
        audio_output_flags_t flags,
        callback_t cbf,
        void* user,
        int notificationFrames,
        int sessionId)
    : mStatus(NO_INIT),
      mIsTimed(false),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousSchedulingGroup(SP_DEFAULT)
{
    mStatus = set(streamType, sampleRate, format, channelMask,
            0 /*frameCount*/, flags, cbf, user, notificationFrames,
            sharedBuffer, false /*threadCanCallJava*/, sessionId);
}
2.调用 AudioTrack::set 方法。
3.调用 AudioTrack::createTrack_l 方法
4.调用 AudioFlinger::createTrack 方法
  sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
                                                      streamType,
                                                      sampleRate,
                                                      format,
                                                      channelMask,
                                                      frameCount,
                                                      trackFlags,
                                                      sharedBuffer,
                                                      output,
                                                      tid,
                                                      &mSessionId,
                                                      &status);
5.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
        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();
    }
  返回 TrackHandle,TrackHandle 持有 PlaybackThread::Track 对象。
6.调用 PlaybackThread::createTrack_l
  if (!isTimed) {
            track = new Track(this, client, streamType, sampleRate, format,
                    channelMask, frameCount, sharedBuffer, sessionId, flags);
        } else {
            track = TimedTrack::create(this, client, streamType, sampleRate, format,
                    channelMask, frameCount, sharedBuffer, sessionId);
        }
        if (track == 0 || track->getCblk() == NULL || track->name() < 0) {
            lStatus = NO_MEMORY;
            goto Exit;
        }
        mTracks.add(track);

原创粉丝点击