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: