この投稿では、Windowsでライブラリをコンパイルし、NDKを使用してEclipseでAndroid用のビデオおよびオーディオFFmpegを処理する方法について説明します。 FFmpegをOpenCV画像処理ライブラリにリンクする方法と、これらすべてをAndroidアプリケーションのJavaコードで使用する方法を学習します。 これらはすべて、Androidアプリケーションの作成プロセスのコンテキストで説明されます。Androidアプリケーションの主な機能は、これらのライブラリの使用とその相互作用に厳密に関連付けられています。 だから、私は猫の下で興味がある人に尋ねます。
免責事項
説明されたもののいくつかはおそらく多くの人にとって明らかであると思われますが、私にとって、Windows開発者として、これらのタスクは新しく、解決策は明白ではなかったので、技術的な詳細の説明を、経験があまりない人にとってできるだけシンプルで理解しやすいものにしようとしましたAndroid NDKおよびそれに関連するすべてのものと連携します。 一部のソリューションは直観的に発見されたため、ほとんどの場合、「美しい」ものではありません。
背景
FFmpegとOpenCVが使用されたAndroidアプリケーションのアイデアは、Vitutasミネラルウォーターに関する1つのコマーシャルを見た後に現れました(Youtubeで検索できます)。 このビデオでは、人間の目によって回転し、唇を動かし、視聴者にこの水を購入するように説得したさまざまな動物の写真を時々フラッシュしました。 かなり面白かった。 一般的には、コンピューターからではなく自分の電話を使用して、そのようなビデオを自分で作成する機会をユーザーに与えるとどうなるでしょうか。
もちろん、最初はアナログを探しました。 iPhoneのAppStoreで似たようなものが見つかりましたが、クリップの作成プロセスはあまり成功していませんでした。写真を選択し、その領域にマークを付けてから、その領域で何かを撮影します。別の場所の写真に少なくとも2つの目を置くと、口がまったく動きませんでした。 Google Playにはそのようなものはありませんでした。 同様の機能を持つ最も近いプログラムは、限られたセットのアニメーション要素を写真に押し付けることができるプログラムでした。
一言で言えば、競合他社はほとんどないので、アプリケーションを実行することが決定されました。
技術の選択
すぐに論理的な疑問が生じました。「これをすべて行う方法は?」 ビデオと画像を処理するためのあらゆる種類のライブラリの研究に2日間を費やした後、FFmpegとOpenCVに立ち寄りました。
利点のうち、次のものをリストできます。
- 両方のライブラリはC / C ++で記述されています。つまり、それらを結合することはすでに理論的には可能です。
- 無料のオープンソース:FFmpegはLGPLでビルドでき、OpenCVは一般にBSDライセンスで配布されます。
- 非常に高速で、実際にどの方向から見てもクールです。
マイナスのうち:
- C / C ++で書かれた;
- それでも、FFmpegはコードをすばやく理解し、何を変更する必要があるかを理解するために複雑です。
使用パターンは次のとおりでした:OpenCVは、ビデオシリーズの各フレームを形成し(たとえば、画像、目、口にそれを配置します)、このフレームを何らかの形でFFmpegに転送します。
Androidの開発経験がほとんどなく、Windowsの開発経験も少なかったため、EclipseとNDKをいじくり始める前に、Visual Studioで小さなプログラムを作成し、FFmpegとOpenCVを使用するというアイデアが正しいことを証明したことを認めなければなりません人生、そして最も重要なのは、彼らの相互作用を実現する方法があるということです。 しかし、これらのライブラリの相互作用の実装は少し後で記述されます。これは、すぐに何かを理解するよりも、時間をかけて理解しているテクノロジーのアイデアをテストする方が良いというトピックに関する簡単な推奨事項です。新しいもの。
Visual StudioでのFFmpegのコンパイルに関しては、驚くほど簡単でしたが、この記事はまだAndroidについて書かれているため、Visual StudioのFFmpegトピックが興味深い場合は、それについて書き、時間を見つけてこれを行う方法を説明しようと思いますする。
そこで、FFmpegとOpenCVを組み合わせるというアイデアが機能することを確認した後、Androidアプリケーションの直接開発を開始しました。
計画はこれでした:
- FFmpegとOpenCV for Androidをコンパイルしてビルドします。
- それらの相互作用のためのコードを書きます。
- すべてをアプリケーションのJavaコードで使用します。
Android StudioではなくEclipseでそれをすべて行うことにしました-どういうわけか私は湿気があり、開発の最初にあまり便利ではなかったようです。
FFmpeg、Android、NDK、Eclipse、Windows
最初のことは、すべての普通の人と同様に、WindowsでAndroid向けのFFmpegをクロスコンパイルする方法についての指示をインターネットで検索し始めました。 いくつかのメイクファイルのセットでさえ提供されている記事があり、githubに何かがありますが、私はそれらのためにこれを行うことができませんでした。 おそらく、これらすべてに関する経験の不足、おそらくこれらの指示とメイクファイルのエラーが原因です。 通常、このような指示は説明された技術に精通している人によって書かれているため、いくつかの「明らかな」ニュアンスを省略しており、初心者がこれを使用することは不可能であることがわかります。
一般に、私はすべてをゼロから自分でやらなければなりませんでした。 以下は、アクションのシーケンス例です。
0.プリセット
ダウンロードとインストール:Eclipse with CDT、Android SDK、NDK、cygwin、およびOpenCV Android SDK。 x86でAndroidをサポートする必要がある場合は、yasmもダウンロードする必要があります。* .asmファイルをクロスコンパイルするために必要ですが、それについては後で詳しく説明します。
これをすべてインストールおよび構成する手順は、実際にダウンロードするサイトで見つけることができます。また、EclipseでNDKをインストールおよび構成する方法については、opencv.org Webサイトにすばらしい記事があります。彼女に。
1.プロジェクトを準備する
Eclipseで新しいAndroidアプリケーションプロジェクトを作成し、それをC / C ++プロジェクトに変換します(記事「OpenCV Introduction to Android Development」を参照)。 実際、AndroidプロジェクトはC / C ++に完全には変換されませんが、C / C ++で動作する機能は単純に追加されます。
ffmpeg.orgからFFmpegコードを含むアーカイブをダウンロードして解凍します。 「ffmpeg-2.6.1」という形式のコードを持つフォルダーをプロジェクトの「jni」フォルダーにスローします(存在しない場合は、「res」、「scr」などと同じ場所に作成します)。
次に、構成ファイル(最も重要なものは「config.h」)とFFmpeg用のメイクファイルを作成する必要があります。 ここで最初のニュアンスが生じます。Androidデバイスには、Arm、x86、MIPSの3つのプラットフォームがあります。 これらの各アーキテクチャについて、独自の* .soライブラリファイル(Windowsの* .dllに類似)を収集する必要があります。 NDKではこれを行うことができます。各プラットフォーム用のコンパイラとリンカーが含まれています。
FFmpegで構成ファイルを生成するために、cygwinをインストールする必要がある特別なスクリプトがあります。 そのため、Cygwin Terminalのコマンドラインを実行し、次のコマンドセットを入力します。
bashスクリプトの説明ARMデバイスの場合:
$ cd D: $ cd MyProject/jni/ffmpeg-2.1.3/ $ PREBUILT=D:/ndk/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64 $ PLATFORM=D:/ndk/android-ndk-r9c/platforms/android-8/arch-arm $ TMPDIR=D:/ $ ./configure --enable-version3 --enable-shared --disable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network --enable-cross-compile --target-os=linux --arch=arm --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- --cc=$PREBUILT/bin/arm-linux-androideabi-gcc --ld=$PREBUILT/bin/arm-linux-androideabi-ld --tempprefix=D:/
x86デバイスの場合:
$ cd D: $ cd MyProject/jni/ffmpeg-2.1.3/ $ PREBUILT=D:/ndk/android-ndk-r9c/toolchains/x86-4.6/prebuilt/windows-x86_64 $ PLATFORM=D:/ndk/android-ndk-r9c/platforms/android-9/arch-x86 $ TMPDIR=D:/ $ ./configure --enable-version3 --enable-shared --disable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network --enable-cross-compile --target-os=linux --arch=x86 --cross-prefix=$PREBUILT/bin/i686-linux-android- --cc=$PREBUILT/bin/i686-linux-android-gcc --ld=$PREBUILT/bin/i686-linux-android-ld --tempprefix=D:/
MIPSデバイスの場合:
$ cd D: $ cd MyProject/jni/ffmpeg-2.1.3/ $ PREBUILT=D:/ndk/android-ndk-r9c/toolchains/mipsel-linux-android-4.6/prebuilt/windows-x86_64 $ PLATFORM=D:/ndk/android-ndk-r9c/platforms/android-9/arch-mips $ TMPDIR=D:/ $ ./configure --enable-version3 --enable-shared --disable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network --enable-cross-compile --target-os=linux --arch=mips --cross-prefix=$PREBUILT/bin/mipsel-linux-android- --cc=$PREBUILT/bin/mipsel-linux-android-gcc --ld=$PREBUILT/bin/mipsel-linux-android-ld --tempprefix=D:/
説明:
- 最初の2つのコマンド-「configure」ファイルがあるFFmpegコードのあるフォルダーに移動します。これは、コンパイル中に使用される「config.h」など、必要なファイルを生成するbashスクリプトです。
- 次に、3つの一時的な環境変数PREBUILT、PLATFORM、TMPDIRを作成します。最初の2つには、異なるプラットフォームのクロスコンパイル用のユーティリティが配置されているNDKのフォルダーへのパスが書き込まれます。これらのフォルダーに移動すると、フォルダー「フォルダー2番目のbin」は、コンパイラとリンカーです。 TMPDIR-操作中にスクリプトが一時ファイルを保存する一時フォルダーへのパス。
- 最後のコマンドは、実際にはパラメーターを使用して「ffmpeg-2.6.1」フォルダーから「configure」スクリプトを起動しています。 説明付きのすべての可能なスクリプトパラメータのリストは、コマンド「./configure -h」によって表示されます。 以下は、使用するパラメーターの説明です。
- パラメーター--enable-version3-このような構成ファイルを生成するようにスクリプトに指示し、LGPL 3.0でライセンスされるFFmpegライブラリのコンパイルに使用できるようにします。
- パラメーター--enable-sharedおよび--disable-static-出力で* .soファイルを取得することをスクリプトに伝えます。 これを実行すると、理論上はLGPLのあるコンパートメントで、LGPLが適用されないコードにリンクすることができます。
- パラメーター--disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network-これらのパラメーターを使用して、コンソールプログラム(言い換えると、ffmpeg.exe、ffplay.exe)を作成する必要がないことをスクリプトに伝えますその他);
- 残りのパラメーターは名前で理解できます-クロスコンパイル、プラットフォーム(linux arm、mipsまたはx86)の割り当て、コンパイラーとリンカーへのパスのスクリプトへの書き込み、一時フォルダーへのパスの設定を行います。
スクリプトは、ファイル「config.h」、「config.asm」、および「jni / ffmpeg-2.1.3」フォルダー内のいくつかのメイクファイルを生成します。
2.メイクファイル、コンパイル、アセンブリ
そのため、この段階ではすでにEclipseのAndroidアプリケーションプロジェクトのフォルダー「jni / ffmpeg-2.1.3」にFFmpegのコードがあり、必要な「config.h」ファイルを生成しました。 ここで、メイクファイルを作成して、これらすべてをコンパイルし、Androidアプリケーションで使用できる* .soファイルを取得する必要があります。
スクリプトで生成されたメイクファイルをコンパイルに使用しようとしましたが、成功しませんでした。おそらく手の曲がりが原因です。 そこで、コメントとインクルードを使用して、独自のメイクファイルを作成することにしました。
NDKを使用してコンパイルするには、少なくとも2つのmakefileが必要です。Android.mkとApplication.mkは、プロジェクトのjniフォルダーに配置する必要があります。 Application.mkには通常、12個以下のパラメーターが含まれており、いわば「グローバル」コンパイルパラメーターが構成されています。 Android.mkは、他のすべてを担当します。
コンパイル時のいくつかのエラーに関連する多くのポイントもあります。 これらは、Googleの助けを借りて、またはコンソールでNDKから提供された情報に基づいて修正することで解決されました(エラーは明確に定式化されており、修正は難しくないはずです)。 残念ながら、ここにすべてを持ち込むことはできません(単に修正するのを忘れていました)が、ここにいくつかのリストがあります。
- コンパイラーはシンボル「av_restrict」を誓います。フォルダー「ffmpeg-2.1.3」のファイル「config.h」を開き、行「#define av_restrict restrict」を「#define av_restrict __restrict」に置き換える必要があります。
- 一部のマシンでは、コンパイラは「getenv()」を誓います。これは、ファイル「ndk \ android-ndk-r9c \ platform \ android-9 \ arch-arm \ usr」の行「extern char * getenv(const char *)」にコメントすることで解決されます\ include \ stdlib.h "。 パスに注意してください。ターゲットアーキテクチャに依存するフォルダーがあります。Arm用にコンパイルする場合は「arch-arm」、MIPS用には「arch-mips」、x86用には「arch-x86」です。
- 競合を回避するには、ffmpeg.cのmain()関数の名前をffmpeg_main()に変更することをお勧めします。 AndroidアプリケーションのJavaコードから呼び出します。
コンパイル中であっても、FFmpegファイルの1つのコードに直接いくつかのエラーがありました。 私はこの場所についてコメントしました(もちろん、何かが壊れないことを多少なりとも確認しています)。 たとえば、コンソールに何かが表示される場所。 残念なことに、私は覚えていませんが、実際には、コンパイルエラーは簡単に修正されます。
説明付きのファイルとバットスクリプトを作成します。ニュアンス:
- libavcodec、libavfilterなどのFFmpegライブラリモジュール自体に加えて、ffmpeg.exeプログラム自体のコードをffmpeg.soライブラリとしてコンパイルする必要もあります。 Javaコードからそのmain()関数(ffmpeg_main()に名前を変更した)を呼び出し、必要なパラメーターを渡すと、必要な作業が行われます。
- NDKはx86アーキテクチャ用の* .asmファイルをコンパイルする方法を知らないため、「jni \ ffmpeg-2.1.3 \ libavcodec \ x86」、「jni \ ffmpeg- 2.1.3 \ libavfilter \ x86 "など。 以下は、これを行う* .batファイルです。 出力では、* .aオブジェクトファイル、x86でコンパイルするときにリンカーに示すパスを取得します。 これは、このアーキテクチャをサポートする場合にのみ行う必要があります。
- ほとんどすべてのモジュールのメイクファイルには、「libavfilter_ignore.mk」という形式の別のメイクファイルが含まれています。 これらには、コンパイルする必要のない各モジュールの* .cファイルが含まれています。 これらのファイルの種類は次のとおりです。コンテンツから理解できるように、その一部はテストプログラムのようなものです(たとえば、mpegaudio_tablegen.cなど)。 それらのいくつかはコンパイル用ではなく、インクルードを介して単純に接続されます(たとえば、h264qpel_template.cはh264qpel.cファイルで接続されます)。 確かに、confgiureスクリプトが機能した後に生成されたメイクファイル(これには何もありませんでした)では、それらもすべて無視されます。
- OpenCVモジュールのアセンブリファイルもメイクファイルに含まれています。 ここではすべてが簡単です。「OpenCV Introduction to Android Development」というopencv.orgの記事を読んでください。 これは、前述のFFmpeg-OpenCV相互作用にのみ必要です。 この相互作用について以下に説明します。
- 最初からすべてのFFmpegモジュールが1時間半の間私に届きます。 特にFFmpegモジュールで何かを変更する必要がある場合は特に、開発中に作業することはまったく不可能です。 これを回避するために、別のメイクファイルを以下に示します。 FFmpegの1つのモジュールのみが最初からコンパイルされ、残りは既にコンパイルされた状態で使用されます。 たとえば、libavfilterモジュールで作業し、そこに何かをプログラムし、絶えず変更します。libavcodecなどを絶えず再ビルドする必要はありません。既にコンパイルされたものを取り、正しい方法でmakefileに示します。
- makefileには説明的なコメントがありますが、いくつかのモジュールがそこでコンパイルされており、コンパイル手順が似ているため、makefileの重複コマンドは説明されていません。
Android.mk-NDKは、コンパイルのためにコードファイルのリストを取得します
LIBAVUTIL_LIB_ARCH_ASM_FILES))$(ソート$(LIBAVUTIL_LIB_ARCH_C_FILES))$(ソート$(LIBAVUTIL_LIB_ARCH_S_FILES))$(ソート$(LIBAVUTIL_LIB_ASM_FILES))$(ソート$(LIBAVUTIL_LIB_C_FILES))$(ソート$(LIBAVUTIL_LIB_S_FILES)
LIBAVCODEC_LIB_ARCH_ASM_FILES))$(ソート$(LIBAVCODEC_LIB_ARCH_C_FILES))$(ソート$(LIBAVCODEC_LIB_ARCH_S_FILES))$(ソート$(LIBAVCODEC_LIB_ASM_FILES))$(ソート$(LIBAVCODEC_LIB_C_FILES))$(ソート$(LIBAVCODEC_LIB_S_FILES)
LIBAVFORMAT_LIB_ARCH_ASM_FILES))$(ソート$(LIBAVFORMAT_LIB_ARCH_C_FILES))$(ソート$(LIBAVFORMAT_LIB_ARCH_S_FILES))$(ソート$(LIBAVFORMAT_LIB_ASM_FILES))$(ソート$(LIBAVFORMAT_LIB_C_FILES))$(ソート$(LIBAVFORMAT_LIB_S_FILES)
LIBSWSCALE_LIB_ARCH_ASM_FILES))$(ソート$(LIBSWSCALE_LIB_ARCH_C_FILES))$(ソート$(LIBSWSCALE_LIB_ARCH_S_FILES))$(ソート$(LIBSWSCALE_LIB_ASM_FILES))$(ソート$(LIBSWSCALE_LIB_C_FILES))$(ソート$(LIBSWSCALE_LIB_S_FILES)
libavfilter_ignore.mk - , yasm_compile_asm_libavfilter.bat - bat-, *.asm x86 REM *.asm libavfilter, 'libavfilter\x86' REM "-f elf" , "error: binary object format does not support external references" REM -D config.h "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o af_volume.o af_volume.asm "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o vf_gradfun.o vf_gradfun.asm "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o vf_hqdn3d.o vf_hqdn3d.asm "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o vf_pullup.o vf_pullup.asm "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o vf_yadif.o vf_yadif.asm "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o yadif-10.o yadif-10.asm "D:\yasm\yasm-1.3.0-win64.exe" -f elf -D ARCH_X86_64=0 -D HAVE_ALIGNED_STACK=1 -D ARCH_X86_32=1 -D HAVE_CPUNOP=1 -D HAVE_AVX_EXTERNAL=1 -ID:\MyProject\jni\ffmpeg-2.1.3 -o yadif-16.o yadif-16.asm "D:\ndk\android-ndk-r9c\toolchains\x86-4.6\prebuilt\windows-x86_64\bin\i686-linux-android-ar.exe" rvs libavfilter_asm.a af_volume.o vf_gradfun.o vf_hqdn3d.o vf_pullup.o vf_yadif.o yadif-10.o yadif-16.o mkdir "D:\MyProject\obj\local\x86\objs\avfilter\ffmpeg-2.1.3\libavfilter\x86" move libavfilter_asm.a "D:\MyProject\obj\local\x86\objs\avfilter\ffmpeg-2.1.3\libavfilter\x86\" del *.o
Android.mk - make-, avfilter, *.so - make- «jni». :

. Project Build, , ( ) «libs» *.so ( libopencv_java.so — OpenCV.mk libffmpeg.so – ffmpeg.exe, *.so ):

*.so , .
4. FFmpeg Android
*.so , Android . , . , FFmpeg ( «OpenCV Introduction into Android Development»).
, , FFmpeg : jni, Android.mk Application.mk, C++ *.so . Java-.
, Activity, , .
«jni» myproject.cpp :
myproject.cpp #include <jni.h> #include <string.h> #include <algorithm> #include <android/log.h> // NDK , , Eclipse , FFmpeg extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/opt.h" #include "libswscale/swscale.h" #include "libavfilter/avfilter.h" #include "libavutil/log.h" #include "libavutil/imgutils.h" } // Extermal Functions Declaration extern "C" { // , main() ffmpeg.c ffmpeg_main() int ffmpeg_main(int argc, char **argv); } // JNI Functions Declarations extern "C" { JNIEXPORT void JNICALL Java_com_example_myproject_MyActivity_nativeFFmpegTest(JNIEnv * _jenv, jclass _this); } JNIEXPORT void JNICALL Java_com_example_myproject_MyActivity_nativeFFmpegTest(JNIEnv * _jenv, jclass _this) { int argc = 5; // , - // FFmpeg , mp4 char* argv[5] = { "ffmpeg", "-i", "//storage//extSdCard//DCIM//Camera//video.mp4", "-an", "//storage//extSdCard//DCIM//Camera//video_no_audio.mp4"}; // , ffmpeg.exe : // > ffmpeg.exe -i "storage/extSdCard/DCIM/Camera/video.mp4" -an "storage/extSdCard/DCIM/Camera/video_no_audio.mp4" // -an ffmpeg , video_no_audio.mp4 ffmpeg_main(argc, argv); }
Android.mk Application.mk:
Application.mk APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi
, «storage/extSdCard/DCIM/Camera/video.mp4», myproject.cpp.
! , , , , video.mp4 video_no_audio.mp4 . , FFmpeg Android !
5. FFmpeg OpenCV
, FFmpeg , Java Android , - FFmpeg OpenCV.
, FFmpeg . , , . , , OpenCV. .
そして突然、私にはそれがわかりました-FFmpegにはビデオフィルターがあります!フィルターは、デコードコーディングの段階で接続されるモジュールであり、ビデオストリームの各フレームは、処理のためにフィルターに渡されます。ここで、ビデオストリームのフレームごとの処理を挿入できます。最初は、変換とOpenCV関数呼び出しを使用して独自のフィルターを作成したかったのです。ビデオのすべてのフレームを処理できます。しかし、その後、既製のフィルターを使用してコードを変更することにしました。, «ffmpeg-2.1.3\libavfilter\vf_scale.c», — - , . , 300x300, , , 640x480. — . , , .
, . ffmpeg_process() , , 640x480 300x300. , 640x480 , , 300x300. , . OpenCV FFmpeg.
この方法で解決されます:vf_scale.cファイルを開くと、filter_frame()関数があります。この関数は、各フレームのビデオ処理中に呼び出されるまさにコールバックです。AVFrame *型の「in」引数があります-これはビデオからデコードされたフレームです。このフレームをOpenCV互換形式に変換して処理する必要があります。! vf_scale _out , , ( ):

, , , — FFmpeg OpenCV .
おわりに
FFmpeg . , , - , . FFmpeg - — , .
!