MS Visual StudioでGStreamerのプラグむンを䜜成する

私は垞にリアルタむムのビデオ凊理アプリケヌションに興味がありたした。 Habréでは、マルチメディアフレヌムワヌクGStreamerに関する䞀連の蚘事を読みたした。



私は本圓にその䜿甚で䜕かをしたかったです。 しかし、通垞起こるように、珟圚のタスクは空き時間リ゜ヌスを完党に䜿い果たしたした。



そしお、プロゞェクトに取り組む過皋で、斜蚭でビデオ監芖システムを線成し、それを䌚蚈システムに統合する必芁がありたした。 このタスクは、圓瀟の専門家によっお成功裏に解決され、䞀般倧衆の泚目に倀するものではありたせん。 アカりンティングシステムはMicrosoft .NET䞊で実行され、すべおのカメラがH264 RTSPストリヌムを発行したす。 ビデオをキャプチャするために、Streamcodersの商甚MediaSuiteラむブラリが䜿甚されたす。



ボヌナスずしお、ビデオをキャプチャしお凊理するためにGStreamerで䞀連の実隓を行うこずを蚱可したした。

たず、車䞡の重量を枬定するためのはかりを察象ずしたカメラの1぀からストリヌムをキャプチャし、フレヌムをナンバヌプレヌト認識サブシステムに転送しお、認識結果をビデオに適甚するこずにしたした。 䞊蚘の䟋では、LPR関数を呌び出さず、フレヌムをむンタヌセプトし、その䞊に長方圢を描画したす。



だから、䞎えられた



あなたが取埗する必芁がありたす



解決方法



GStreamerは、開発者にクラス階局を提䟛したす 。 この目的のために、 GstElementクラスからプラグむンを継承できたす。 GstElementは、GStreamerスレッドの凊理に䜿甚できる芁玠を開発するために必芁な基本抜象クラスです。



GStreamerをむンストヌルする


GStreamer gstreamer-1.0-xxx-1.2.4.msiをダりンロヌドしおむンストヌルしたす。 ここで取るこずができたす 。

開発には、gstreamer-1.0-devel-xxx.msiディストリビュヌションgstreamer-1.0-devel-x86-1.2.4.msiなども必芁ですむンストヌル䞭に、必芁なオプションを遞択したす。







今埌は、 Windowsデバむスドラむバヌキット7.1.0をむンストヌルするこずをお勧めしたす。 デフォルトでは、C\ WinDDK \ 7600.16385.1に蚭定されおおり、プロゞェクトをビルドするずきにVisual Studioが怜玢する堎所です。 すでに別の方法でDDKをむンストヌルしおいる堎合は、プロゞェクト蚭定で盎接修正できたす。



GStreamerプロゞェクトのWebサむトには、他のドキュメントの䞭でも、プラグむン開発者向けのガむドがありたす 。 マニュアルを読んですべおのコヌドを自分で䜜成できたすが、 リポゞトリからプラグむンプロゞェクトテンプレヌトをダりンロヌドできたす 。



このテンプレヌトには、C ++゜ヌスファむルずプラグむンコヌドを生成するためのスクリプトが含たれおいたす。 マニュアルにあるように、リポゞトリからテンプレヌトをデプロむした埌、gst-template / gst-plugin / srcディレクトリに移動し、.. / tools / make_elementナヌティリティを実行する必芁がありたす。 make_elementナヌティリティには、プラグむンの名前ダミヌ、䜿甚する゜ヌスファむルの名前デフォルトではgstpluginの2぀のパラメヌタヌがありたす。



実行の結果、gstdummy.cずgstdummy.hの2぀のファむルを取埗したす。 内郚にはダミヌのプラグむンのスケルトンがありたすが、これはただ愚かで䜕もしたせんが、プラグむンフレヌムワヌクのシステムに既に組み蟌むこずができたす。



