[Android] Audiotrack::start

Source: Internet
Author: User

Audiotrack's Start method is used to achieve Android audio output, what exactly did start do? Recalling the last section of the previous section createtrack_l, a track handle was returned through binder and saved

status_t audiotrack::createtrack_l (...) {    sp<iaudiotrack> track = Audioflinger->createtrack (...);    Maudiotrack = track;}

Start is primarily called the Start method of the track to achieve the audio output function

-------------------------------------------------------------------------status_t Audiotrack::start () {    Automutex Lock (MLock);    If the audiotrack is already in the start state, return directly if (mstate = = state_active) {return invalid_operation;    } Minunderrun = true;    Save last state previousstate = mstate;    Sets the current state if (previousstate = = state_paused_stopping) {mstate = state_stopping;    } else {mstate = state_active;        }//If the previous state is a stop state, indicating the need to reset position to 0, play from the beginning if (previousstate = = State_stopped | | previousstate = = state_flushed) { Reset current position as seen by client to 0 Mproxy->setepoch (Mproxy->getepoch ()-Mproxy->getposi        tion ());        Force refresh of remaining frames by Processaudiobuffer () as last//write before stop could is partial.    Mrefreshremaining = true;    }//Current position mnewposition = mproxy->getposition () + mupdateperiod; Gets share buffer's flag, atomic operation int32_t flags = Android_atomic_and (~CBLK_disabled, &mcblk->mflags); If there is a callback thread, generally if we call Audiotrack on the apk side independently, the callback thread will not be set, but the Audioplayer system player will set the callback thread//To set the priority, otherwise audio may not get the time slice, and the stutter//if it is Audioplayer, will have its own defined priority, audiotrack after the newly created thread will inherit its priority//if it is the APK call, the priority is generally fixed, then we need to set a android_priority_ here    Audio priority to ensure the smooth output of audio sp<audiotrackthread> t = maudiotrackthread;        if (t! = 0) {if (previousstate = = state_stopping) {//interrupt mproxy->interrupt ();        } else {//resume playing t->resume ();        }} else {//Save current thread priority, set back when stop later mpreviouspriority = getpriority (prio_process, 0);        Get_sched_policy (0, &mpreviousschedulinggroup);    Set thread priority to Android_priority_audio androidsetthreadpriority (0, Android_priority_audio);    } status_t status = No_error; if (! (        Flags & Cblk_invalid) {//If share buffer is available, call track's Start method status = Maudiotrack->start (); if (status = = Dead_object) {Flags|= Cblk_invalid;    }} if (Flags & cblk_invalid) {status = restoretrack_l ("Start");        } if (Status! = No_error) {//start error after processing Aloge ("Start () status%d", status);        Mstate = previousstate;            if (t! = 0) {if (previousstate! = state_stopping) {t->pause ();            }} else {setpriority (prio_process, 0, mpreviouspriority);        Set_sched_policy (0, Mpreviousschedulinggroup); }} return status;}

Since Maudiotrack is a proxy object for binder, start invokes the Start method to the Bbinder object, which is

status_t Audioflinger::trackhandle::start () {    return Mtrack->start ();}

Since we are doing audio output under Playbackthread, we will call further to Playbackthread::track:: Start method, the most important of which is the following two steps:

status_t Audioflinger::P laybackthread::track::start (        playbackthread *playbackthread = (PlaybackThread *) Thread.get ();        Status = playbackthread->addtrack_l (this);}

Remember when we created a mixerthread at the time of the GetOutput, and in createtrack_l, the thread was added to the mplaybackthreads for management, and now we're going to take it out, It's called the addtrack_l method.

audio_io_handle_t audioflinger::openoutput (audio_module_handle_t module,...)     {thread = new Mixerthread (this, output, ID, *pdevices); return ID;} Audioflinger::P laybackthread *audioflinger::checkplaybackthread_l (audio_io_handle_t output) const{return Mplaybackthreads.valuefor (output). get ();}

Within the addtrack_l method, there are three main steps:

    • If the track (share buffer) is a new track, you need to call Startoutput to initialize
    • Add the track to Mactivetracks
    • Send a broadcast to notify Mixerthread to start working
Addtrack_l () must is called with Threadbase::mlock heldstatus_t Audioflinger::P laybackthread::addtrack_l (const SP <Track>& track) {    if (Mactivetracks.indexof (track) < 0) {        status = Audiosystem::startoutput (MId, Track->streamtype (), Track->sessionid ());    }    Mactivetracks.add (track);    Broadcast_l ();}

1. Track initialization

In analyzing getoutput, we already know the call flow of the Audio interface, that is, audiosystem->audiopolicyservice->audio_policy_hal-> Audiopolicymanagerbase, now let's take a look at Audiopolicymanagerbase:: What did Startoutput do

status_t audiopolicymanagerbase::startoutput (audio_io_handle_t output,                                             audiosystem::stream_type stream,                                             int session) {        Checkandsetvolume (stream,                          mstreams[stream].getvolumeindex (newdevice),                          output,                          Newdevice);}

Checkandsetvolume actually just set the stream volume.

2. Track Join Maudiotrack

Maudiotrack is the track set that is contained in the current Mixerthread, which is followed by mixing these track sets

3. broadcast_l
void Audioflinger::P laybackthread::broadcast_l () {    //Thread could is blocked waiting for async    //So signal it to  Handle state changes immediately    //If Threadloop is currently unlocked a signal of MWAITWORKCV of would    //be lost so We also flag to prevent it blocking on MWAITWORKCV    msignalpending = true;    Mwaitworkcv.broadcast ();}

We have mixerthread, because mixerthread inherit and Playbackthread, so run is playbackthread::threadloop, within Threadloop, If the mactivetrack is empty, indicating that no audio data is waiting for the output, then Threadloop will go to sleep and wait for the wake-up, broadcast is doing this wake-up work

BOOL Audioflinger::P Laybackthread::threadloop () {    if (!mactivetracks.size () && systemTime () > Standbytime) | |                                   Issuspended ())        mwaitworkcv.wait (MLock);    }    ...}

The following is the overall process of start

[Android] Audiotrack::start

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.