1. Order
The audio decoding process in Mplayer is analyzed step by step.
Audio Decoding, including the video decoding mentioned later, does not involve specific formats and decoding algorithms.
If you are interested in the format and decoding of object files, you can find relevant information on the Internet ~ You can also pay attention to post on popy (advertisement ~
)
Ii. Portal
The entry in the main function is as follows ~
/* = ============================= */
If (mpctx-> sh_audio)
If (! Fill_audio_out_buffers ())
// At eof, all audio at least written to ao
This is derived from mpctx-> sh_audio. I want to emphasize the sh_audio_t structure, which is the structure of the audio stream header,
You need to take a closer look (comment should not be missed )~
// Stream headers:
Typedef struct {
Int aid;
Demux_stream_t * ds;
Struct codecs_st * codec;
Unsigned int format;
Int initialized;
Float stream_delay; // number of seconds stream shocould be delayed (according
To dwStart or similar)
// Output format:
Int sample_format;
Int samplerate;
Int samplesize;
Int channels;
Int o_bps; // = samplerate * samplesize * channels (uncompr. bytes/sec)
Int I _bps; // = bitrate (compressed bytes/sec)
// In buffers:
Int audio_in_minsize; // max. compressed packet size (= min. in buffer size
)
Char * a_in_buffer;
Int a_in_buffer_len;
Int a_in_buffer_size;
// Decoder buffers:
Int audio_out_minsize; // max. uncompressed packet size (= min. out buffsize
)
Char * a_buffer;
Int a_buffer_len;
Int a_buffer_size;
// Output buffers:
Char * a_out_buffer;
Int a_out_buffer_len;
Int a_out_buffer_size;
Struct af_stream_s * afilter; // the audio filter stream
Struct ad_functions_s * ad_driver;
# Ifdef DYNAMIC_PLUGINS
Void * dec_handle;
# Endif
// Win32-compatible codec parameters:
AVIStreamHeader audio;
WAVEFORMATEX * wf;
// Codec-specific:
Void * context; // codec-specific stuff (usually HANDLE or struct pointer)
Unsigned char * codecdata; // extra header daTa passed from demuxer to codec
Int codecdata_len;
Double pts; // last known pts value in output from decoder
Int pts_bytes; // bytes output by decoder after last known pts
Char * lang; // track language
Int default_track;
} Sh_audio_t;
3. step by step
1. Next we will analyze the fill_audio_out_buffers () function
Static int fill_audio_out_buffers (void)
1.1 check the space of the audio driver to fill in the decoded audio data.
Bytes_to_write = mpctx-> audio_out-> get_space ();
If there is free space, Mplayer calls the ao-> play () function to fill in the buffer and play audio data.
The buffer size of the audio driver should be set properly. If the buffer size is too small, the buffer will be
If this parameter is left blank, audio and video files are seriously not synchronized. If this parameter is too large, Mplayer needs to constantly parse media files to fill this field.
Audio buffer, and the video may be too late to play...
1.2 decoding audio streams
If (decode_audio (sh_audio, playsize) <0)
Note: decode_audio is only an interface, not a specific decoding api.
This function obtains decoded or filtered audio data of at least playsize bytes from sh_audio-> a_out_buffer.
, 0 is returned for success, and-1 is returned for failure.
1.3 play the decoded audio data
Playsize = mpctx-> audio_out-> play (sh_audio-> a_out_buffer, playsize, playflags)
;
Note: copy playsize bytes data from sh_audio-> a_out_buffer. Make sure to copy the data here,
This is because after play is called, this part of data will be overwritten. The data does not have to be used up, and the returned value is
Data Length. In addition, when the value of flags | AOPLAY_FINAL_CHUNK is true, the audio file is almost over.
1.4 if (playsize> 0 ){
Sh_audio-> a_out_buffer_len-= playsize;
Memmove (sh_audio-> a_out_buffer, & sh_audio-> a_out_buffer [playsize],
Sh_audio-> a_out_buffer_len );
Mpctx-> delay + = playback_speed * playsize/(double) ao_daTa. bps;
}
After playing the video, remove the data from sh_audio-> a_out_buffer and subtract
Sh_audio-> a_out_buffer_len Length
2. As mentioned earlier, the decode_audio () function is not a real decoding function. It only provides an interface.
Let's see what this function has done.
Int decode_audio (sh_audio_t * sh_audio, int minlen)
2.1 The decoded video data is cut into large and small intervals ~
Int unitsize = sh_audio-> channels * sh_audio-> samplesize * 16;
2.2 If the decoder is set with audio_out_minsize, decoding can be equivalent
While (output_len <target_len) output_len + = audio_out_minsize;
Therefore, we must ensure that a_buffer_size is greater than the length of the decoded data we need plus audio_out_minsize,
Therefore, we have the following restrictions on the maximum decoding length: (is it a bit of a detour ?~~)
Int max_decode_len = sh_audio-> a_buffer_size-sh_audio-> audio_out_minsize
;
2.3 if there is not enough decoded data in a_out_buffer, we will continue to decode the data ~
However, we should note that the data in a_out_buffer is filtered by the filter (the length has changed ).
There will be a filter coefficient, we calculate the length of the data before filtering in the opposite direction, so we need to divide by this coefficient.
While (sh_audio-> a_out_buffer_len <minlen ){
Int declen = (minlen-sh_audio-> a_out_buffer_len)/filter_multiplier
+ (Unitsize <5); // some extra for possible filter buffering
Declen-= declen % unitsize;
If (filter_n_bytes (sh_audio, declen) <0)
Return-1;
}
3. Let's take a look at this filter_n_bytes function.
Static int filter_n_bytes (sh_audio_t * sh, int len)
3.1 Do you still remember the maximum decoding length we just mentioned? Make sure that the decoded data does not overflow.
Assert (len-1 + sh-> audio_out_minsize <= sh-> a_buffer_size );
3.2 decode more data as needed
While (sh-> a_buffer_len <len ){
Unsigned char * buf = sh-> a_buffer + sh-> a_buffer_len;
Int minlen = len-sh-> a_buffer_len;
Int maxlen = sh-> a_buffer_size-sh-> a_buffer_len;
// Call the previously determined audio decoder for real audio decoding.
Int ret = sh-> ad_driver-> decode_audio (sh, buf, minlen, maxlen );
If (ret <= 0 ){
Error =-1;
Len = sh-> a_buffer_len;
Break;
}
// A_buffer_len added after Decoding
Sh-> a_buffer_len + = ret;
}
3.3 As mentioned above, the process of filtering is described in the following figure.
Filter_output = af_play (sh-> afilter, & filter_input );
Note: what we actually do here is to filter this part of work.
----------------------------------
| Decoding | filtering | playing
| Undecoded data | -----> | decoded data | ------> | playback data | ------>
| A_in_buffer | a_buffer | a_out_buffer |
----------------------------------
3.4 if (sh-> a_out_buffer_size <sh-> a_out_buffer_len + filter_output-> len)
Note: If the filtered data is too long, you need to extend the_out_buffer_size.
3.5 remove the filtered data from the decoder buffer:
Sh-> a_buffer_len-= len;
Memmove (sh-> a_buffer, sh-> a_buffer + len, sh-> a_buffer_len );
Iv. Conclusion
Based on the sh_audio_t struct, we analyze fill_audio_out_ B in sequence.
Uffers () function, decode_audio () function, and filter_n_bytes () function, but the specific de
CoDe and play functions.
By the way, looking at Mplayer code, the features of structured modularization are very prominent. Generally, a group is defined first.
Interface, and then the specific program to implement these interfaces, this is very good for code maintenance and expansion ~
Mplayer audio/video sync Learning
The major loop process of mplayer playback is as follows:
While (! Mpctx-> eof ){
Fill_audio_out_buffers (); // read, decode, and play audio streams.
Update_video (& blit_frame); // read, decode, and filter video streams.
Sleep_until_update (& time_frame, & aq_sleep_time); // calculate the delay time and wait for sleep
Mpctx-> video_out-> flip_page (); // video playback
Adjust_sync_and_print_status (frame_time_remaining, time_frame); // perform synchronous correction based on the PTS of the audio and video.
}
The audio/video synchronization method is
1) After audio playback playsize = mpctx-> audio_out-> play (sh_audio-> a_out_buffer, playsize, playflags, calculate the time based on the data size and accumulate the mpctx-> delay + = playback_speed * playsize/(double) ao_daTa. bps;
2) before video decoding, use the accumulated delay time to cut the time of the video in this tutorial.
-= Frame_time;
3) Calculate the sound delay time * time_frame
= Delay-mpctx-> delay/playback_speed;
Float delay = mpctx-> audio_out-> get_delay () is the time required to play all the data in the output buf of the current sound.
4) after the video is synchronized, the video is completely synchronized Based on the audio card's final data output.
5) Calculate the current audio and video PTS difference double AV_delay = a_pts-audio_delay-v_pts; then calculate the correction value x = (AV_delay + timing_error * playback_speed) * 0.1f; at last, we add the correction time to the delay accumulation ;.