小さなコメント䞊蚘のすべおはLinux、Unixマシンに圓おはたりたすが、Windowsの哀れな所有者はどうですか Cmd.exeはmake_elementを実行したせん。 make_elementの内郚を芋るず、圌が耇雑なこずをしおいないこずが明らかになり、ストリヌム゚ディタヌの助けを借りお、sedは䞎えられたパラメヌタヌに基づいおタヌゲット゜ヌスを生成したす。 あなたは自分でそれを行うこずができたす。 念のため、テストプロゞェクトを開発䞭に配眮するリポゞトリgithub.com/nostrum-service/gstを䜜成したした 。



準備䜜業を行った埌、MS Visual Studio 2010でプロゞェクトを盎接䜜成するずきが来たした。幞いなこずに、GStreamer開発者はVisual Studioナヌザヌの面倒を芋お、プロゞェクトの䜜成に必芁なすべおを配垃キットに入れたした。 Visual Studioのディレクトリにファむルを正しく配眮する必芁がありたす。

必芁なものはすべおgstreamer \ 1.0 \ x86 \ share \ vs \ 2010ディレクトリにありたす。

私たちは実斜したす

xcopy c:\gstreamer\1.0\x86\share\vs\2010\gst-template\*.* "C:\Program Files\Microsoft Visual Studio 10.0\VC\VCWizards\gst-template\*.*" /s /e /c xcopy C:\gstreamer\1.0\x86\share\vs\2010\wizard\*.* "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcprojects\"
      
      





Visual Studioを起動たたは再起動しお新しい蚭定を確認しお、新しいプロゞェクトを䜜成し、むンストヌルされおいるテンプレヌトからVisual C ++ \ gst-dk-templateを遞択したす。







すべおがうたくいった堎合、必芁な蚭定を持぀空のプロゞェクトが䜜成されたす。 プラグむンを䜜成したいので、プロゞェクト蚭定に移動し、プロゞェクトの詳现構成タむプをアプリケヌション.exeからダむナミックラむブラリ.dllに倉曎したす。







[プロパティマネヌゞャヌ]りィンドりで、次の図を確認したす[プロパティマネヌゞャヌ]ビュヌ-> [その他のりィンドり]-> [プロパティマネヌゞャヌ]を有効にできたす。







䜜成された空のプロゞェクトには、make_elementナヌティリティを䜿甚しお以前に䜜成されたファむルを含める必芁がありたす。







コンパむルしお、すべおが正しい堎合、GStreamerプラグむンディレクトリにコピヌする必芁がある既補のDLLを取埗したすC\ gstreamer \ 1.0 \ x86 \ lib \ gstreamer-1.0 \がありたす。

念のため、gst-inspect-1.0 dummyを確認しおください。 ここで、GStreamerがプラグむンに぀いお孊んだこずを確認したす。







最小限のプラグむン機胜


プラグむンをチェヌンに埋め蟌むには、次のラむフサむクルを実装する必芁がありたす。



メタデヌタ


プラグむンに関するメタデヌタを提䟛するために、機胜がありたす

static void gst_dummy_class_initGstdummyClass * klass



この䟋では、ダミヌ芁玠にはブヌル型のSilentプロパティがあり、ストリヌムを凊理するずきにテキストを衚瀺したす。



  gobject_class->set_property = gst_dummy_set_property; gobject_class->get_property = gst_dummy_get_property; g_object_class_install_property (gobject_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, (GParamFlags)G_PARAM_READWRITE));
      
      





このコヌドを䜿甚しお、プラグむンにSilentプロパティがあり、ブヌル型であり、デリゲヌトgst_dummy_set_propertyがそのむンストヌルを担圓し、読み取りがgst_dummy_get_propertyであり、読み取りず曞き蟌みが可胜であり、デフォルト倀がFALSEであるこずをGStreamer環境に通知したす。 次に、接続ポむントをプラグむンに登録したす-パッド。



  gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&src_factory)); gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sink_factory));
      
      





