Android Audio Subsystem - AudioTrack - play

 

 

 

1.        AudioTrack::play()

Frameworks/base/media/java/android/media/AudioTrack.java

   public void play()

   throws IllegalStateException {

       if (mState != STATE_INITIALIZED) {

           throw new IllegalStateException("play() called on uninitializedAudioTrack.");

       }

 

       synchronized(mPlayStateLock) {

           native_start();

           mPlayState = PLAYSTATE_PLAYING;

       }

}

 

2.       android_media_AudioTrack_start()

frameworks/base/core/jni/android_media_AudioTrack.cpp

static void

android_media_AudioTrack_start(JNIEnv*env, jobject thiz)

{

   sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);

 

//这儿lpTrack是保存在javaenv中本地AudioTrack对象

//这个对象的mAudioTrack成员变量指向一个BpAudioTrack(BpBinder)对象

 

    if (lpTrack == NULL) {

        jniThrowException(env,"java/lang/IllegalStateException",

            "Unable to retrieve AudioTrackpointer for start()");

        return;

    }

 

   lpTrack->start();

}

 

3.      AudioTrack::start()

Frameworks/av/media/libmedia/AudioTrack.cpp

voidAudioTrack::start()

{

    sp<AudioTrackThread> t =mAudioTrackThread;

 

    ALOGV("start %p", this);

 

    AutoMutex lock(mLock);

    // acquire a strong reference on theIMemory and IAudioTrack so that they cannot be destroyed

    // while we are accessing the cblk

 

   sp<IAudioTrack> audioTrack = mAudioTrack;  

// get BpAudioTrack(BpBinder)对象指针

 

    sp<IMemory> iMem = mCblkMemory;

    audio_track_cblk_t* cblk = mCblk;

 

    if (!mActive) {

        mFlushed = false;

        mActive = true;

        mNewPosition = cblk->server +mUpdatePeriod;

        cblk->lock.lock();

        cblk->bufferTimeoutMs =MAX_STARTUP_TIMEOUT_MS;

        cblk->waitTimeMs = 0;

        android_atomic_and(~CBLK_DISABLED,&cblk->flags);

        if (t != 0) {

            t->resume();

        } else {

            mPreviousPriority =getpriority(PRIO_PROCESS, 0);

            get_sched_policy(0,&mPreviousSchedulingGroup);

            androidSetThreadPriority(0,ANDROID_PRIORITY_AUDIO);

        }

 

        ALOGV("start %p before lock cblk%p", this, cblk);

        status_t status = NO_ERROR;

        if (!(cblk->flags &CBLK_INVALID)) {

            cblk->lock.unlock();

           ALOGV("mAudioTrack->start()");

 

           status =mAudioTrack->start();

 

// mAudioTrack指向BpAudioTrack(BpBinder)对象

//因此这儿实际调用的是BpAudioTrack::start()

 

            cblk->lock.lock();

            if (status == DEAD_OBJECT) {

                android_atomic_or(CBLK_INVALID,&cblk->flags);

            }

        }

        if (cblk->flags & CBLK_INVALID){

            audio_track_cblk_t* temp = cblk;

            status = restoreTrack_l(temp, true/*fromStart*/);

            cblk = temp;

        }

        cblk->lock.unlock();

        if (status != NO_ERROR) {

            ALOGV("start() failed");

            mActive = false;

            if (t != 0) {

                t->pause();

            } else {

                setpriority(PRIO_PROCESS, 0,mPreviousPriority);

                set_sched_policy(0,mPreviousSchedulingGroup);

            }

        }

    }

 

}

 

4.      BpAudioTrack::start()

Frameworks/av/media/libmedia/IAudioTrack.cpp

    virtual status_t start()

    {

        Parcel data, reply;

       data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());

 

       status_t status= remote()->transact(START, data, &reply);

 

// remote返回 BpAudioTrack::mRemote成员变量

//这个变量指向一个BpBinder对象

//因此这儿实际调用的BpBinder::transact()

 

        if (status == NO_ERROR) {

            status = reply.readInt32();

        } else {

            ALOGW("start() error:%s", strerror(-status));

        }

        return status;

    }

5.      BpBinder::transact()

Frameworks/native/libs/binder/BpBinder.cpp

status_tBpBinder::transact(

    uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)

