- GStreamerã®çŽ¹ä»ïŒã¯ããã«
- GStreamerã®çŽ¹ä»ïŒããŒã¿ãœãŒã¹
- GStreamerã®çŽ¹ä»ïŒåºåããã€ã¹
- GStreamerïŒLinux颚ã®ã³ãŒããã¯
ç§ã¯æ¬åœã«ãã®äœ¿çšã§äœãããããã£ãã§ãã ããããéåžžèµ·ããããã«ãçŸåšã®ã¿ã¹ã¯ã¯ç©ºãæéãªãœãŒã¹ãå®å šã«äœ¿ãæãããŸããã
ãããŠããããžã§ã¯ãã«åãçµãéçšã§ãæœèšã§ãããªç£èŠã·ã¹ãã ãç·šæãããããäŒèšã·ã¹ãã ã«çµ±åããå¿ èŠããããŸããã ãã®ã¿ã¹ã¯ã¯ãåœç€Ÿã®å°é家ã«ãã£ãŠæåè£ã«è§£æ±ºãããäžè¬å€§è¡ã®æ³šç®ã«å€ãããã®ã§ã¯ãããŸããã ã¢ã«ãŠã³ãã£ã³ã°ã·ã¹ãã ã¯Microsoft .NETäžã§å®è¡ããããã¹ãŠã®ã«ã¡ã©ãH264 RTSPã¹ããªãŒã ãçºè¡ããŸãã ãããªããã£ããã£ããããã«ãStreamcodersã®åçšMediaSuiteã©ã€ãã©ãªã䜿çšãããŸãã
ããŒãã¹ãšããŠããããªããã£ããã£ããŠåŠçããããã«GStreamerã§äžé£ã®å®éšãè¡ãããšãèš±å¯ããŸããã
ãŸããè»äž¡ã®ééã枬å®ããããã®ã¯ããã察象ãšããã«ã¡ã©ã®1ã€ããã¹ããªãŒã ããã£ããã£ãããã¬ãŒã ããã³ããŒãã¬ãŒãèªèãµãã·ã¹ãã ã«è»¢éããŠãèªèçµæããããªã«é©çšããããšã«ããŸããã äžèšã®äŸã§ã¯ãLPRé¢æ°ãåŒã³åºããããã¬ãŒã ãã€ã³ã¿ãŒã»ãããããã®äžã«é·æ¹åœ¢ãæç»ããŸãã
ã ãããäžããããïŒ
- RTSP H264ãœãŒã¹
- Windows 7 32ãããã·ã¹ãã
- MS Visual Studio 2010
- C ++èšèª
- Gstreamer 1.0
ããªããååŸããå¿ èŠããããŸãïŒ
- åŠççµæãå«ââããããªã¹ããªãŒã
解決æ¹æ³ïŒ
- GStreamer 1.0ã®ãã©ã°ã€ã³éçº
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
ãã©ã°ã€ã³ãã³ãã¬ãŒããªããžããª
ç§ã®æ å ±æº