入力パッドシンクを定矩したす。これは垞に䜿甚可胜です-GST_PAD_ALWAYSで、GST_STATIC_CAPS "ANY"の圢匏を受け入れたす。

 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY") );
      
      





出力パッドsrcを決定したす。これは垞に䜿甚可胜です-GST_PAD_ALWAYSで、GST_STATIC_CAPS "ANY"の圢匏を生成したす。

 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY") );
      
      





むンスタンスの初期化


パむプラむン構築プロセス䞭に、GStreamer環境はプラグむンむンスタンスの初期化関数を呌び出したす。

 static void gst_dummy_init (Gstdummy * filter)
      
      





入り口に、満たされる構造物が䟛絊されたす。

 struct _Gstdummy { GstElement element; GstPad *sinkpad, *srcpad; gboolean silent; };
      
      





プラグむンの入力で発生するむベントを凊理するには、適切なデリゲヌトを指定する必芁がありたす。

 gst_pad_set_event_function (filter->sinkpad, GST_DEBUG_FUNCPTR(gst_dummy_sink_event));
      
      





ストリヌム接続


プラグむン入力でむベントが発生するず、この堎合、関数が呌び出されたす

 static gboolean gst_dummy_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
      
      





ただ䜕もしおいたせん。



詊運転


実行しおみおください-gst-launch-1.0 videotestsrc ダミヌ autovideosink –v。 このコマンドは、videotestsrcによっお生成されたテストビデオストリヌムをプラグむンに転送し、プラグむンはautovideosinkビデオプレヌダヌを倉曎せずにさらに転送したす。 キヌvを䜿甚するず、チェヌン党䜓がどのように凊理されるかを確認できたす。







テスト画像が衚瀺された堎合、プラグむンが入力から出力にデヌタを正垞に転送したこずを意味したす。

この堎合、凊理の出力には以䞋が含たれたす。

 /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = video/x-raw, format=(string)I420, width=(int)320, height=(int)240, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
      
      





続いお、videotestsrc0ずいう名前のGstVideoTestSrcクラスのむンスタンスがpad srcを提䟛し、フレヌムサむズが320 x 240などのI420圢匏のビデオ/ x-rawストリヌムを発行したす。

プラグむンは任意の圢匏を受け入れるこずができるため、その入力はvideotestsrc0の出力に関連付けられおいたした。

 /GstPipeline:pipeline0/Gstdummy:dummy0.GstPad:sink: caps = video/x-raw, format=(string)I420, width=(int)320, height=(int)240, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
      
      





さらに飛び蟌む


メカニズムが機胜しおいるこずがわかったので、目暙に向けおいく぀かの手順を実行しおみたす。 ゜リュヌションの進化を説明するために、別のペむンタプラグむンをプロゞェクトに远加したした。このプラグむンは、画像䞊に長方圢を描画したす。

ラむブラリを䜿甚せずに長方圢を描画できたすが、OpenCVを䜿甚しお実隓を続けたいず思いたした。



新しいプラグむンを远加するずき、その登録の問題がありたす。 レゞストラはプロゞェクトごずに1぀必芁です。 この点で、䞡方のプラグむンの登録コヌドを含むGstTestLib.cppファむルが導入されたした。

 struct _elements_entry { const gchar *name; GType (*type) (void); }; static const struct _elements_entry _elements[] = { {"dummy", gst_dummy_get_type}, {"painter", gst_painter_get_type}, {NULL, 0}, }; static gboolean plugin_init (GstPlugin * plugin) { gint i = 0; while (_elements[i].name) { if (!gst_element_register (plugin, _elements[i].name, GST_RANK_NONE, (_elements[i].type) ())) return FALSE; i++; } return TRUE; }
      
      





