Gstreamerの基本的な説明

Gstreamerの説明

ベース

バックグラウンド

歴史的な観点から見ると、Linux はマルチメディアの点で他のオペレーティング システムに大きく遅れをとっています。Microsoft の Windows と Apple の MacOS は、既にマルチメディア デバイス、マルチメディアの作成、再生、およびリアルタイム処理を非常によくサポートしています。一方で、マルチメディア アプリケーションに対する Linux の包括的な貢献は比較的小さく、そのため、Linux がプロフェッショナル レベルのソフトウェアで MS Windows や MacOS と競合することも難しくなっています。GStreamer は、Linux マルチメディアの現在の問題を解決するように設計されています

GStreamer は、非常に強力で用途の広いストリーミングアプリケーションフレームワークです。GStreamer はオーディオとビデオの処理に限定されず、あらゆるタイプのデータ ストリームを処理できます。主な利点は、プラグ可能なコンポーネントを任意のパイプラインに簡単に接続できることです。この利点により、GStreamer を使用して、ユニバーサルな編集可能なオーディオおよびビデオ アプリケーションを作成できます。

GStreamerフレームワークはプラグインに基づいていますすべてのプラグインは、定義されたデータ パイプラインにリンクできます。

公式サイト:https://gstreamer.freedesktop.org/

まとめ

Gstreamer の利点
1. 明確な構造と強力な
GStreamer は一連の明確なインターフェイスを提供し、メディア パイプラインを構築するアプリケーション プログラマーとプラグイン プログラマーの両方がこれらの API を便利に使用できます。
2.オブジェクト指向プログラミングのアイデア
GStreamer は、シグナルとオブジェクト属性のメカニズムを使用して、GLib 2.0 オブジェクト モデルに関連付けられています。
3. 柔軟で拡張可能なパフォーマンス
すべての GStreamer オブジェクトは、GObject 継承によって拡張できます.
すべてのプラグインは動的にロードでき、独立して拡張またはアップグレードできます.
4. コア ライブラリとプラグインの分離 (コア/プラグイン)
すべてのメディア処理機能は、外部からプラグインによってカーネルに提供され、特定のメディア タイプの処理方法をカーネルに伝えます。

画像-20220114212052396

エレメント

Element(エレメント)はGStreamerで最も重要な概念です。

一連のコンポーネントを作成し、それらを接続して、接続されたコンポーネント間でデータ フローを送信することができます。

複数のコンポーネントを接続してパイプライン (パイプライン) を作成し、メディアの再生や録音などの特定のタスクを完了することができます。

プログラマーにとって、GStreamer で最も重要な概念の 1 つは GstElement オブジェクトです。要素は、メディア パイプラインを構築するための基本的なブロックです。各要素は GstElement に対応します。デコーダ エンコーダ、スプリッタ、ビデオ/オーディオ出力コンポーネントは、実際には GstElement オブジェクトです。

下図はパイプラインの例で、ファイル→音声と映像のデコード→再生の機能を別々に実現しています

画像-20220114215215203

ソース要素

ソース コンポーネントは、ディスクやサウンド カードからのデータの読み取りなど、パイプライン用のデータを生成します。下の画像は視覚化されたソース コンポーネントです。常に **ソース パッド** をコンポーネントの右端に描画します。

画像-20220114220749263

source 要素はデータを受信せず、データを生成するだけです。ソース パッドが 1 つしかないため (右端)、上の画像から確認できます。

フィルター/フィルターのような要素

フィルターとフィルターのような要素の両方に、入力パッドと出力パッドの両方があります。入力パッドから取得したデータを処理し、そのデータを出力パッドに送ります。ボリューム エレメント (フィルター)、ビデオ コンバーター (コンバーター)、Ogg スプリッター、または Vorbis デコーダーはすべて、このタイプのエレメントです。

クラス フィルター要素には、任意の数のソース パッドまたはシンク パッドを含めることができます。デコーダのように、ソース パッドとシンク パッドは 1 つだけです。一方、ビデオ デマルチプレクサには、メタデータ ストリームごとに 1 つのシンク パッドと複数のソース パッドがあります。

