Benpianは、APIを介してフィルタグラフ機能を実現しようとしています。ソースを参照してくださいhttps://andy-zhangtao.github.io/ffmpeg-examples/
その上、オーバーレイ規模、トリム、setptsと:FFmpegのは、以下のような便利で強力なフィルターの多くを提供します。
-filter-complex
表現機能、複数のフィルタは、より複雑なビデオクリップのために、コールグラフに組み立てることができます。どのようにコードを通してこの機能を実現するには?
アプリケーションのFFmpegを開発する際にまず、前述のルーチンのいくつかによると、一般的に3つの軸を持っています:
- 初期入力装置(デコーダ及びアプリケーションコンテキストを初期化)
- 出力装置(エンコーダおよびそのアプリケーション・コンテキストの初期化)を初期化します
- (要件を満たすように、フレームデータに各種の演算処理を行う)フレーム処理ロジックを書きます
完了するために必要なフレーム処理する前に、わずかに異なる機能フィルターグラフを達成するための必要性Filter Graph
処理を。次のようにプロセスは以下のとおりです。
+------------------------------------------------+
| +---------+ |
| | Input | ----------read --------+ |
| +---------+ | |
| | |
| \|/ |
| +-----------+ |
| +-----------------------| Input | |
| | +-----------| |
| | | |
| | \|/ |
| | +-----------+ +-----------+ |
| +<--| Filter N |<-.N.--| Filter 1 | |
| | +-----------+ +-----------+ |
| | |
| | +-------------+ |
| +------>| Output | |
| +-------------+ |
+------------------------------------------------+
Input
後の映像データを読み込み、順番に通過Filter 1
してFilter N
、順番に各ウェルFilterパラメータ処理フレーム・データ・ストリームのすべてのフィルターが処理された設定に応じて、その後、エンコーダを通じて吸入をコードしていますOutput
。
プロセスからわかるように、ビデオの各フレームは、ビデオコーデックは、フィルタの適用において、いくつかの長い時間を感じる理由である、N回で処理されます。
APIの増加一部:
- avfilter_get_by_name
- avfilter_inout_alloc
- avfilter_graph_alloc
- avfilter_graph_create_filter
- avfilter_graph_parse_ptr
- av_buffersink_get_frame
- アクセスデバイスの初期化
そして、ここで説明するように、前のアクションは、あまりにも多くを行うことはありません。必要な場合は、以前の記事で見ることができます。ここだけのダンプ機能を高めます:
av_dump_format(inFormatContext, 0, "1", 0);
av_dump_format
FormatContextは、出力指定されたデータは、ポジショニングの問題を容易にすることがあります。
- 出力デバイスの初期化
また、必要に応じて、以前の記事を見たり、直接ソースコードを見て、あまりにも多くの説明をしません。time_baseのわずか数リマインダーをハングアップ。
time_base基準時間(すなわち、PTS)フレームを再生するにはどのくらいの速エンコーダを伝え変換を行うために使用されます。いくつかの従来time_baseコードが使用されます。
outCodecContext->time_base = (AVRational) {1, 25};
図1は、分子と分母が25です。符号化中に、エンコーダは、時点(すなわち、対応するPTS及びDTS)で表示し、レンダリングになるように各キーフレームを知る必要があります。ケースないBフレームでは、=のDTSをPTS。そして、PTS、time_baseの符号化および復号化time_baseとの対応関係を確立する必要性を計算します。
假设,time=5. 那么在1/25(编码time_base)的时间刻度下应该等于1/10000(编码time_base)时间刻度下的(5*1/25)/(1/90000) = 3600*5=18000
詳細なアプリケーションtime_base、参照setpts
実装。
- 初期化フィルタグラフ
でFilter Graph API
真ん中が二つの特別なフィルターは、次のとおりbuffer
とbuffersink
:
----------> |buffer| ---------|Filter ..... Filter N|----------->|buffersink|-------->
buffer
彼は、フィルタグラフを表現するために始めた、とbuffersink
フィルタグラフの終わりを示します。両方が不可欠であるフィルター内に存在しなければなりません。
次のようにフィルタグラフ手順は次のとおりです。
- 初期化
buffer
とbuffersink
。 - 他のフィルタの初期化
- 入力と出力のグラフセットをフィルタリングします。
- 初期化
buffer
とbuffersink
することでavfilter_get_by_name
、たとえば、フィルターに合致して下さい:
const AVFilter *buffersrc = avfilter_get_by_name("buffer");
バッファフィルターを取得します。そのような初期バッファとして、avfilter_graph_create_filterによって初期化フィルタ:
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
inCodecContext->width, inCodecContext->height, inCodecContext->pix_fmt,
time_base.num, time_base.den,
inCodecContext->sample_aspect_ratio.num, inCodecContext->sample_aspect_ratio.den);
av_log(NULL, AV_LOG_ERROR, "%s\n", args);
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
args, NULL, filter_graph);
「で」全体のグラフと呼ばれるバッファを表し、「で」。名前は簡単のような非繰り返しの限り唯一の保証、呼び出すことができます。
- 他のフィルタの初期化
: ``例えば、フィルタグラフの残りのフィルターを初期化するための構文を指定することで
const char *filter_descr = "movie=t.png[wm];[in][wm]overlay=10:20[out]";
avfilter_graph_parse_ptr(filter_graph, filter_descr,
&inputs, &outputs, NULL)
上記は、2つのフィルタの使用を表す:movie
およびoverlay
。inputs
そして、outputs
グラフの入力と出力を表します。
- 入力と出力のグラフセットをフィルタリング
このコードは、理解するのがやや困難です。
outputs->name = av_strdup("in");
outputs->filter_ctx = buffersrc_ctx;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = buffersink_ctx;
inputs->pad_idx = 0;
inputs->next = NULL;
出力対応するin
(すなわちバッファ)は、in
唯一の出力側は、(それが出力に相当する)ように、第1グラフフィルタです。同様にout
(buffersink)は最後のフィルタグラフであり、唯一の入力端子は、こうして入力に対応します。
+-------+ +---------------------+ +---------------+
|buffer | |Filter ..... Filter N| | buffersink |
----------> | |output|------>|input| |output|---> |input| |-------->
+-------+ +---------------------+ +---------------+
次の記事では、我々は他のAPIを介して各フィルタの入力および出力を設定します、その時は理解し少し楽にする必要があります。
フィルタグラフの初期化を完了した後、我々は合格しなければならないavfilter_graph_config
パラメータが正しいことを確認します。
avfilter_graph_config(filter_graph, NULL)
- ロジック処理
フレームデータを処理し、前にするとの考えは同じままでした。その後に送られ、デコーダからのフレームを受信しFilter Graph
処理するためのフィルタ、および最終的にはエンコーダに送信する出力ファイルに書き込まれます。
唯一の違いは、一部は2つの機能を添加することであるav_buffersrc_add_frame_flags
とav_buffersink_get_frame
。av_buffersrc_add_frame_flags
データのフレームは、フィルタ・グラフに追加される表し、av_buffersink_get_frame
フィルタグラフから抽出されたデータのフレームを表しています。
whileループの増加に符号化プロセスので:
while av_read_frame
|
+---> avcodec_send_packet
|
+----> while avcodec_receive_frame
| 对每一数据帧进行解码
| 通过`sws_scale`进行源帧和目标帧的数据转换
|
+---->av_buffersrc_add_frame_flags
|
|
+while av_buffersink_get_frame
|
|
+-->avcodec_send_frame
|
+---> while avcodec_receive_packet
|
|
|+--->av_interleaved_write_frame (写入到输出设备)
これはによってコードの実装を完了-filter-complex
機能。