ペむンタヌの堎合、入力ストリヌム圢匏に察しおより厳しい制限を䜜成したした。 これは次のようになりたす。

 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ( GST_VIDEO_CAPS_MAKE ("{ BGRx }") ) );
      
      





぀たり、任意の解像床ずフレヌムレヌトのBGRx圢匏のストリヌミングビデオを入力できたす。 OpenCVはデフォルトでBGRスキヌムを䜿甚したす。 ここで配色ず倉換に぀いお読むこずができたす 。

興味のあるカメラがRTSP H264ストリヌムを提䟛するため、それをデコヌドし、ビデオ倉換コンバヌタヌの入力に䟛絊する必芁がありたす。 テストケヌスは次のようになりたす。

 gst-launch-1.0 -v rtspsrc location=rtsp://10.10.0.15 ! rtph264depay ! avdec_h264 ! videoconvert ! painter ! videoconvert ! autovideosink
      
      





10.10.0.15-私の内郚アドレスは䟋ずしお取られたす。

これで、入力バッファはBGRx圢匏になりたす。 パむプラむンの構築方法がわからない堎合は、ナニバヌサルdecodebinコンテナヌを䜿甚できたす。 圌は適切なプラグむンを遞択しお接続しようずしたす

 gst-launch-1.0 -v rtspsrc location=rtsp://10.10.0.15 ! decodebin ! autovideosink
      
      





蚺断出力には–vスむッチが必芁です。そこで、パむプラむンがどのように圢成されるかがわかりたす。



プラグむンに戻りたす。 すべおの凊理は、入力画像に基づいお新しい画像を圢成し、その䞊に長方圢を描画するこずで構成されたす。 䜜業関数の圢匏は次のずおりです。

 static GstBuffer * gst_painter_process_data (Gstpainter * filter, GstBuffer * buf) { //          GstMapInfo srcmapinfo; gst_buffer_map (buf, &srcmapinfo, GST_MAP_READ); //    GstBuffer * outbuf = gst_buffer_new (); //      IplImage * dst = cvCreateImageHeader (cvSize (filter->width, filter->height), IPL_DEPTH_8U, 4); //      GstMemory * memory = gst_allocator_alloc (NULL, dst->imageSize, NULL); GstMapInfo dstmapinfo; if (gst_memory_map(memory, &dstmapinfo, GST_MAP_WRITE)) { //        memcpy (dstmapinfo.data, srcmapinfo.data, srcmapinfo.size); dst->imageData = (char*)dstmapinfo.data; //   cvRectangle (dst, cvPoint(10,10), cvPoint(100, 100), CV_RGB(0, 255, 0), 1, 0); //         gst_buffer_insert_memory (outbuf, -1, memory); gst_memory_unmap(memory, &dstmapinfo); } cvReleaseImageHeader(&dst); gst_buffer_unmap(buf, &srcmapinfo); return outbuf; }
      
      







シンクパッドむベントハンドラヌでは、入力ストリヌム情報を確認できたす。

 static gboolean gst_painter_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean ret; Gstpainter *filter; filter = GST_PAINTER (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps * caps; gst_event_parse_caps (event, &caps); //  GstStructure *structure = gst_caps_get_structure (caps, 0); //  gst_structure_get_int (structure, "width", &filter->width); gst_structure_get_int (structure, "height", &filter->height); filter->format = gst_structure_get_string (structure, "format"); ret = gst_pad_event_default (pad, parent, event); break; } default: ret = gst_pad_event_default (pad, parent, event); break; } return ret; }
      
      





問題は額で解決されたす。 実隓は成功したした。 GStreamerが開発されるず、新しい機䌚が開かれたす。この機䌚に進み、トピックに興味を持っおいる堎合は、さらに詳しく説明したす。



゜ヌス


Gstreamer

GStreamerオブゞェクト階局

GStreamerプラグむン開発ガむド

Opencv

プラグむンテンプレヌトリポゞトリ

私の情報源



All Articles