画像-20220114224254934

受信要素 (シンク要素)

受信要素は、データを受信するがデータを生成しないメディア パイプラインの終端です。ディスクへの書き込み、サウンド カードを使用したサウンドの再生、およびビデオ出力はすべて、受信コンポーネントによって実装されます。下の図は、受信要素を示しています。

画像-20220114225023291

コンポーネントを相互にリンクする

ソース要素、0 個以上のフィルターのような要素、およびシンク要素をリンクすることで、メディア パイプラインを構築できます。これらの要素間でデータが流れます。これは、GStreamer でのメディア処理の基本概念です。

画像-20220114225536564

パッド

パッドは GStreamer で複数の要素をリンクするために使用され、データがそのようなリンクを通過できるようにします。パッドは、コンポーネントのソケットまたはポートと見なすことができるコンポーネントの外部インターフェイスであり、コンポーネント間のリンクはパッドに依存します。データは、ある要素のソース パッドから別の要素のシンク パッドに流れます。パッド機能 (機能) は、コンポーネントが処理できるメディアのタイプを決定します。

ライナーには、特別なデータを処理する機能があります。ライナーは、通過するデータ フローのタイプを制限できます。リンクが成功する条件は、2 つのパッドで許可されているデータ型が同じ場合にのみリンクが確立されることです。これを交渉といいます

パッド情報は gst-inspect-1.0 で表示できます

Pad Templates:
  SINK template: 'sink'                    ------>sink pad:数据流入
    Availability: Always                   ------>pad时效性:永久型
    Capabilities:                          ------>pad支持的caps
      video/quicktime
      video/mj2
      audio/x-m4a
      application/x-3gp

  SRC template: 'video_%u'                 ------>src pad:数据流出
    Availability: Sometimes                ------>pad时效性:随机型
    Capabilities:
      ANY

  SRC template: 'audio_%u'
    Availability: Sometimes
    Capabilities:
      ANY

  SRC template: 'subtitle_%u'
    Availability: Sometimes
    Capabilities:
      ANY

上記からわかるように、各パッドには次の属性があります: パッド名、方向、プレゼンス、キャップ。

  • padname: パッド名

  • 方向: パッドの入出力方向。src と sink の 2 種類があります。

  • プレゼンス: パッドの適時性. パーマネント GST_PAD_ALWAYS, ランダム GST_PAD_SOMETIMES, リクエスト GST_PAD_REQUEST. リクエスト タイプは呼び出されるだけで、ランダム タイプはgst_element_request_pad()異なる入力データに応じて異なるパッドを使用します. 3 種類の適時性の意味はその名の通り、永続的なパッドは常に存在し、ランダムなパッドは特定の条件下でのみ存在し (ランダムに消えるパッドもランダムです)、リクエスト パッドはアプリケーションによって明示的に要求された場合にのみ発生します。

  • caps: パッドがサポートする機能

参照:
https://blog.csdn.net/houxiaoni01/article/details/98509594

Gstreamerのオブジェクト指向

Gstreamer は C 言語を使用して、主に glib ライブラリの GObject ライブラリのデータ型に基づいて、オブジェクト指向の実装をシミュレートします. GObject は、C 言語でオブジェクト指向プログラムを作成するのに役立つプログラム ライブラリです.

多くの人は、オブジェクト指向プログラムを作成するには、C++、Java、C# などのオブジェクト指向プログラミング言語を学ぶ必要があり、C 言語は構造化プログラムを作成するために使用されるという概念を植え付けられています。実際、オブジェクト指向は単なるプログラミングのアイデアであり、プログラミング言語ではありません。つまり、オブジェクト指向はゲームのルールであり、ゲームではありません。GObject は、C 言語でプログラムを作成する場合、オブジェクト指向プログラミングのアイデアを使用できることを示しています。

GObject の世界では、クラスは2 つの構造の組み合わせであり、1 つはインスタンス構造で、もう 1 つはクラス構造です。たとえば、MyObject はインスタンス構造であり、MyObjectClass はクラス構造であり、合わせて MyObjectクラスと呼ぶことができます。