{

    // Once a binder has died, it will nevercome back to life.

    if (mAlive) {

       status_t status= IPCThreadState::self()->transact(

           mHandle,code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

 

    return DEAD_OBJECT;

}

 

6.      IPCThreadState::transact()

……………………………………….

IPCThreadState::waitForResponse()  -> executeCommand()

……………………………………….

7.      BBinder::transact()

                   --status_t AudioFlinger::TrackHandle::onTransact(

    uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)

{

         return   BnAudioTrack::onTransact(code, data, reply, flags);

}

8.      BnAudioTrack::onTransact()

Frameworks/av/media/libmedia/IAudioTrack.cpp

status_tBnAudioTrack::onTransact(

    uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)

{

    switch (code) {

        case GET_CBLK: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

           reply->writeStrongBinder(getCblk()->asBinder());

            return NO_ERROR;

        } break;

        case START: {

           CHECK_INTERFACE(IAudioTrack, data, reply);

           reply->writeInt32(start());

            return NO_ERROR;

        } break;

        case STOP: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

            stop();

            return NO_ERROR;

        } break;

        case FLUSH: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

            flush();

            return NO_ERROR;

        } break;

        case PAUSE: {

            CHECK_INTERFACE(IAudioTrack, data, reply);

            pause();

            return NO_ERROR;

        }

        case ATTACH_AUX_EFFECT: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

           reply->writeInt32(attachAuxEffect(data.readInt32()));

            return NO_ERROR;

        } break;

        case ALLOCATE_TIMED_BUFFER: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

            sp<IMemory> buffer;

            status_t status =allocateTimedBuffer(data.readInt32(), &buffer);

            reply->writeInt32(status);

            if (status == NO_ERROR) {

               reply->writeStrongBinder(buffer->asBinder());

            }

            return NO_ERROR;

        } break;

        case QUEUE_TIMED_BUFFER: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

            sp<IMemory> buffer =interface_cast<IMemory>(

                data.readStrongBinder());

            uint64_t pts = data.readInt64();

           reply->writeInt32(queueTimedBuffer(buffer, pts));

            return NO_ERROR;

        } break;

        case SET_MEDIA_TIME_TRANSFORM: {

            CHECK_INTERFACE(IAudioTrack, data,reply);

            LinearTransform xform;

            xform.a_zero = data.readInt64();

            xform.b_zero = data.readInt64();

            xform.a_to_b_numer = data.readInt32();

            xform.a_to_b_denom =data.readInt32();

            int target = data.readInt32();

           reply->writeInt32(setMediaTimeTransform(xform, target));

            return NO_ERROR;

        } break;

        default:

            return BBinder::onTransact(code,data, reply, flags);

    }

}

 

9.      AudioFlinger::TrackHandle::start()

Frameworks/av/services/audioflinger/AudioFlinger.cpp

status_t AudioFlinger::TrackHandle::start() {

    return mTrack->start();

}

10.  AudioFlinger::PlaybackThread::Track::start()

Frameworks/av/services/audioflinger/Tracks.cpp

status_tAudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,

                                                   int triggerSession)

{

    status_t status = NO_ERROR;

    ALOGV("start(%d), calling pid %dsession %d",

            mName,IPCThreadState::self()->getCallingPid(), mSessionId);

 

    sp<ThreadBase> thread =mThread.promote();

    if (thread != 0) {

        Mutex::Autolock _l(thread->mLock);

        track_state state = mState;

        // here the track could be either new,or restarted

        // in both cases "unstop" thetrack

        if (state == PAUSED) {

            mState = TrackBase::RESUMING;

            ALOGV("PAUSED => RESUMING(%d) on thread %p", mName, this);

        } else {

            mState = TrackBase::ACTIVE;

            ALOGV("? => ACTIVE (%d) onthread %p", mName, this);

        }

 

        if (!isOutputTrack() && state!= ACTIVE && state != RESUMING) {

            thread->mLock.unlock();

            status =AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);

            thread->mLock.lock();

 

#ifdefADD_BATTERY_DATA

            // to track the speaker usage

            if (status == NO_ERROR) {

                addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);

            }

#endif

        }

        if (status == NO_ERROR) {

           PlaybackThread *playbackThread = (PlaybackThread *)thread.get();

           playbackThread->addTrack_l(this);

        } else {

            mState = state;

           triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);

        }

    } else {

        status = BAD_VALUE;

    }

    return status;

}

 

11.  AudioFlinger::PlaybackThread::addTrack_l()

Frameworks/av/services/audioflinger/Threads.cpp

status_tAudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)

{

    status_t status = ALREADY_EXISTS;

    // set retry count for buffer fill

    track->mRetryCount =kMaxTrackStartupRetries;

    if (mActiveTracks.indexOf(track) < 0) {

        // the track is newly added, make sureit fills up all its

        // buffers before playing. This is toensure the client will

        // effectively get the latency itrequested.

        track->mFillingUpStatus =Track::FS_FILLING;

        track->mResetDone = false;

        track->mPresentationCompleteFrames =0;

       mActiveTracks.add(track);

        sp<EffectChain> chain =getEffectChain_l(track->sessionId());

        if (chain != 0) {

            ALOGV("addTrack_l() startingtrack on chain %p for session %d", chain.get(),

                    track->sessionId());

            chain->incActiveTrackCnt();

        }

        status = NO_ERROR;

    }

    ALOGV("mWaitWorkCV.broadcast");

   mWaitWorkCV.broadcast();

 

    return status;

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值