2

私はパイプラインを設計して、opencv アプリケーション (Web カメラから取得) からビデオ フレームをビデオ/x-h264 形式にエンコードし、ネットワーク経由で送信し、別のタイプのデバイス (おそらくラズベリー パイ) でデコードします。プロジェクトの適切な RGB ストリーム。

このために、ハードウェア アクセラレーション エンコーダーとデコーダーを使用することになっています。シナリオ全体が巨大であるため、現在の開発は gstreamer VAAPI プラグイン (vaapiencode_h264 & vaapidecode) を使用して Intel マシンで実行されています。また、TCPServer や UDPServer などのネットワーク プラグインを使用する必要がないという事実

このために、私は目的のために以下のパイプラインを使用しました: エンコーダ側:

appsrc name=applicationSource ! videoconvert ! video/x-raw, format=I420, width=640, height=480,framerate=30/1, pixel-aspect-ratio=1/1,interlace-mode=progressive ! vaapiencode_h264 bitrate=600 tune=high-compression ! h264parse config-interval=1 ! appsink name=applicationSink sync=false

Appsrc 部分は問題なく動作しますが、appsink 部分には問題があります。

このパイプラインのアプリシンク部分は、以下のキャップで設定されています。

"video/x-h264, format=(string){avc,avc3,byte-stream},alignment=(string){au,nal};video/mpeg, mpegversion=(int)2, profile=(string)simple "

私のappsinkのデータ抽出のコードは

    bool HWEncoder::grabData()
{

    // initial checks..

    if (!cameraPipeline)
    {

        GST_ERROR("ERROR AS TO NO PIPE FOUND ... Stopping FRAME GRAB HERE !! ");
        return false;
    }


    if (gst_app_sink_is_eos (GST_APP_SINK(applicationSink)))
    {

        GST_WARNING("APP SINK GAVE US AN EOS! BAILING OUT ");
        return false;
    }

    if (sample)
    {
        cout << "sample available ... unrefing it ! "<< endl;
        gst_sample_unref(sample);
    }


    sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));

    if (!sample)
    {
        GST_WARNING("No valid sample");
        return false; // no valid sample pulled !
    }

    sink_buffer = gst_sample_get_buffer(sample);

    if (!sink_buffer)
    {
        GST_ERROR("No Valid Buffer ");return false;
    }

    return true;
}

パイプラインを起動し、アプリシンクでバッファがいっぱいになっていることを確認した後、コードの以下の行で無期限にスタックします。

sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));

次の質問があります: 1) 私の Caps for appsink は正しいですか? そうでない場合、どうすればそれらの上限を決定できますか? 2) 上記のパイプラインに何か問題がありますか?

Appsink でこの問題を解決するにはどうすればよいですか??

どんな種類の助けも役に立ちます!

ありがとう !!

4

1 に答える 1

1

推測では(同様の問題がありました)appsinkとappsrcが同じパイプラインにあるという問題は、そのうちの1つを埋める/空にすると、もう1つがブロックされる可能性があります(詳細は以下)。

appsink と appsrc は、いっぱい/空のときにブロックされます。これは、通常の望ましい動作です。dropappsink または appsrc にはオプションがありますがblock、これらを使用すると単なる回避策になる可能性があり、ストリームに不具合が発生します。適切な解決策は、appsrc と appsink の間の同期をより適切に処理することです。

appsrc シグナルenough-dataに反応することができneed-dataます。これが私たちのやり方です。また、 appsrc: is-livedo-timestampおよびバッファ サイズのプロパティをいじりました (これは役立つ場合とそうでない場合があります)。

g_object_set(src->appsrc,
    "stream-type", GST_APP_STREAM_TYPE_STREAM,
    "format", GST_FORMAT_TIME,
    "do-timestamp", TRUE,
    "is-live", TRUE,
    "block", TRUE,
    NULL);

なぜ彼らはお互いをブロックするのですか?(私が推測する) メイン アプリケーション スレッドで appsink を処理し、同時に appsrc を処理するためです。appsink/appsrc の 1 つがスレッドをブロックすると、他のスレッドの処理を処理する人は誰もいません。したがって、appsink がデータを持たないためにブロックされると、appsrc に新しいデータを供給することができる人が誰もいないため、無限のデッドロックが発生します。

また、appsink *pull_sample メソッドの noblock バージョンも実装しましたが、これは単なる回避策であり、解決策よりも多くの問題が発生しました。

何が起こっているかをデバッグしたい場合は、appsrc/appsink に GST_DEBUG エントリを追加できます (それらが何であったかは覚えていません)。前述enough-dataneed-data信号にコールバックを追加するか、キューを追加して GST_DEBUG=queue_dataflow:5 を有効にして、どれを確認するかを確認できます。キューが最初にいっぱいになるなど。これは、「データデッドロック」をデバッグするときに常に役立ちます。

于 2015-11-27T08:22:05.870 に答える