#include <glib-object.h>

//实例结构体
typedef struct _MyObject{
    
    
        GObject parent_instance;
} MyObject;
//类结构体
typedef struct _MyObjectClass {
    
    
        GObjectClass parent_class;
} MyObjectClass;

//让GObjectx系统知道你定义了这个类
G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT);

GObject でのオブジェクトの生成は、次の原則に従います。

クラスの最初のインスタンスが生成される場合、最初に Class 構造体が割り当てられ、次にインスタンスの構造体が割り当てられます。それ以外の場合は、インスタンスの構造を直接割り当てます。つまり、クラス構造内のすべてのコンテンツは、クラスによって生成されたインスタンスによって共有されます。各オブジェクトがインスタンス化されると、専用のインスタンス構造がそれに割り当てられます。

MyObjectクラスインスタンス構造の最初のメンバーはGObject 構造であり、MyObjectクラスクラス構造の最初のメンバーはGObjectClass 構造であることに気付くかもしれません。実際には、GObject 構造体と GObjectClass 構造体は、それぞれGObject クラスインスタンス構造体とクラス構造体であり、それぞれがMyObjectクラスインスタンス構造体クラス構造体最初のメンバーである場合、MyObjectクラスのことを意味します。 GObject クラスを継承しています

各クラスは、クラス構造とインスタンス構造の 2 つの構造として定義する必要があります。すべてのクラス構造の最初のメンバーは GTypeClass 構造でなければならず、すべてのインスタンス構造の最初のメンバーは GTypeInstance 構造でなければなりません。

Gstreamer マルチスレッド

GStreamer はマルチスレッドをサポートするフレームワークであり、完全にスレッドセーフです。

Gstreamerのマルチスレッド化はコンポーネントキューによって実装され、キューの前後の2つの部分が2つのスレッドに分割されて実行されます。

画像-20220119215443674

ユーティリティ

gst-inspect はプラグインの情報を表示するために使用され、gstreamer1.0 バージョンでは gst-inspect-1.0 です。

gst-launch はパイプラインを開始するために使用され、gstreamer1.0 バージョンでは gst-launch-1.0 です。

gst-launch は主にパイプラインを一時的に有効化またはデバッグするために使用されます. パイプラインがファイナライズされている場合は、gstreamer が提供する C 関数を使用してパイプラインを形成する必要があります.

独自のプラグインが gstreamer によって正常に検出されるようにするために、gstreamer は GST_PLUGIN_PATH 環境変数を追加してプラグインの検索パスを増やすことをサポートしています。

gst-launch が開始する前に、まず、使用する必要がある各プラグインに対応する so ライブラリをスキャンします. 対応するライブラリがスキャンされても、正常にロードできない場合、プラグインはブラックリストに追加されます.ブラックリストを確認する必要があります。gst-inspect-1.0 -b が必要です。

破損したプラグインは、最初のスキャン時にブラックリストに追加する理由を報告し、その後のスキャンでは理由を報告しません. ブラックリストに追加する理由を確認する必要がある場合は、対応するキャッシュを削除し、再度実行してください。

rm ~/.cache/gstreamer-1.0/registry.x86_64.bin
gst-inspect-1.0 -b

Gstreamer デバッグ レベル。環境変数 GST_PLUGIN を設定して gstreamer ランタイムのデバッグ レベルを設定すると、さまざまなレベルでさまざまなレベルの情報が出力されます。

[0 , 5 ]の合計 6 段階
あります
GST_ERROR () GST_WARNING () GST_INFO () GST_DEBUG () 情報の出力 5: GST_ERROR () GST_WARNING () GST_INFO () GST_DEBUG () GST_LOG () 情報の出力



Gstreamer共通プラグイン紹介

Gstreamer には、パイプラインを構築するために一般的に使用されるプラグインがいくつかあります。

v4l2src(Linux 2 ソースのビデオ)

