The first thing to note is that audioplayer processes decoded data.
1. Create an audioplayer object
(1) The audioplayer object is created in the awesomeplayer: play_l () function, and only the audioplayer object is created in the awesomeplayer. cpp file.
If (maudiosource! = NULL) {If (maudioplayer = NULL) {If (maudiosink! = NULL) {// The audioplayer object is created only when the maudiosink parameter is not null and used as the first parameter maudioplayer = new audioplayer (maudiosink, this ); maudioplayer-> setsource (maudiosource); mtimesource = maudioplayer; // If There Was A seek request before we ever started, // honor the request now. // make sure to do this before starting the audio player // to avoid a race condition. seekaudioifnecessary_l ();}}
(2) After you create a maudioplayer in the awesomeplayer: play_l () function, call startaudioplayer_l to execute the output data.
status_t err = startAudioPlayer_l( false /* sendErrorNotification */);
2. awesomeplayer: startaudioplayer_l
Call the start function of maudioplayer to start outputting data.
// We 've already started the mediasource in order to enable // The prefetcher to read its data. status_t err = maudioplayer-> Start (true/* sourcealreadystarted */); // The sourcealreadystarted parameter is true.
3. audioplayer: Start
(1) because the sourcealreadystarted parameter is true, msource-> Start () function is no longer called.
(2) read the decoded data of the first segment.
Mfirstbufferresult = msource-> Read (& mfirstbuffer, & options );
(3) because maudiosink is not empty, the following maudiosink-> OPEN function will be executed, and the audiosinkcallback function will be registered. instead of creating a new audiotrack, The audiocallback function will not be registered.
If (maudiosink. Get ()! = NULL) {status_t err = maudiosink-> open (msamplerate, numchannels, channels, channels, & audioplayer: audiosinkcallback, this); // register the audiosinkcallback function if (Err! = OK) {If (mfirstbuffer! = NULL) {mfirstbuffer-> release (); mfirstbuffer = NULL;} If (! Sourcealreadystarted) {msource-> stop ();} return err;} mlatencyus = (int64_t) maudiosink-> latency () * 1000; mframesize = maudiosink-> framesize (); maudiosink-> Start (); // The actual audiosink implementation class audiooutput: Start (), audiooutput: Start () and audiotrack: Start () start to output data} else {maudiotrack = new audiotrack (audio_stream_music, msamplerate, audio_format_pcm_16_bit, (numchannels = 2 )? Audio_channel_out_stereo: audio_channel_out_mono, 0, 0, & audiocallback, this, 0); // The New audiotrack function is not executed and the audiocallback function is not registered.
4. audioplayer: audiosinkcallback
This callback function is called cyclically when data arrives.
Call the fillbuffer function to fill data
5. audioplayer: fillbuffer
(1) the return value of this function, size_done, indicates the total size of the processed data, which is not necessarily the same as the size of the passed data (the second parameter ).
(2) Obtain decoded data
If (minputbuffer = NULL) {status_t err; If (misfirstbuffer) {// the first data segment, assign mfirstbuffer to minputbuffer = mfirstbuffer; mfirstbuffer = NULL; err = mfirstbufferresult; misfirstbuffer = false;} else {// read data from the mediasource implementation class err = msource-> Read (& minputbuffer, & options );}
(3) obtain the timestamp mpositiontimemediaus stored in a media file.
CHECK(mInputBuffer->meta_data()->findInt64( kKeyTime, &mPositionTimeMediaUs));
(4) Calculate the timestamp of the actual playback position of a frame of data
Mpositiontimerealus = (mnumframesplayed + size_done/mframesize) * 1000000)/msamplerate; logv ("buffer-> size () = % d," mpositiontimemediaus = %. 2f mpositiontimerealus = %. 2f ", minputbuffer-> range_length (), mpositiontimemediaus/1e6, mpositiontimerealus/1e6); // these two timestamps are in awesomeplayer: onvideoevent, the basis for calculating audio/video synchronization is int64_t realtimeus, mediatimeus; If (! (Mflags & audio_at_eos) & maudioplayer! = NULL & maudioplayer-> getmediatimemapping (& realtimeus, & mediatimeus) {mtimesourcedeltaus = realtimeus-mediatimeus ;}
(5) Output decoded data and release the used minputbuffer
If (minputbuffer-> range_length () = 0) {minputbuffer-> release (); minputbuffer = NULL; // release minputbuffer continue;} size_t copy = size_remaining; if (copy> minputbuffer-> range_length () {copy = minputbuffer-> range_length ();} // copy the decoded data to the output buffer memcpy (char *) data + size_done, (const char *) minputbuffer-> data () + minputbuffer-> range_offset (), copy); // after each copy of a piece of data, reset the range of the remaining uncopied data. minputbuffer-> set_range (minputbuffer-> range_offset () + copy, minputbuffer-> range_length ()-copy); size_done + = copy; size_remaining-= copy;