Although by declaring [x][y]avfilter=a=x:b=y;avfilter=xxx
create a usable way Filter
call chain, and in most cases this way is reliable and practical. But if you want to 精细化
manage AVFilter
the call chain, such as dynamically generated based on certain conditions AVFilter Graph
. This declarative approach is less flexible (can also be dynamically assembled to determine if the string through, if you really like this string declaratively, not far suggest you read on the).
First quick brush up on how to create a AVFilter Graph
.
+-------+ +---------------------+ +---------------+
|buffer | |Filter ..... Filter N| | buffersink |
----------> | |output|------>|input| |output|---> |input| |-------->
+-------+ +---------------------+ +---------------+
Creating Trilogy:
- Initialization
buffer
andbuffersink
. - Other filter initialization
- Filter Graph set of Input and Output.
Wherein buffer
and buffersink
represent the Graph
start and end.
Then quickly package args
is movie=t.png[wm];[in][wm]overlay=10:20[out]
such a filter-complex commands. And by avfilter_graph_parse_ptr
completing the initialization of the intermediate filter,
Finally, specify the input and each filter output, even get a graph.
Well, let's look how the API 精细化
generation AVFilter Graph
. Generates the following Graph:
+-------+ +---------------------+ +---------------+
|buffer | | Filter | | buffersink |
----------> | |output|------>|input| Fade |output|---> |input| |-------->
+-------+ +---------------------+ +---------------+
First, initialize each AVFilter. All initialization AVFilter are two steps can be simplified as:
- Through
avfilter_get_by_name
to find the specified AVFilter - By
avfilter_graph_create_filter
initializing AVFilterContext
The same AVcodec
and AVCodecContext
the same relationship, perform all rely AVFilter the corresponding AVFilterContext (ffmpeg in development, Each component corresponds to a context manager, context manager of the various parameters and invoke the component package execution).
By avfilter_get_by_name
After generating AVFilter instance, followed by need to call avfilter_graph_create_filter
initialize context manager.
According to the following procedure, the initialization sequence three AVFilter:
buffer_src = avfilter_get_by_name("buffer");
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffer_src, "in", args, NULL, filter_graph);
The focus here talk about avfilter_graph_create_filter
. Here is the function prototype:
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
const char *name, const char *args, void *opaque,
AVFilterGraph *graph_ctx);
filt_ctx indicates that the AVFilter context manager.
AVFilter name is indicated in the Graph name in this Jiaosha name is not important but must be unique. For example Fade AVFilter
it can be called fade1
, fade2
or ifade
the like.
args is the argument of this AVFilter, pay attention to this parameter is only AVFilter, not the entire graph parameters. Let's use Fade
an example, args will be t=in:st=3:d=3
.
generally opaque to NULL on it.
After completion of the initial three AVFilter, entered into the focus of this document: avfilter_link
.
int avfilter_link( AVFilterContext * src,
unsigned srcpad,
AVFilterContext * dst,
unsigned dstpad
)
avfilter_link
They were used to link two AVFilter (Satisfy legendary). src
And dst
represent the source and destination Filter Filter. srcpad
It represents src
N-th output terminal, dstpad
showing dst
the N-th input terminal. If not well understood, direct look at the following chart:
+-------------+ +-------------+
| src srcpad 1 -----> dstpad 3 dst |
| srcpad 2 -----> dstpad 2 |
| srcpad 3 -----> dstpad 1 |
+-------------+ +-------------+
The figure assumptions src
and dst
respectively have three outputs and three inputs (not all avfilter have so many inputs and outputs, just like a fade, but there are multiple overlay).
And srcpad
and dstpad
represented is the output / input number. If the buffer
first output terminal corresponding to fade
the first input terminal. Then it would look like this:
avfilter_link(buffersrc_ctx, 0, ifade_ctx, 0);
Then fade
the first output terminal corresponding to buffersink
the input, so write:
avfilter_link(ifade_ctx, 0, buffersink_ctx, 0);
The so-called 精细化
is here embodied by the code determination logic may be a combination of different dynamic AVFilter
different build Filter Graph
. And it may also be a combination of different input / output terminal.
The reference code sample ifilter
. Also refer FFmpeg-Go-Server (attempt to provide a restful API for ffmpeg web server).