Video for Linux 2 は、アプリケーションがオーディオおよびビデオ ドライバーにアクセスするためのカーネルによって提供される統合インターフェイスであり、v4l2src はプラグイン video4linux2 に属する gstreamer に提供されるプラグイン要素であり、ダイナミック リンク ライブラリ ファイル名はlibgstvideo4linux2.so.

画像-20220118223403315

v4l2src 属性で、一般的に使用されるものは次のとおりです。

device: /dev/video0 などの Linux デバイス ファイルを指定するために使用されます。

num-buffers: デバイスから読み取るフレーム数を指定するために使用されます。

v4l2src は caps タイプを外部から指定できます。

gst-inspect-1.0 v4l2src で検出可能

画像-20220118224209893

v4l2src インスタンス:

gst-launch-1.0 v4l2src devce=/dev/video0 num-buffers=60 ! video/x-raw、幅=1280、高さ=720 ! フェイクシンク

その中で、fakesink は、デバッグ中にパイプラインを終了するために使用されるユニバーサルな終了要素です。

公式文書:

https://gstreamer.freedesktop.org/documentation/video4linux2/v4l2src.html?gi-language=c

内容は gst-inspect-1.0 v4l2src を直接実行するのと同様です

filesrc

filesrc は gstreamer のコア プラグインの 1 つで、ファイル システムからファイルを読み取るために使用されます。

共通のプロパティ:

場所: ファイルの場所

num-buffers: デバイスから読み取るフレーム数を指定するために使用されます。

ファイルシンク

ビデオストリームをファイルに保存するために使用

共通のプロパティ:

場所: ファイルの場所

qtdemux(QuickTime デマルチプレクサ)

ファイル内のオーディオとビデオを分離するために使用されます. 通常、このコンポーネントはファイルを読み取った後に接続する必要がありますが、一部のビデオ ファイルでは必要ありません. これはファイル自体に関連しています.

例:gst-launch-1.0 filesrc location=flower_groundtruth.mp4 ! qtdemux ! h264パース!omxh264dec ! omxh264enc !filesink location=output.mp4

機能: ファイルの読み取り -> ビデオの抽出 -> h264 ビデオ ストリームの解析 -> h264 デコード -> h264 エンコード -> ファイルの書き込み

videotestrc

gstreamer に付属するテスト ビデオ ソース

共通のプロパティ:

pattern: テスト映像表示パターン

画像-20220119150355022

例: gst-launch-1.0 videotestsrc pattern=2 ! ximagesink

ximagesink がウィンドウ表示を参照する場所

fakesrc と fakesink

gstreamer に付属するユニバーサル src とシンク

ビデオクロップ

ビデオをトリミングし、v4l2src のようにキャップを外部から指定します

共通のプロパティ:

画像-20220119151006293

ビデオスケール

ビデオサイズを変更し、v4l2src のように外部でキャップを指定します

共通のプロパティ:

メソッド: 補間法

n-threads: スレッド数

ビデオ変換

2 つのプラグインのフォーマットが一致しない場合に通常使用されるビデオ フォーマットを、2 つのプラグインのフォーマットを調整する中間プラグインとして変更し、v4l2src のように外部でキャップを指定します。

kmssink

ビデオを HDMI 出力に送信するために使用されます。

共通のプロパティ:

sync: 同期, True の場合, 処理速度が遅すぎる場合, 一部のフレームを破棄して最新のフレームを処理する戦略を使用します. False の場合, フレームは破棄されず, 内部にバッファがあります未完成のフレームを保存します。

bus-id: HDMI 出力に対応するデバイスを記入します。たとえば、a0007000.v_mix の場合、dmesg で特定の情報を確認する必要があります。

画像-20220119154355851

jpegdec

jpeg デコード。USB カメラを使用する場合、入力は JPEG 画像であり、正常に処理するにはデコードする必要があります。

その他の便利なプラグインについては、gstreamer の公式ドキュメントを参照してください。

gstreamer プロジェクト レコード

カスタム ハードウェアを gstreamer フレームワークに統合する場合は、gstreamer プラグインを作成する必要があります。

