8

私は現在、.NETからlibavutil、libavformat、libavcodec(すべてFFMpegの一部)にアクセスしようとしています。

現在、 Windows32ビット用に毎晩実行される共有FFMpegパッケージの自動ビルドからライブラリを取得しています。

ffmpeg-sharpプロジェクトのコードも使用しています。そのプロジェクトでは、コンパイルされていなかったいくつかのクラスを削除しました(これらは、P / Invoke宣言ではなくラッパークラスです)。

コードは正常にコンパイルされますが、いくつかの問題が発生しています。

まず、av * .dllのビルドでは、cdecl呼び出し規約PInvokeStackImbalanceExceptionを使用しているようです。これは、を呼び出そうとしたときにいくつかの呼び出し規約を受け取っていたためav_open_input_fileです。これは、正しく機能させるために変更するのに十分簡単でした。AVFormatContext構造にデータが入力されます。

その後av_find_stream_info、ファイル内のストリームに関する情報を取得するために呼び出したいと思います。ただし、AVFormatContextへの呼び出しから取得したものを使用してそれを呼び出すと、保護されたメモリから読み取りまたは書き込みを行おうとしていることを示すav_open_input_fileanがスローされます。AccessViolationException

誰かがP/Invokeを使用して、P / Invokeを介してlibavutil、libavformat、およびlibavcodec dllライブラリにアクセスし、それを機能させましたか?

コマンドラインバージョンのFFMpegを使用することは、解決策ではありますが、この場合は実行可能な解決策ではありませんが、ライブラリを介してアクセスする必要があります。この理由は、必要なことを実行するにはディスクをあまりにも多くスラッシングする必要があり(非常に高解像度のビデオのフレームごとの分析を実行する必要があります)、ディスクを避けたいためです。できるだけ。

4

4 に答える 4

2

これは私が理解したことです-つまり、ffmpeg-sharpプロジェクトのP/Invoke宣言のかなりの量が正しくありません。マーシャリングされた宣言で構造を使用する場所はたくさんありますが、その後、割り当て解除ルーチンに渡す必要があります。

マーシャリングの一部としてポインターが失われたためAccessViolationException、有効なポインター(Windowsのハンドルなど)を受け入れる他のメソッドにその構造を渡そうとしたときに、がスローされていました。それらを不透明として扱う代わりに(Windows APIのように)、構造をマーシャリングして戻し、プロセスでポインターを失います。

解決策は、API宣言を変更して、構造を取得/返し、IntPtr必要に応じて構造のマーシャリングを実行することです。P/Invoke宣言にそれらを含めないでください。

于 2010-09-24T19:57:12.660 に答える
1

C#/。NETおよびMono用の自動生成されたFFmpegラッパーを参照してください。

于 2014-02-11T08:41:00.027 に答える
0

私はそれらのライブラリ/プロジェクトのいずれからも明確に舵を切りました。当時私が見つけたすべての情報は、新しいバージョンで簡単に壊れたり、古すぎたりしていることを示していました。

私がしたことは、この回答で述べたように、そこにリンクしているブログ投稿のサンプルを変更することによって、ffmpegプロセスを直接実行することでした。今日まで、問題は発生していません:)

上記があなたのシナリオでうまくいかない場合は、頑張ってください。

于 2010-09-24T19:11:14.017 に答える
0

SharpFFmpegはc++ライブラリをインポートします。C++コードはアンマネージコードです。アンマネージメモリへのポインタが必要です。「Marshal」クラスは、アンマネージメモリを割り当てるためのメソッドを提供します。例えば:

    IntPtr buffer = Marshal.AllocHGlobal(buf.Length + FFmpeg.FF_INPUT_BUFFER_PADDING_SIZE); //buf is a byte array

また、マネージ変数(任意のC#変数)を関数に送信する場合は、この変数をアンマネージメモリにマーシャリング(コピー)する必要があります。

    for (int i = 0; i < buf.Length; i++)
        Marshal.StructureToPtr(buf[i], buffer + i, true);

これで、関数へのポインターを送信できます。

    FFmpeg.avcodec_decode_video(codecContextUnmanaged, frame, ref success, buffer, buf.Length);

一部の管理されていない構造を変更する必要がある可能性があります。これを行うには、構造を管理対象メモリ(Marshal.PtrToStructureメソッド)にコピーしてから変更し、非管理対象メモリに再度コピーする必要があります。
私は同じ問題に何度も苦しめられました。私はそれを解決しましたが、とにかくビデオをデコードすることはできません))私の解決策が誰かに役立つことを願っています。

于 2011-08-30T10:54:11.163 に答える