Mplayer audio decoding Analysis

Source: Internet
Author: User

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 ;.

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.