Gstreamerのx86環境とaarch64クロスコンパイル環境の構築について

x86 Ubuntu環境の場合

apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

aarch64 クロスコンパイル環境の場合

まず、gcc に加えて他の必要なツールを含むクロスコンパイラ ツールチェーンに従います。

sudo apt-get install gcc-aarch64-linux-gnu

画像-20220116184832612

	其次,准备好必要的依赖库。库依赖关系:

画像-20220115164854318

gst-plugins-base と gstreamer core のクロスコンパイル環境を用意したい場合は、依存関係に応じて前述のコンパイル環境を用意する必要があります。

: クロスコンパイル環境のバージョンは、開発ボードの gstreamer バージョンと一致している必要があります. これは、ヘッダー ファイルと接続された依存ライブラリが一致していることを確認するためです. 特に、1.12 より前のバージョンと 1.14 より後のバージョンの gstreamer はユニバーサルに使用できず、2 つのバージョンのプラグインはユニバーサルに使用できません。

  • orc 0.4.27 サポート ライブラリをインストールする

    gtk-doc-tools と libgtk2.0-doc のインストール後に gtkdoc-mktmpl: command not found が表示される場合は、./autogen.sh --prefix=/usr を次のコマンドに変更します。

./configure --prefix=/home/rongyitong/aarch64 --host=aarch64-linux-gnu
make 
sudo make install
  • zlib 1.2.11 クロスコンパイル
export CC=arm-linux-gnu-gcc   #它的configure不支持用CC变量来指定交叉工具链
./configure --prefix=/home/rongyitong/aarch64  #最后生成的库、头文件和man文件都在该目录下
make && make install
  • libffi 3.4.2 クロスコンパイル

    export CC=aarch64-linux-gnu-gcc
    ./configure --prefix=/home/rongyitong/aarch64 --host=aarch64-linux-gnu
    make && sudo make install
    

  • glib 2.45.3 glib のルート ディレクトリに新しい glib.cache をクロスコンパイルし、そこに書き込みます。

glib_cv_long_long_format=ll
glib_cv_stack_grows=no
glib_cv_have_strlcpy=no
glib_cv_have_qsort_r=yes
glib_cv_va_val_copy=yes
glib_cv_uscore=no
glib_cv_rtldglobal_broken=no
ac_cv_func_posix_getpwuid_r=yes
ac_cv_func_posix_getgrgid_r=yes
./autogen.sh --prefix=/home/rongyitong/aarch64 --host=aarch64-linux-gnu CC=aarch64-linux-gnu-gcc  LIBFFI_CFLAGS="-I/home/rongyitong/aarch64/lib/libffi-3.0.13/include" LIBFFI_LIBS="-L/home/rongyitong/aarch64/lib -lffi" -cache-file=glib.cache  --disable-selinux  --disable-xattr --disable-libelf ZLIB_CFLAGS="-I/home/rongyitong/aarch64/include" ZLIB_LIBS="-lz -L/home/rongyitong/aarch64/lib"

遭遇した場合

画像-20220103153940015

これはコンパイラのバージョンの問題です。glib/gdate.c の前に #pragma GCC diagnostic ignore "-Wformat-nonliteral" を追加してください

  • gstreamer 1.12 クロスコンパイル (開発ボードがバージョン 1.12 であるため、一貫性が必要です)

    Note that the environment variable PKG_CONFIG_PATH is added before, which is used in ./configure to use pkg-config to detect whether glib exists. x86 バージョンの glib が干渉する場合は、一時的に /usr/local/lib の名前を変更できます

 ./configure --prefix=/home/rongyitong/aarch64 --host=aarch64-linux-gnu GLIB_LIBS=`-lglib-2.0 -L/home/rongyitong/aarch64/lib` GLIB_CFLAGS=`-I /home/rongyitong/aarch64/include/glib-2.0 -I /home/rongyitong/aarch64/lib/glib-2.0/include` GIO_LIBS=`-lgio-2.0 -lgobject-2.0 -lglib-2.0 -L/home/rongyitong/aarch64/lib` GIO_CFLAGS=`-pthread -I/home/rongyitong/aarch64/include/glib-2.0 -I/home/rongyitong/aarch64/lib/glib-2.0/include` LIBS=`-lzlib -L=/home/rongyitong/aarch64/lib`
  • gst-plugin-base ライブラリをコンパイルする
