初心者の学習のFFmpeg - APIを介して、完全なフィルタ、複雑な機能

Benpianは、APIを介してフィルタグラフ機能を実現しようとしています。ソースを参照してくださいhttps://andy-zhangtao.github.io/ffmpeg-examples/

その上、オーバーレイ規模、トリム、setptsと:FFmpegのは、以下のような便利で強力なフィルターの多くを提供します。

-filter-complex表現機能、複数のフィルタは、より複雑なビデオクリップのために、コールグラフに組み立てることができます。どのようにコードを通してこの機能を実現するには?

アプリケーションのFFmpegを開発する際にまず、前述のルーチンのいくつかによると、一般的に3つの軸を持っています:

  1. 初期入力装置(デコーダ及びアプリケーションコンテキストを初期化)
  2. 出力装置(エンコーダおよびそのアプリケーション・コンテキストの初期化)を初期化します
  3. (要件を満たすように、フレームデータに各種の演算処理を行う)フレーム処理ロジックを書きます

完了するために必要なフレーム処理する前に、わずかに異なる機能フィルターグラフを達成するための必要性Filter Graph処理を。次のようにプロセスは以下のとおりです。

+------------------------------------------------+
|   +---------+                                  |
|   | Input   | ----------read --------+         |
|   +---------+                        |         |
|                                      |         |
|                                     \|/        |
|                          +-----------+         |
|  +-----------------------|   Input   |         |
|  |                       +-----------|         |
|  |                                   |         |
|  |                                  \|/        |
|  |   +-----------+       +-----------+         |
|  +<--|  Filter N |<-.N.--| Filter 1  |         |
|  |   +-----------+       +-----------+         |
|  |                                             |
|  |       +-------------+                       |
|  +------>|     Output  |                       |
|          +-------------+                       |
+------------------------------------------------+

Input後の映像データを読み込み、順番に通過Filter 1してFilter N、順番に各ウェルFilterパラメータ処理フレーム・データ・ストリームのすべてのフィルターが処理された設定に応じて、その後、エンコーダを通じて吸入をコードしていますOutput

プロセスからわかるように、ビデオの各フレームは、ビデオコーデックは、フィルタの適用において、いくつかの長い時間を感じる理由である、N回で処理されます。

APIの増加一部:

  1. avfilter_get_by_name
  2. avfilter_inout_alloc
  3. avfilter_graph_alloc
  4. avfilter_graph_create_filter
  5. avfilter_graph_parse_ptr
  6. av_buffersink_get_frame
  • アクセスデバイスの初期化

そして、ここで説明するように、前のアクションは、あまりにも多くを行うことはありません。必要な場合は、以前の記事で見ることができます。ここだけのダンプ機能を高めます:

av_dump_format(inFormatContext, 0, "1", 0);

av_dump_formatFormatContextは、出力指定されたデータは、ポジショニングの問題を容易にすることがあります。

  • 出力デバイスの初期化

また、必要に応じて、以前の記事を見たり、直接ソースコードを見て、あまりにも多くの説明をしません。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真ん中が二つの特別なフィルターは、次のとおりbufferbuffersink

 ----------> |buffer| ---------|Filter ..... Filter N|----------->|buffersink|-------->

buffer彼は、フィルタグラフを表現するために始めた、とbuffersinkフィルタグラフの終わりを示します。両方が不可欠であるフィルター内に存在しなければなりません。

次のようにフィルタグラフ手順は次のとおりです。

  1. 初期化bufferbuffersink
  2. 他のフィルタの初期化
  3. 入力と出力のグラフセットをフィルタリングします。
  • 初期化bufferbuffersink

することで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およびoverlayinputsそして、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_flagsav_buffersink_get_frameav_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機能。

おすすめ

転載: www.cnblogs.com/vikings-blog/p/11512530.html