FFplay audio filter analysis

The filter of the audio stream is  configure_audio_filters() created through a function, because  ffplay for the generality of the code, even if the command line parameter does not use the filter, AVFrame it will pass through the empty filter to make the following appearance.

configure_audio_filters() The flowchart of the function is as follows:

configure_audio_filters() The function is defined as follows:

static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format){....}

The parameters of this function are explained below.

VideoState *is , is the global manager of the ffplay player.

char *afilters, is a filter string, such as the following command:

ffplay -af "atempo=2.0" -i juren-5s.mp4

"atempo=2.0" This string will be assigned to  afilters .

int force_output_format , which means whether to force  buffersink the audio frame sampling and other information of the export filter to be set to be the  is->audio_tgt same.

As I said before,  is->audio_tgt it is the information that the audio hardware device is turned on. is->audio_tgt is the final audio format to be passed to SDL. All the sampling rate, the number of channels, etc. must be converted into the final  is->audio_tgt .


Let's analyze configure_audio_filters() the key code in the function, as follows:

This function defines some arrays with only 2 elements at the beginning. This is actually the way of passing parameters in the ffmpeg project. There are two main ways to pass an array into the function.

1. Pass the size of the array. Just how many elements there are.

2. Pass the end of the array, as long as the end element (-1) is read, it is over.

Most functions of ffmpeg use the second method.


Then he will release  avfilter_graph_free() the filter container (FilterGraph), some students may wonder, is->agraph isn't it at first  NULL ? Why do you need to release?

is->agraph It is indeed NULL at the beginning, but  configure_audio_filters() this function may be called a second timeis->agraph , and  it will not be NULL the second time  .

configure_audio_filters() The first call is  stream_component_open() inside, as follows:

The second call is  audio_thread() inside, as follows:

The second call  configure_audio_filters() is because the sampling rate and channel of the actually decoded AVFrame are inconsistent with those recorded in the container. Before,  is->audio_filter_src the data was taken directly from the container and the encapsulation layer. The audio sampling rate recorded by the encapsulation layer may be wrong , and the actual decoded one shall  AVFrame prevail.

Moreover, note that the second time, force_output_format the parameter will be set to 1, which will force  buffersink the sampling information of the export filter to be  is->audio_tgt the same.

In fact, configure_audio_filters() it will definitely be adjusted a second time , because  is->auddec.pkt_serial != last_serial this condition must be true.


The next step is to set the number of threads used by the filter, 0 is to automatically select the number of threads, as follows:

is->agraph->nb_threads = filter_nbthreads;

The third point is to set the resampling options (aresample_swr_opts), as follows:

What kind of command line parameters are the resampling options  libswresample/options.c can be found in it, as follows:

For example, as follows:

ffpaly -ich 1 -i juren-5s.mp4

ich 1 It will be parsed and copied into  the variables ffplay.c inside  swr_opts .

A new function is also used here  av_opt_set(). In fact, this function can not only set the attribute fields of the filter , but also set the attribute fields of most data structures , such as decoders, wrappers, etc., as long as there AVClass are data structures. Used to av_opt_set() set properties, please read " AVOptions Detailed Explanation " for details


The next point is to set the entry and exit filters, as follows:

The export filter is also set  sample_fmts to  AV_SAMPLE_FMT_S16, which is  ffpaly the characteristic of the player itself, that is to say, no matter what the audio format in the MP4 file is, it will be converted into a  AV_SAMPLE_FMT_S16 format and thrown to SDL for playback, and when it uses   SDL_OpenAudioDevice to open the audio device , It is the S16 format, which is hard-coded .


force_output_format The logic is mainly to force  buffersink the sampling information of the export filter to be set to be the  is->audio_tgt same. audio_tgt is the final format in which SDL accepts audio frames.

The first time  configure_audio_filters() the function is called, force_output_format it is 0, and it will not run into this logic.


The last is to call  configure_filtergraph() the function to link the entry and exit filters , and create a filter container (FilterGraph), as follows:

The most important thing in the above figure is that the entry filter and exit filter are assigned to the global manager  is . Later, just throw the AVFrame output by the decoder to the entry filter, and then read it to the exit filter.


configure_filtergraph() The internal logic of the function is relatively simple. Please do your own research. If you are not familiar with the various functions of the filter, you can read "FFmpeg's scale filter introduction" and other filter articles.


Recommend a free open course of Zero Sound Academy. I personally think the teacher taught it well, so I would like to share it with you:

Linux, Nginx, ZeroMQ, MySQL, Redis, fastdfs, MongoDB, ZK, streaming media, CDN, P2P, K8S, Docker, TCP/IP, coroutines, DPDK and other technical content, learn now

Guess you like

Origin blog.csdn.net/u012117034/article/details/128394373