./configure --prefix=/home/rongyitong/aarch64 --host=aarch64-linux-gnu --disable-ogg --disable-vorbis

pkg-config パスはここで構成されています。構成されていない場合は、gstreamer などの環境変数を構成する必要があります

ダイナミック リンク ライブラリ(共有オブジェクト ライブラリ)に関する補足知識

gstreamer プラグイン ライブラリはダイナミック リンク ライブラリの形式になっているため、ダイナミック リンク ライブラリの知識を理解しておく必要があります。

ソフトウェア ライブラリは一般にスタティック リンク ライブラリダイナミック リンク ライブラリに分けられ、スタティック リンク ライブラリの拡張子は .a (Linux) または .lib (Windows) であり、ダイナミック リンク ライブラリの拡張子は .so (Linux) です。または .dll (Windows) 。

動的リンクの基本的な考え方は、すべてのプログラム モジュールを 1 つの実行可能ファイルにリンクするのではなく、プログラムをモジュールに従って比較的独立した部分に分割し、それらをリンクして、プログラムの実行時に完全なプログラムを形成することです。

Linux のダイナミック リンク ライブラリは通常 libxxx.so の形式ですが、必要なダイナミック ライブラリを gcc でリンクするには、-lxxx と省略します。

スタティック リンク ライブラリは、リンク プロセス中にターゲット プログラムにマージされます。ダイナミック リンク ライブラリは、ターゲット プログラムの実行中にターゲット プログラムがこの関数を必要とする場合にのみ、対応する so ファイル内の関数を検索します。リンク ライブラリには、しばしば依存関係の問題があります。

ダイナミック リンク ライブラリには通常、次の 2 種類の依存関係の問題があります。

  1. 対応する .so ファイルが見つからないか、対応する .so ファイルの形式がターゲット プログラムと一致しません。このエラーは通常、リンク時に報告されます。

  2. 必要な関数が、対応する .so ファイルに見つかりません。このエラーは正常にリンクできますが、ターゲット プログラムの実行時にエラーが報告されます。
    エラーの種類は通常、未定義のシンボルのようなシンボル未定義の問題です: pthread_create

    動的リンク ライブラリと静的リンク ライブラリでは、関数と変数をまとめてシンボルと呼び、関数名または変数名をシンボル名と呼び、各ライブラリにはシンボル テーブル(シンボル テーブル)があります。

    ダイナミック リンク ライブラリのユーティリティ:

    リーデルフ

    一般的な使い方

    readelf -h libxxx.so

    オプション -h (elf ヘッダー) は、elf ファイルの先頭にあるファイル ヘッダー情報を表示します。

    画像-20220118141843116

    readelf -s libxxx.so

    オプション -s、シンボル テーブル セグメント内の項目を表示します (名前が完全に表示されない場合は、完全な表示を示すために -W パラメータを追加できます)。

    画像-20220118151931033

    画像-20220118152014689

    画像-20220118151427682

    Ndx はシンボルが配置されているセグメントを示し、UND は undefined を示し、シンボルがファイルで定義されていないこと、シンボルのみが参照されていること、およびシンボルが他のファイルで定義されていることを示します。

    ldd (動的依存関係のリスト) ツール

    は、実行可能ファイルが依存するライブラリまたはその他のライブラリを表示するために使用されます。

    画像-20220118153659677

場合によっては ldd ツールを使用すると、プロンプトが表示されます

画像-20220118154609043

この状況は、ファイルのアーキテクチャと、コマンドが実行されるプラットフォームとの間の不一致が原因である可能性があります。たとえば、aarch64 プラットフォームは x86 プラットフォームで実行されます。解決策として、ldd ツールの aarch64 バージョンを使用して、それを aarch64 プラットフォームに移植することができます。

ldd ツールは基本的に単なるシェル スクリプトなので、コードを変更するだけです。

1. #!/bin/bash がプラットフォーム インタープリターと一致するように注意してください;
2. 変数 RTLDLIST 値を変更します。これを aarch64 プラットフォームのリンク ダイナミック ライブラリ (ld-linux-xx.so) に変更します。そのほとんどは /lib ディレクトリにあります。

画像-20220118154942345

テンプレートからプラグインを作成する

git clone https://gitlab.freedesktop.org/gstreamer/gst-template.git

gitディレクトリに入るには、ブランチをバージョン1.18に切り替える必要があります.マスターバージョンのテンプレートにはいくつかの問題があります. 名前をmake_elementツールで置き換えた後、

videocrop プラグインを例に、実際のプラグインに基づいてリファクタリングします

プラグインの継承

GObject
    ╰──GInitiallyUnowned
        ╰──GstObject
            ╰──GstElement
                ╰──GstBaseTransform
                    ╰──GstVideoFilter
                        ╰──videocrop

プラグインの再構築方法 gstvideofilter.c と gstbasetransform.c は、それぞれ libgstvideo.so と libgstreamer-1.0.so に統合されています。必要がなければ、2 つのソース コードを変更せず、対応する動的ライブラリを直接リンクするだけです。ソース コードを直接変更すると、2 つの c ファイルは一連のヘッダー ファイルとその他の依存ライブラリに依存し、その一部は gstreamer コア ライブラリをコンパイルするときに生成されます. ヘッダー ファイルの環境は非常に複雑であるため、この方法は使用できません。おすすめされた。

画像がメモリに保存される仕組み

ビデオ画像がメモリに保存されると、画像の各行の終わりに拡張コンテンツが含まれる場合があります. これらの拡張コンテンツは、画像がメモリに保存される方法にのみ影響しますが、画像の表示方法には影響しません。

ストライドはこれらの拡張機能の名前です. ストライドはピッチとも呼ばれます. 画像内のピクセルの各行の最後に拡張機能がある場合, ストライドの値は画像の幅よりも大きくなければなりません, に示すように次の図
:ここに写真の説明を書きます

The two buffers contain video frames of the same size (width and height), but there are not the same Stride value. ビデオ フレームを処理する場合は、計算時にストライドを考慮する必要があります。

また、画像には2つの異なる格納順序(配列)があり、上から下に格納される(Top-Down)画像の場合、一番上の行のピクセルがメモリの先頭に格納されます。ボトムアップ (Bottom-Up) から格納される場合、最後の行のピクセルはメモリの最初の部分に格納されます。次の図は、2 つのケースを示しています。

ここに写真の説明を書きます

YUV 画像は常に上から下に表され、RGB 画像は通常、システム メモリに格納されるときに下から上に格納されます。

YUVに関する補足知識

YUV (YCrCb) は、輝度パラメーター Y とクロミナンス パラメーター U/V を分離するピクセル形式を指し、主にカラー ビデオ信号の伝送を最適化するために使用されます。

私たちの目の中にある網膜桿体細胞は網膜錐体細胞よりも多く、網膜桿体細胞は明るさを認識し、錐体細胞は色度を認識するため、私たちの目は色よりも明暗を区別します. つまり、私たちの目はより敏感です.彩度よりも明るさに。次に、画像情報を保存する場合、スペースを節約するために、すべての彩度情報を保存する必要はありません。

YUV ピクセル フォーマットは、RGB ピクセル フォーマットから派生したもので、式の計算により、YUV の 3 つのコンポーネントを RGB に復元できます。

YUV 保存形式

YUV 形式には、平面とパックの 2 つのカテゴリがあります。

  • 平面の YUV 形式の場合、すべてのピクセルの Y が連続して格納され、その後にすべてのピクセルの U が格納され、次にすべてのピクセルの V が格納されます。
  • パックされた YUV フォーマットの場合、各ピクセルの Y、U、および V が連続的にインターリーブされます。

YUV サンプリング形式

YUV ストリームの保存形式は、実際にはそのサンプリング方法と密接に関係しており、主流のサンプリング方法には、YUV4:4:4、YUV4:2:2、YUV4:2:0 の 3 つがあります。

3 つのグラフを使用して、取得方法を視覚的に表現します。ピクセルの Y 成分は黒い点で表され、ピクセルの UV 成分は白抜きの円で表されます。

ここに写真の説明を書きます

  • YUV 4:4:4 サンプリング、各 Y は一連の UV コンポーネントに対応します。
  • YUV 4:2:2 サンプリング、2 つの Y ごとに一連の UV コンポーネントを共有します。
  • YUV 4:2:0 サンプリング、4 つの Y ごとに UV コンポーネントのセットを共有します。

保管方法の例:

<1>YUV422 保存タイプ

<1-1>YUYV形式(サンプリング形式はYUV422、保存形式はpacked)

画像

YUYV は、YUV422 によってサンプリングされるストレージ形式の 1 つであり、隣接する 2 つの Y は、隣接する 2 つの Cb(U) と Cr(V) を共有します。ピクセル Y'00 と Y'01 の場合、Cb と Cr の値は両方とも Cb00 と Cr00 であり、他のピクセルの YUV 値は類推によって推定されます。

<1-2>UYVY形式(サンプリング形式はYUV422、保存形式はpacked)

画像

<1-3>YUV422P (サンプリング形式は YUV422、保存形式は平面)

画像

YUV422P は Plane モード、つまり平面モードで、上記の YUV データとインターリーブされず、最初にすべての Y 成分を保存し、次にすべての U (Cb) 成分を保存し、最後にすべての V (Cr) 成分を保存します。コンポーネント。各ピクセルの YUV 値の抽出方法も、YUV422 形式に続く最も基本的な抽出方法、つまり 2 つの Y が 1 つの UV を共有する方法です。たとえば、ピクセル ポイント Y'00 と Y'01 の場合、Cb と Cr の値は両方とも Cb00 と Cr00 です。

<2>YUV420収納タイプ

YUV 4:2:0 サンプリングに基づくフォーマットには、主に YUV 420P と YUV 420SP が含まれ、各タイプは他の特定のフォーマットに対応します。

  • YUV420Pタイプ
    • YU12形式
    • YV12形式
  • YUV420SPタイプ
    • NV12フォーマット

    • NV21フォーマット

YUV 420P と YUV 420SP はいずれもPlanar プレーナー フォーマットに基づいて保存されます. YUV420P タイプは最初にすべての Y コンポーネントを保存した後、最初にすべての U またはV

<2-1>YUV420sp (サンプリング形式は YUV420、格納形式は平面、Y-planner と UV-planar に分けられ、UV 平面がパックされます)

画像

画像

NV21 と NV12 はどちらも YUV420 形式に属します。これは 2 プレーン モードです。つまり、Y と UV は 2 つのプレーンに分割されますが、UV (CbCr) は 3 つのプレーンに分割される代わりにインターリーブされて格納されます。抽出方法は上記と同様で、Y'00、Y'01、Y'10、Y'11 は Cr00 と Cb00 を共有しています。

<2-2>YUV420p (サンプリング形式は YUV420、保存形式は平面、Y-planner、U-planar、V-planar に分割)

画像

画像

YU12 (別名 I420) と YV12 は YUV420 フォーマットに属し、これもプレーン モードです. Y、U、および V コンポーネントは別々にパッケージ化され、順番に格納されます。各ピクセルの YUV データ抽出は、YUV420 フォーマットの抽出方法に従います。つまり、4 つの Y コンポーネントが 1 セットの UV を共有します。上の図に示すように、Y'00、Y'01、Y'10、Y'11 は Cr00 と Cb00 を共有します。

YU12 と YV12 の違いは、U と V のどちらを先に格納するかです。YU12 の場合、格納順序は YUV、つまり YCbCr であり、YV12 の場合、格納順序は YVU、つまり YCrCb です。

おすすめ

転載: blog.csdn.net/qq_37117214/article/details/126781955