mirror of
https://bitbucket.org/ohhara/ohmulticastvideoscanner.git
synced 2025-06-08 16:36:26 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f445979318 | ||
|
9f477e32d2 | ||
|
ad95a4c05f | ||
|
20fcf95852 | ||
|
7181e74c46 | ||
|
ffc2d1c497 | ||
|
db12c70938 | ||
|
973f48702b | ||
|
da327ab47d | ||
|
15aa054470 | ||
|
32b602aad3 | ||
|
65477c5009 | ||
|
e672832cdf | ||
|
9a277b2aed | ||
|
6cfa826913 | ||
|
3c969575fd |
13
INSTALL.macos
Normal file
13
INSTALL.macos
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
1) Install Mac OS X El Capitan Version 10.11.6
|
||||||
|
|
||||||
|
2) Install Homebrew from http://brew.sh
|
||||||
|
|
||||||
|
3) Run as follows.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$ brew install gstreamer gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav
|
||||||
|
$ git clone https://bitbucket.org/ohhara/ohmulticastvideoscanner.git
|
||||||
|
$ cd ohmulticastvideoscanner
|
||||||
|
$ ./configure
|
||||||
|
$ make
|
||||||
|
$ sudo ./omvs 233.19.187.192/30 233.19.187.244 233.19.187.1
|
||||||
|
-------------------------------------------------------------------------------
|
@ -23,11 +23,12 @@ $ pacman -S VCS base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-gstreamer
|
|||||||
|
|
||||||
9) Start "MinGW-w64 Win64 Shell".
|
9) Start "MinGW-w64 Win64 Shell".
|
||||||
|
|
||||||
10) Run as follows. Set CFLAGS and LDFLAGS properly when you run ./configure.
|
10) Run as follows. Set CFLAGS and LDFLAGS properly to find WinPcap Developer's
|
||||||
|
Pack when you run ./configure.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
$ git clone https://bitbucket.org/ohhara/ohmulticastvideoscanner.git
|
$ git clone https://bitbucket.org/ohhara/ohmulticastvideoscanner.git
|
||||||
$ cd ohmultivideoscanner
|
$ cd ohmultivideoscanner
|
||||||
$ CFLAGS="-IWpdPack/Include" LDFLAGS="-LWpdPack/Lib/x64" ./configure
|
$ CFLAGS="-I../WpdPack/Include" LDFLAGS="-L../WpdPack/Lib/x64" ./configure
|
||||||
$ make
|
$ make
|
||||||
$ ./omvs 233.19.187.192/30 233.19.187.244 233.19.187.1
|
$ ./omvs 233.19.187.192/30 233.19.187.244 233.19.187.1
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
bin_PROGRAMS = omvs
|
bin_PROGRAMS = omvs
|
||||||
omvs_SOURCES = omvs_main.c omvs_gst.h omvs_gst.c
|
omvs_SOURCES = \
|
||||||
|
omvs_main.c \
|
||||||
|
omvs_gst.h \
|
||||||
|
omvs_gst.c \
|
||||||
|
omvs_gst_plugin.h \
|
||||||
|
omvs_gst_plugin.c \
|
||||||
|
omvs_gst_plugin_rtpsrc.h \
|
||||||
|
omvs_gst_plugin_rtpsrc.c
|
||||||
omvs_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GSTREAMER_CFLAGS)
|
omvs_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GSTREAMER_CFLAGS)
|
||||||
omvs_CFLAGS += -std=gnu99 -W -Wall -Wno-unused-result -pedantic
|
omvs_CFLAGS += -std=gnu99 -W -Wall -Wno-unused-result -pedantic
|
||||||
omvs_LDADD = $(GLIB_LIBS) $(GIO_LIBS) $(GSTREAMER_LIBS)
|
omvs_LDADD = $(GLIB_LIBS) $(GIO_LIBS) $(GSTREAMER_LIBS)
|
||||||
|
44
Makefile.in
44
Makefile.in
@ -100,7 +100,9 @@ CONFIG_CLEAN_FILES =
|
|||||||
CONFIG_CLEAN_VPATH_FILES =
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
PROGRAMS = $(bin_PROGRAMS)
|
PROGRAMS = $(bin_PROGRAMS)
|
||||||
am_omvs_OBJECTS = omvs-omvs_main.$(OBJEXT) omvs-omvs_gst.$(OBJEXT)
|
am_omvs_OBJECTS = omvs-omvs_main.$(OBJEXT) omvs-omvs_gst.$(OBJEXT) \
|
||||||
|
omvs-omvs_gst_plugin.$(OBJEXT) \
|
||||||
|
omvs-omvs_gst_plugin_rtpsrc.$(OBJEXT)
|
||||||
omvs_OBJECTS = $(am_omvs_OBJECTS)
|
omvs_OBJECTS = $(am_omvs_OBJECTS)
|
||||||
am__DEPENDENCIES_1 =
|
am__DEPENDENCIES_1 =
|
||||||
omvs_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
omvs_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||||
@ -316,7 +318,15 @@ target_alias = @target_alias@
|
|||||||
top_build_prefix = @top_build_prefix@
|
top_build_prefix = @top_build_prefix@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
omvs_SOURCES = omvs_main.c omvs_gst.h omvs_gst.c
|
omvs_SOURCES = \
|
||||||
|
omvs_main.c \
|
||||||
|
omvs_gst.h \
|
||||||
|
omvs_gst.c \
|
||||||
|
omvs_gst_plugin.h \
|
||||||
|
omvs_gst_plugin.c \
|
||||||
|
omvs_gst_plugin_rtpsrc.h \
|
||||||
|
omvs_gst_plugin_rtpsrc.c
|
||||||
|
|
||||||
omvs_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GSTREAMER_CFLAGS) \
|
omvs_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GSTREAMER_CFLAGS) \
|
||||||
-std=gnu99 -W -Wall -Wno-unused-result -pedantic
|
-std=gnu99 -W -Wall -Wno-unused-result -pedantic
|
||||||
omvs_LDADD = $(GLIB_LIBS) $(GIO_LIBS) $(GSTREAMER_LIBS)
|
omvs_LDADD = $(GLIB_LIBS) $(GIO_LIBS) $(GSTREAMER_LIBS)
|
||||||
@ -436,6 +446,8 @@ distclean-compile:
|
|||||||
-rm -f *.tab.c
|
-rm -f *.tab.c
|
||||||
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omvs-omvs_gst.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omvs-omvs_gst.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omvs-omvs_gst_plugin.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omvs-omvs_main.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omvs-omvs_main.Po@am__quote@
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
@ -487,6 +499,34 @@ omvs-omvs_gst.obj: omvs_gst.c
|
|||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -c -o omvs-omvs_gst.obj `if test -f 'omvs_gst.c'; then $(CYGPATH_W) 'omvs_gst.c'; else $(CYGPATH_W) '$(srcdir)/omvs_gst.c'; fi`
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -c -o omvs-omvs_gst.obj `if test -f 'omvs_gst.c'; then $(CYGPATH_W) 'omvs_gst.c'; else $(CYGPATH_W) '$(srcdir)/omvs_gst.c'; fi`
|
||||||
|
|
||||||
|
omvs-omvs_gst_plugin.o: omvs_gst_plugin.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -MT omvs-omvs_gst_plugin.o -MD -MP -MF $(DEPDIR)/omvs-omvs_gst_plugin.Tpo -c -o omvs-omvs_gst_plugin.o `test -f 'omvs_gst_plugin.c' || echo '$(srcdir)/'`omvs_gst_plugin.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omvs-omvs_gst_plugin.Tpo $(DEPDIR)/omvs-omvs_gst_plugin.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omvs_gst_plugin.c' object='omvs-omvs_gst_plugin.o' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -c -o omvs-omvs_gst_plugin.o `test -f 'omvs_gst_plugin.c' || echo '$(srcdir)/'`omvs_gst_plugin.c
|
||||||
|
|
||||||
|
omvs-omvs_gst_plugin.obj: omvs_gst_plugin.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -MT omvs-omvs_gst_plugin.obj -MD -MP -MF $(DEPDIR)/omvs-omvs_gst_plugin.Tpo -c -o omvs-omvs_gst_plugin.obj `if test -f 'omvs_gst_plugin.c'; then $(CYGPATH_W) 'omvs_gst_plugin.c'; else $(CYGPATH_W) '$(srcdir)/omvs_gst_plugin.c'; fi`
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omvs-omvs_gst_plugin.Tpo $(DEPDIR)/omvs-omvs_gst_plugin.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omvs_gst_plugin.c' object='omvs-omvs_gst_plugin.obj' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -c -o omvs-omvs_gst_plugin.obj `if test -f 'omvs_gst_plugin.c'; then $(CYGPATH_W) 'omvs_gst_plugin.c'; else $(CYGPATH_W) '$(srcdir)/omvs_gst_plugin.c'; fi`
|
||||||
|
|
||||||
|
omvs-omvs_gst_plugin_rtpsrc.o: omvs_gst_plugin_rtpsrc.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -MT omvs-omvs_gst_plugin_rtpsrc.o -MD -MP -MF $(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Tpo -c -o omvs-omvs_gst_plugin_rtpsrc.o `test -f 'omvs_gst_plugin_rtpsrc.c' || echo '$(srcdir)/'`omvs_gst_plugin_rtpsrc.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Tpo $(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omvs_gst_plugin_rtpsrc.c' object='omvs-omvs_gst_plugin_rtpsrc.o' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -c -o omvs-omvs_gst_plugin_rtpsrc.o `test -f 'omvs_gst_plugin_rtpsrc.c' || echo '$(srcdir)/'`omvs_gst_plugin_rtpsrc.c
|
||||||
|
|
||||||
|
omvs-omvs_gst_plugin_rtpsrc.obj: omvs_gst_plugin_rtpsrc.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -MT omvs-omvs_gst_plugin_rtpsrc.obj -MD -MP -MF $(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Tpo -c -o omvs-omvs_gst_plugin_rtpsrc.obj `if test -f 'omvs_gst_plugin_rtpsrc.c'; then $(CYGPATH_W) 'omvs_gst_plugin_rtpsrc.c'; else $(CYGPATH_W) '$(srcdir)/omvs_gst_plugin_rtpsrc.c'; fi`
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Tpo $(DEPDIR)/omvs-omvs_gst_plugin_rtpsrc.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omvs_gst_plugin_rtpsrc.c' object='omvs-omvs_gst_plugin_rtpsrc.obj' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omvs_CFLAGS) $(CFLAGS) -c -o omvs-omvs_gst_plugin_rtpsrc.obj `if test -f 'omvs_gst_plugin_rtpsrc.c'; then $(CYGPATH_W) 'omvs_gst_plugin_rtpsrc.c'; else $(CYGPATH_W) '$(srcdir)/omvs_gst_plugin_rtpsrc.c'; fi`
|
||||||
|
|
||||||
mostlyclean-libtool:
|
mostlyclean-libtool:
|
||||||
-rm -f *.lo
|
-rm -f *.lo
|
||||||
|
|
||||||
|
11
NEWS
11
NEWS
@ -1,3 +1,14 @@
|
|||||||
|
Oh! Multicast Video Scanner 0.4 2016-07-27
|
||||||
|
===============================================================================
|
||||||
|
* Support udp protocol.
|
||||||
|
* Fix m3u filename collision.
|
||||||
|
|
||||||
|
Oh! Multicast Video Scanner 0.3 2016-02-23
|
||||||
|
===============================================================================
|
||||||
|
* Add waiting for multicast packet mode.
|
||||||
|
* Support rtp protocol uri.
|
||||||
|
* Generate m3u file.
|
||||||
|
|
||||||
Oh! Multicast Video Scanner 0.2 2016-01-29
|
Oh! Multicast Video Scanner 0.2 2016-01-29
|
||||||
===============================================================================
|
===============================================================================
|
||||||
* Improve documents.
|
* Improve documents.
|
||||||
|
202
README
202
README
@ -8,42 +8,186 @@ something, omvs tries to decode it with gstreamer and saves it as png file in
|
|||||||
the output directory. There are many cases omvs finds something but png file is
|
the output directory. There are many cases omvs finds something but png file is
|
||||||
not stored. Such as, the video is scrambled(encrypted, not free), multicasting
|
not stored. Such as, the video is scrambled(encrypted, not free), multicasting
|
||||||
data doesn't contain video(audio only, data only), gstreamer doesn't recognize
|
data doesn't contain video(audio only, data only), gstreamer doesn't recognize
|
||||||
it(unknown codec), etc. If you increase the number of jobs with "-j" command
|
it(unknown codec), etc. If png file is successfully stored, the multicast ip
|
||||||
line option, you can scan faster. However, You need take caution, because it
|
address is stored in an m3u file in the output directory.
|
||||||
can cause network congestion.
|
|
||||||
|
|
||||||
As omvs uses libpcap to capture raw packet, root privilege is required to run
|
Disable all network device interfaces except for one network device interface
|
||||||
omvs.
|
is recommended, which means disabling all wifi network device interfaces and
|
||||||
|
disabling all unused ethernet network device interfaces.
|
||||||
|
|
||||||
|
With "-i" option, you can decide which network device interface is used. Use the
|
||||||
|
dev_idx from "-l" option output.
|
||||||
|
With "-l" option, you can see the available network device interface list.
|
||||||
|
With "-j" option, you can change the number of jobs. If you increase the number
|
||||||
|
of jobs, you can scan faster. However, You need take caution, because it can
|
||||||
|
cause network congestion.
|
||||||
|
With "-o" option, you can change the output directory. The default directory is
|
||||||
|
"omvs_out".
|
||||||
|
With "-s" option, you can change how long you sleep after finishing scanning an
|
||||||
|
multicast ip address before starting scanning the next ip address. The default
|
||||||
|
is 1000ms(1 second).
|
||||||
|
With "-t" option, you can change the scan timeout. The default scan timeout is
|
||||||
|
10000ms(10 seconds). It tries to get png image file while scanning. If it can't
|
||||||
|
get the png image file for the timeout, it gives up and tries the next
|
||||||
|
multicast ip address.
|
||||||
|
With "-u" option, you can scan with udp protocol instead of rtp protocol. The
|
||||||
|
default is scanning with rtp protocol.
|
||||||
|
With "-q" option, you can disable the log printing.
|
||||||
|
With "-w" option, you can wait for the multicast packet without specifying the
|
||||||
|
scanning ip addresses. When it detects multicast packet from the specified
|
||||||
|
network device, it tries to scan the ip address from multicast packet and save
|
||||||
|
the png file from the multicast ip address. In order to use "-w" option,
|
||||||
|
the network device interface need to be connected where it can sniff multicast
|
||||||
|
packet. The environment such as connection to switch hub without igmp-snooping
|
||||||
|
function is necessary. Press Ctrl-C if you want to stop waiting.
|
||||||
|
|
||||||
|
As omvs uses libpcap(or WinPcap on MS Windows) to capture raw packet, root
|
||||||
|
privilege is required to run omvs.
|
||||||
|
|
||||||
Run "./configure ; make" to build omvs. Run "./omvs" with scanning multicast ip
|
Run "./configure ; make" to build omvs. Run "./omvs" with scanning multicast ip
|
||||||
addresses.
|
addresses. For the detailed build information, consult INSTALL, INSTALL.ubuntu,
|
||||||
|
or INSTALL.windows.
|
||||||
|
|
||||||
e.g.)
|
e.g.)
|
||||||
|
Scanning multicast ip addresses.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
$ sudo ./omvs 233.19.187.192/30 233.19.187.244 233.19.187.1
|
$ ifconfig
|
||||||
[0x21be1e0] start scanning 233.19.187.192
|
eth0 Link encap:Ethernet HWaddr 80:ee:73:a2:58:4b
|
||||||
[0x21be1e0] trying to save udp://233.19.187.192:5000 to omvs_out/233.19.187.192-5000.png
|
inet addr:172.30.1.201 Bcast:172.30.1.255 Mask:255.255.255.0
|
||||||
[0x21be1e0] finish scanning 233.19.187.192
|
inet6 addr: fe80::82ee:73ff:fea2:584b/64 Scope:Link
|
||||||
[0x21be1e0] start scanning 233.19.187.193
|
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||||
[0x21be1e0] trying to save udp://233.19.187.193:5000 to omvs_out/233.19.187.193-5000.png
|
RX packets:41357508 errors:0 dropped:5 overruns:0 frame:0
|
||||||
[0x21be1e0] finish scanning 233.19.187.193
|
TX packets:827665 errors:0 dropped:0 overruns:0 carrier:0
|
||||||
[0x21be1e0] start scanning 233.19.187.194
|
collisions:0 txqueuelen:1000
|
||||||
[0x21be1e0] trying to save udp://233.19.187.194:5000 to omvs_out/233.19.187.194-5000.png
|
RX bytes:56530625218 (56.5 GB) TX bytes:99250131 (99.2 MB)
|
||||||
[0x21be1e0] finish scanning 233.19.187.194
|
|
||||||
[0x21be1e0] start scanning 233.19.187.195
|
eth1 Link encap:Ethernet HWaddr 80:ee:73:a2:58:4a
|
||||||
[0x21be1e0] trying to save udp://233.19.187.195:5000 to omvs_out/233.19.187.195-5000.png
|
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
||||||
[0x21be1e0] finish scanning 233.19.187.195
|
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||||
[0x21be1e0] start scanning 233.19.187.244
|
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||||
[0x21be1e0] trying to save udp://233.19.187.244:5000 to omvs_out/233.19.187.244-5000.png
|
collisions:0 txqueuelen:1000
|
||||||
[0x21be1e0] finish scanning 233.19.187.244
|
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
||||||
[0x21be1e0] start scanning 233.19.187.1
|
|
||||||
[0x21be1e0] finish scanning 233.19.187.1
|
lo Link encap:Local Loopback
|
||||||
|
inet addr:127.0.0.1 Mask:255.0.0.0
|
||||||
|
inet6 addr: ::1/128 Scope:Host
|
||||||
|
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||||
|
RX packets:38983 errors:0 dropped:0 overruns:0 frame:0
|
||||||
|
TX packets:38983 errors:0 dropped:0 overruns:0 carrier:0
|
||||||
|
collisions:0 txqueuelen:0
|
||||||
|
RX bytes:15278201 (15.2 MB) TX bytes:15278201 (15.2 MB)
|
||||||
|
|
||||||
|
$ sudo ./omvs -l
|
||||||
|
dev_idx(0) dev_name(eth0) dev_desc((null))
|
||||||
|
dev_idx(1) dev_name(bluetooth0) dev_desc(Bluetooth adapter number 0)
|
||||||
|
dev_idx(2) dev_name(nflog) dev_desc(Linux netfilter log (NFLOG) interface)
|
||||||
|
dev_idx(3) dev_name(nfqueue) dev_desc(Linux netfilter queue (NFQUEUE) interface)
|
||||||
|
dev_idx(4) dev_name(eth1) dev_desc((null))
|
||||||
|
dev_idx(5) dev_name(any) dev_desc(Pseudo-device that captures on all interfaces)
|
||||||
|
dev_idx(6) dev_name(lo) dev_desc((null))
|
||||||
|
$ sudo ./omvs -i 0 233.19.187.192/30 233.19.187.244 233.19.187.1
|
||||||
|
openning omvs_out/omvs_67883420797.m3u
|
||||||
|
[0x18c6230] start scanning 233.19.187.192
|
||||||
|
[0x18c6230] trying to save rtp://233.19.187.192:5000 to omvs_out/233.19.187.192-5000.png
|
||||||
|
[0x18c6230] finish scanning 233.19.187.192
|
||||||
|
[0x18c6230] start scanning 233.19.187.193
|
||||||
|
[0x18c6230] trying to save rtp://233.19.187.193:5000 to omvs_out/233.19.187.193-5000.png
|
||||||
|
[0x18c6230] finish scanning 233.19.187.193
|
||||||
|
[0x18c6230] start scanning 233.19.187.194
|
||||||
|
[0x18c6230] trying to save rtp://233.19.187.194:5000 to omvs_out/233.19.187.194-5000.png
|
||||||
|
[0x18c6230] finish scanning 233.19.187.194
|
||||||
|
[0x18c6230] start scanning 233.19.187.195
|
||||||
|
[0x18c6230] trying to save rtp://233.19.187.195:5000 to omvs_out/233.19.187.195-5000.png
|
||||||
|
[0x18c6230] finish scanning 233.19.187.195
|
||||||
|
[0x18c6230] start scanning 233.19.187.244
|
||||||
|
[0x18c6230] trying to save rtp://233.19.187.244:5000 to omvs_out/233.19.187.244-5000.png
|
||||||
|
[0x18c6230] finish scanning 233.19.187.244
|
||||||
|
[0x18c6230] start scanning 233.19.187.1
|
||||||
|
[0x18c6230] finish scanning 233.19.187.1
|
||||||
$ ls -l omvs_out
|
$ ls -l omvs_out
|
||||||
total 1960
|
total 1692
|
||||||
-rw-r--r-- 1 root root 545742 Jan 23 21:55 233.19.187.193-5000.png
|
-rw-r--r-- 1 root root 442585 Mar 3 01:54 233.19.187.193-5000.png
|
||||||
-rw-r--r-- 1 root root 477971 Jan 23 21:55 233.19.187.194-5000.png
|
-rw-r--r-- 1 root root 600331 Mar 3 01:54 233.19.187.194-5000.png
|
||||||
-rw-r--r-- 1 root root 398304 Jan 23 21:55 233.19.187.195-5000.png
|
-rw-r--r-- 1 root root 217721 Mar 3 01:54 233.19.187.195-5000.png
|
||||||
-rw-r--r-- 1 root root 574233 Jan 23 21:55 233.19.187.244-5000.png
|
-rw-r--r-- 1 root root 458283 Mar 3 01:54 233.19.187.244-5000.png
|
||||||
|
-rw-r--r-- 1 root root 160 Mar 3 01:54 omvs_67883420797.m3u
|
||||||
|
$ cat omvs_out/omvs_67883420797.m3u
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:1,1
|
||||||
|
rtp://233.19.187.193:5000
|
||||||
|
#EXTINF:2,2
|
||||||
|
rtp://233.19.187.194:5000
|
||||||
|
#EXTINF:3,3
|
||||||
|
rtp://233.19.187.195:5000
|
||||||
|
#EXTINF:4,4
|
||||||
|
rtp://233.19.187.244:5000
|
||||||
|
$
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Waiting for the multicast packet.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$ ifconfig
|
||||||
|
eth0 Link encap:Ethernet HWaddr 80:ee:73:a2:58:4b
|
||||||
|
inet6 addr: fe80::82ee:73ff:fea2:584b/64 Scope:Link
|
||||||
|
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||||
|
RX packets:41357843 errors:0 dropped:5 overruns:0 frame:0
|
||||||
|
TX packets:828004 errors:0 dropped:0 overruns:0 carrier:0
|
||||||
|
collisions:0 txqueuelen:1000
|
||||||
|
RX bytes:56530695954 (56.5 GB) TX bytes:99292621 (99.2 MB)
|
||||||
|
|
||||||
|
eth1 Link encap:Ethernet HWaddr 80:ee:73:a2:58:4a
|
||||||
|
inet addr:183.101.193.195 Bcast:183.101.193.255 Mask:255.255.255.0
|
||||||
|
inet6 addr: fe80::82ee:73ff:fea2:584a/64 Scope:Link
|
||||||
|
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||||
|
RX packets:408 errors:0 dropped:0 overruns:0 frame:0
|
||||||
|
TX packets:149 errors:0 dropped:0 overruns:0 carrier:0
|
||||||
|
collisions:0 txqueuelen:1000
|
||||||
|
RX bytes:44532 (44.5 KB) TX bytes:23688 (23.6 KB)
|
||||||
|
|
||||||
|
lo Link encap:Local Loopback
|
||||||
|
inet addr:127.0.0.1 Mask:255.0.0.0
|
||||||
|
inet6 addr: ::1/128 Scope:Host
|
||||||
|
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||||
|
RX packets:39301 errors:0 dropped:0 overruns:0 frame:0
|
||||||
|
TX packets:39301 errors:0 dropped:0 overruns:0 carrier:0
|
||||||
|
collisions:0 txqueuelen:0
|
||||||
|
RX bytes:15311882 (15.3 MB) TX bytes:15311882 (15.3 MB)
|
||||||
|
|
||||||
|
$ sudo ./omvs -l
|
||||||
|
dev_idx(0) dev_name(eth0) dev_desc((null))
|
||||||
|
dev_idx(1) dev_name(bluetooth0) dev_desc(Bluetooth adapter number 0)
|
||||||
|
dev_idx(2) dev_name(nflog) dev_desc(Linux netfilter log (NFLOG) interface)
|
||||||
|
dev_idx(3) dev_name(nfqueue) dev_desc(Linux netfilter queue (NFQUEUE) interface)
|
||||||
|
dev_idx(4) dev_name(eth1) dev_desc((null))
|
||||||
|
dev_idx(5) dev_name(any) dev_desc(Pseudo-device that captures on all interfaces)
|
||||||
|
dev_idx(6) dev_name(lo) dev_desc((null))
|
||||||
|
$ sudo ./omvs -i 4 -w
|
||||||
|
openning omvs_out/omvs_68456824735.m3u
|
||||||
|
[0x1029840] start scanning 233.18.158.252
|
||||||
|
[0x1029840] trying to save rtp://233.18.158.252:1901 to omvs_out/233.18.158.252-1901.png
|
||||||
|
[0x1029840] finish scanning 233.18.158.252
|
||||||
|
[0x1029840] start scanning 233.14.173.241
|
||||||
|
[0x1029840] trying to save rtp://233.14.173.241:5000 to omvs_out/233.14.173.241-5000.png
|
||||||
|
[0x1029840] finish scanning 233.14.173.241
|
||||||
|
[0x1029840] start scanning 233.18.158.250
|
||||||
|
[0x1029840] trying to save rtp://233.18.158.250:1902 to omvs_out/233.18.158.250-1902.png
|
||||||
|
[0x1029840] finish scanning 233.18.158.250
|
||||||
|
[0x1029840] start scanning 233.18.158.206
|
||||||
|
[0x1029840] trying to save rtp://233.18.158.206:5000 to omvs_out/233.18.158.206-5000.png
|
||||||
|
[0x1029840] finish scanning 233.18.158.206
|
||||||
|
[0x1029840] start scanning 233.18.158.75
|
||||||
|
[0x1029840] trying to save rtp://233.18.158.75:5000 to omvs_out/233.18.158.75-5000.png
|
||||||
|
[0x1029840] finish scanning 233.18.158.75
|
||||||
|
^C$ ls -l omvs_out
|
||||||
|
total 3876
|
||||||
|
-rw-r--r-- 1 root root 1917823 Mar 3 02:05 233.18.158.206-5000.png
|
||||||
|
-rw-r--r-- 1 root root 2040917 Mar 3 02:07 233.18.158.75-5000.png
|
||||||
|
-rw-r--r-- 1 root root 83 Mar 3 02:07 omvs_68456824735.m3u
|
||||||
|
$ cat omvs_out/omvs_68456824735.m3u
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:1,1
|
||||||
|
rtp://233.18.158.206:5000
|
||||||
|
#EXTINF:2,2
|
||||||
|
rtp://233.18.158.75:5000
|
||||||
$
|
$
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
20
configure
vendored
20
configure
vendored
@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for Oh! Multicast Video Scanner 0.2.
|
# Generated by GNU Autoconf 2.69 for Oh! Multicast Video Scanner 0.4.
|
||||||
#
|
#
|
||||||
# Report bugs to <ohhara@postech.edu>.
|
# Report bugs to <ohhara@postech.edu>.
|
||||||
#
|
#
|
||||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='Oh! Multicast Video Scanner'
|
PACKAGE_NAME='Oh! Multicast Video Scanner'
|
||||||
PACKAGE_TARNAME='omvs'
|
PACKAGE_TARNAME='omvs'
|
||||||
PACKAGE_VERSION='0.2'
|
PACKAGE_VERSION='0.4'
|
||||||
PACKAGE_STRING='Oh! Multicast Video Scanner 0.2'
|
PACKAGE_STRING='Oh! Multicast Video Scanner 0.4'
|
||||||
PACKAGE_BUGREPORT='ohhara@postech.edu'
|
PACKAGE_BUGREPORT='ohhara@postech.edu'
|
||||||
PACKAGE_URL='http://ohhara.sarang.net/omvs'
|
PACKAGE_URL='http://ohhara.sarang.net/omvs'
|
||||||
|
|
||||||
@ -1332,7 +1332,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures Oh! Multicast Video Scanner 0.2 to adapt to many kinds of systems.
|
\`configure' configures Oh! Multicast Video Scanner 0.4 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1402,7 +1402,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of Oh! Multicast Video Scanner 0.2:";;
|
short | recursive ) echo "Configuration of Oh! Multicast Video Scanner 0.4:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1524,7 +1524,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
Oh! Multicast Video Scanner configure 0.2
|
Oh! Multicast Video Scanner configure 0.4
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -1893,7 +1893,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by Oh! Multicast Video Scanner $as_me 0.2, which was
|
It was created by Oh! Multicast Video Scanner $as_me 0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -2757,7 +2757,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='omvs'
|
PACKAGE='omvs'
|
||||||
VERSION='0.2'
|
VERSION='0.4'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -13266,7 +13266,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by Oh! Multicast Video Scanner $as_me 0.2, which was
|
This file was extended by Oh! Multicast Video Scanner $as_me 0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -13333,7 +13333,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
Oh! Multicast Video Scanner config.status 0.2
|
Oh! Multicast Video Scanner config.status 0.4
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([Oh! Multicast Video Scanner], [0.2], [ohhara@postech.edu], [omvs],
|
AC_INIT([Oh! Multicast Video Scanner], [0.4], [ohhara@postech.edu], [omvs],
|
||||||
[http://ohhara.sarang.net/omvs])
|
[http://ohhara.sarang.net/omvs])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_INIT_AUTOMAKE([-Wall])
|
AM_INIT_AUTOMAKE([-Wall])
|
||||||
|
31
omvs_gst.c
31
omvs_gst.c
@ -18,6 +18,7 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include "omvs_gst.h"
|
#include "omvs_gst.h"
|
||||||
|
|
||||||
@ -29,6 +30,9 @@ typedef struct _OMVSGstImpl {
|
|||||||
OMVSGst omvs_gst_open(const gchar *uri, const gchar *filename) {
|
OMVSGst omvs_gst_open(const gchar *uri, const gchar *filename) {
|
||||||
guint flags;
|
guint flags;
|
||||||
OMVSGstImpl *gst_impl;
|
OMVSGstImpl *gst_impl;
|
||||||
|
gchar *protocol;
|
||||||
|
gchar *location;
|
||||||
|
gchar *real_uri;
|
||||||
GstElement *play;
|
GstElement *play;
|
||||||
GstElement *conv;
|
GstElement *conv;
|
||||||
GstElement *png;
|
GstElement *png;
|
||||||
@ -37,9 +41,34 @@ OMVSGst omvs_gst_open(const gchar *uri, const gchar *filename) {
|
|||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
GstPad *ghostpad;
|
GstPad *ghostpad;
|
||||||
|
|
||||||
|
if (gst_uri_is_valid(uri)) {
|
||||||
|
protocol = gst_uri_get_protocol(uri);
|
||||||
|
if (protocol) {
|
||||||
|
location = gst_uri_get_location(uri);
|
||||||
|
if (location) {
|
||||||
|
if (!gst_uri_protocol_is_supported(GST_URI_SRC, protocol)) {
|
||||||
|
if (strcmp(protocol, "rtp") == 0) {
|
||||||
|
g_free(protocol);
|
||||||
|
protocol = g_strdup("ortp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
real_uri = g_strdup_printf("%s://%s", protocol, location);
|
||||||
|
g_free(location);
|
||||||
|
} else {
|
||||||
|
real_uri = g_strdup(uri);
|
||||||
|
}
|
||||||
|
g_free(protocol);
|
||||||
|
} else {
|
||||||
|
real_uri = g_strdup(uri);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
real_uri = g_strdup(uri);
|
||||||
|
}
|
||||||
|
|
||||||
gst_impl = g_malloc0(sizeof(OMVSGstImpl));
|
gst_impl = g_malloc0(sizeof(OMVSGstImpl));
|
||||||
gst_impl->play = play = gst_element_factory_make("playbin", "play");
|
gst_impl->play = play = gst_element_factory_make("playbin", "play");
|
||||||
g_object_set(G_OBJECT(play), "uri", uri, NULL);
|
g_object_set(G_OBJECT(play), "uri", real_uri, NULL);
|
||||||
|
g_free(real_uri);
|
||||||
g_object_get(play, "flags", &flags, NULL);
|
g_object_get(play, "flags", &flags, NULL);
|
||||||
flags &= (~0x00000002);
|
flags &= (~0x00000002);
|
||||||
g_object_set(play, "flags", flags, NULL);
|
g_object_set(play, "flags", flags, NULL);
|
||||||
|
53
omvs_gst_plugin.c
Normal file
53
omvs_gst_plugin.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Oh! Multicast Video Scanner
|
||||||
|
Copyright (C) 2016 Taeho Oh <ohhara@postech.edu>
|
||||||
|
|
||||||
|
This file is part of Oh! Multicast Video Scanner.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "omvs_gst_plugin.h"
|
||||||
|
#include "omvs_gst_plugin_rtpsrc.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
static gboolean omvs_gst_plugin_init(GstPlugin *plugin);
|
||||||
|
|
||||||
|
static gboolean omvs_gst_plugin_init(GstPlugin *plugin) {
|
||||||
|
if (!omvs_gst_plugin_rtpsrc_init(plugin)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, omvsrtp,
|
||||||
|
"RTP protocol for " PACKAGE, omvs_gst_plugin_init, PACKAGE_VERSION, "GPL",
|
||||||
|
PACKAGE, PACKAGE_URL)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
gboolean omvs_gst_plugin_register(void) {
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
|
||||||
|
"omvsrtpsrc", "RTP protocol for " PACKAGE, omvs_gst_plugin_rtpsrc_init,
|
||||||
|
PACKAGE_VERSION, "GPL", PACKAGE, PACKAGE, PACKAGE_URL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
28
omvs_gst_plugin.h
Normal file
28
omvs_gst_plugin.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
Oh! Multicast Video Scanner
|
||||||
|
Copyright (C) 2016 Taeho Oh <ohhara@postech.edu>
|
||||||
|
|
||||||
|
This file is part of Oh! Multicast Video Scanner.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OMVS_GST_PLUGIN_H_
|
||||||
|
#define _OMVS_GST_PLUGIN_H_
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
extern gboolean omvs_gst_plugin_register(void);
|
||||||
|
|
||||||
|
#endif /* _OMVS_GST_PLUGIN_H_ */
|
398
omvs_gst_plugin_rtpsrc.c
Normal file
398
omvs_gst_plugin_rtpsrc.c
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/*
|
||||||
|
Oh! Multicast Video Scanner
|
||||||
|
Copyright (C) 2016 Taeho Oh <ohhara@postech.edu>
|
||||||
|
|
||||||
|
This file is part of Oh! Multicast Video Scanner.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "omvs_gst_plugin_rtpsrc.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC(omvs_rtpsrc_debug);
|
||||||
|
#define GST_CAT_DEFAULT omvs_rtpsrc_debug
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_URI,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_PROP_URI (NULL)
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("src",
|
||||||
|
GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS("application/x-rtp"));
|
||||||
|
|
||||||
|
static gboolean gst_omvs_rtpsrc_parse_uri(const gchar *uristr, gchar **host,
|
||||||
|
guint16 *port);
|
||||||
|
static GstURIType gst_omvs_rtpsrc_uri_get_type(GType type);
|
||||||
|
static const gchar *const *gst_omvs_rtpsrc_uri_get_protocols(GType type);
|
||||||
|
static gchar *gst_omvs_rtpsrc_uri_get_uri(GstURIHandler *handler);
|
||||||
|
static gboolean gst_omvs_rtpsrc_uri_set_uri(GstURIHandler *handler,
|
||||||
|
const gchar *uri, GError **error);
|
||||||
|
static void gst_omvs_rtpsrc_uri_handler_init(gpointer g_iface,
|
||||||
|
gpointer iface_data);
|
||||||
|
static void gst_omvs_rtpsrc_set_property(GObject *object, guint prop_id,
|
||||||
|
const GValue *value, GParamSpec *pspec);
|
||||||
|
static void gst_omvs_rtpsrc_get_property(GObject *object, guint prop_id,
|
||||||
|
GValue *value, GParamSpec *pspec);
|
||||||
|
static void gst_omvs_rtpsrc_finalize(GObject *gobject);
|
||||||
|
static void gst_omvs_rtpsrc_rtpbin_pad_added_cb(GstElement *element,
|
||||||
|
GstPad *pad, gpointer data);
|
||||||
|
static gboolean gst_omvs_rtpsrc_start(GstOMVSRtpSrc *rtpsrc);
|
||||||
|
static GstStateChangeReturn gst_omvs_rtpsrc_change_state(GstElement *element,
|
||||||
|
GstStateChange transition);
|
||||||
|
|
||||||
|
static gboolean gst_omvs_rtpsrc_parse_uri(const gchar *uristr, gchar **host,
|
||||||
|
guint16 *port) {
|
||||||
|
gchar *protocol, *location_start;
|
||||||
|
gchar *location, *location_end;
|
||||||
|
gchar *colptr;
|
||||||
|
|
||||||
|
protocol = gst_uri_get_protocol(uristr);
|
||||||
|
if (!protocol) {
|
||||||
|
goto no_protocol;
|
||||||
|
}
|
||||||
|
if (strcmp(protocol, "ortp") != 0) {
|
||||||
|
goto wrong_protocol;
|
||||||
|
}
|
||||||
|
g_free(protocol);
|
||||||
|
|
||||||
|
location_start = gst_uri_get_location(uristr);
|
||||||
|
if (!location_start) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG("got location '%s'", location_start);
|
||||||
|
|
||||||
|
location = g_strstr_len(location_start, -1, "@");
|
||||||
|
if (location == NULL) {
|
||||||
|
location = location_start;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
location += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location[0] == '[') {
|
||||||
|
GST_DEBUG("parse IPV6 address '%s'", location);
|
||||||
|
location_end = strchr(location, ']');
|
||||||
|
if (location_end == NULL) {
|
||||||
|
goto wrong_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
*host = g_strndup(location + 1, location_end - location - 1);
|
||||||
|
colptr = strrchr(location_end, ':');
|
||||||
|
} else {
|
||||||
|
GST_DEBUG("parse IPV4 address '%s'", location);
|
||||||
|
colptr = strrchr(location, ':');
|
||||||
|
|
||||||
|
if (colptr != NULL) {
|
||||||
|
*host = g_strndup(location, colptr - location);
|
||||||
|
} else {
|
||||||
|
*host = g_strdup(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GST_DEBUG("host set to '%s'", *host);
|
||||||
|
|
||||||
|
if (colptr != NULL) {
|
||||||
|
*port = g_ascii_strtoll(colptr + 1, NULL, 10);
|
||||||
|
} else {
|
||||||
|
*port = 0;
|
||||||
|
}
|
||||||
|
g_free(location_start);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
no_protocol:
|
||||||
|
{
|
||||||
|
GST_ERROR("error parsing uri %s: no protocol", uristr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
wrong_protocol:
|
||||||
|
{
|
||||||
|
GST_ERROR("error parsing uri %s: wrong protocol (%s != ortp)", uristr,
|
||||||
|
protocol);
|
||||||
|
g_free(protocol);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
wrong_address:
|
||||||
|
{
|
||||||
|
GST_ERROR("error parsing uri %s", uristr);
|
||||||
|
g_free(location);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define gst_omvs_rtpsrc_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE_WITH_CODE(GstOMVSRtpSrc, gst_omvs_rtpsrc, GST_TYPE_BIN,
|
||||||
|
G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER,
|
||||||
|
gst_omvs_rtpsrc_uri_handler_init))
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_class_init(GstOMVSRtpSrcClass *klass) {
|
||||||
|
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||||
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
|
||||||
|
|
||||||
|
oclass->set_property = gst_omvs_rtpsrc_set_property;
|
||||||
|
oclass->get_property = gst_omvs_rtpsrc_get_property;
|
||||||
|
oclass->finalize = gst_omvs_rtpsrc_finalize;
|
||||||
|
|
||||||
|
g_object_class_install_property(oclass, PROP_URI,
|
||||||
|
g_param_spec_string("uri", "URI", "URI of the media to play",
|
||||||
|
DEFAULT_PROP_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template(gstelement_class,
|
||||||
|
gst_static_pad_template_get(&src_template));
|
||||||
|
|
||||||
|
gstelement_class->change_state =
|
||||||
|
GST_DEBUG_FUNCPTR(gst_omvs_rtpsrc_change_state);
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata(gstelement_class, "omvsrtpsrc",
|
||||||
|
"Generic/Bin/Src", "OMVS RTP Src", "Taeho Oh <ohhara@postech.edu>");
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT(omvs_rtpsrc_debug, "omvsrtpsrc", 0, "OMVS RTP Src");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_init(GstOMVSRtpSrc *rtpsrc) {
|
||||||
|
rtpsrc->uri = NULL;
|
||||||
|
rtpsrc->udpsrc = NULL;
|
||||||
|
rtpsrc->rtpbin = NULL;
|
||||||
|
rtpsrc->n_pads = 0;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "omvsrtpsrc initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstURIType gst_omvs_rtpsrc_uri_get_type(GType type) {
|
||||||
|
(void)type;
|
||||||
|
return GST_URI_SRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *const *gst_omvs_rtpsrc_uri_get_protocols(GType type) {
|
||||||
|
static const gchar *protocols[] = { "ortp", NULL };
|
||||||
|
|
||||||
|
(void)type;
|
||||||
|
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *gst_omvs_rtpsrc_uri_get_uri(GstURIHandler *handler) {
|
||||||
|
GstOMVSRtpSrc *rtpsrc = GST_OMVS_RTPSRC(handler);
|
||||||
|
|
||||||
|
return g_strdup(rtpsrc->uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean gst_omvs_rtpsrc_uri_set_uri(GstURIHandler *handler,
|
||||||
|
const gchar *uri, GError **error) {
|
||||||
|
GstOMVSRtpSrc *rtpsrc = (GstOMVSRtpSrc *)handler;
|
||||||
|
|
||||||
|
(void)error;
|
||||||
|
|
||||||
|
g_object_set(G_OBJECT(rtpsrc), "uri", uri, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_uri_handler_init(gpointer g_iface,
|
||||||
|
gpointer iface_data) {
|
||||||
|
GstURIHandlerInterface *iface = (GstURIHandlerInterface *)g_iface;
|
||||||
|
|
||||||
|
(void)iface_data;
|
||||||
|
|
||||||
|
iface->get_type = gst_omvs_rtpsrc_uri_get_type;
|
||||||
|
iface->get_protocols = gst_omvs_rtpsrc_uri_get_protocols;
|
||||||
|
iface->get_uri = gst_omvs_rtpsrc_uri_get_uri;
|
||||||
|
iface->set_uri = gst_omvs_rtpsrc_uri_set_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_set_property(GObject *object, guint prop_id,
|
||||||
|
const GValue *value, GParamSpec *pspec) {
|
||||||
|
GstOMVSRtpSrc *rtpsrc = GST_OMVS_RTPSRC(object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_URI:
|
||||||
|
g_free(rtpsrc->uri);
|
||||||
|
rtpsrc->uri = g_strdup(g_value_get_string(value));
|
||||||
|
if (rtpsrc->udpsrc) {
|
||||||
|
gchar *host;
|
||||||
|
guint16 port;
|
||||||
|
if (gst_omvs_rtpsrc_parse_uri(rtpsrc->uri, &host, &port)) {
|
||||||
|
gchar *udpsrc_uri;
|
||||||
|
udpsrc_uri = g_strdup_printf("udp://%s:%u", host, port);
|
||||||
|
g_object_set(G_OBJECT(rtpsrc->udpsrc), "uri", udpsrc_uri, NULL);
|
||||||
|
g_free(host);
|
||||||
|
g_free(udpsrc_uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_get_property(GObject *object, guint prop_id,
|
||||||
|
GValue *value, GParamSpec *pspec) {
|
||||||
|
GstOMVSRtpSrc *rtpsrc = GST_OMVS_RTPSRC(object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_URI:
|
||||||
|
g_value_set_string(value, rtpsrc->uri);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_finalize(GObject *gobject) {
|
||||||
|
GstOMVSRtpSrc *rtpsrc = GST_OMVS_RTPSRC(gobject);
|
||||||
|
|
||||||
|
g_free(rtpsrc->uri);
|
||||||
|
rtpsrc->uri = NULL;
|
||||||
|
rtpsrc->udpsrc = NULL;
|
||||||
|
rtpsrc->rtpbin = NULL;
|
||||||
|
rtpsrc->n_pads = 0;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS(parent_class)->finalize(gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_omvs_rtpsrc_rtpbin_pad_added_cb(GstElement *element,
|
||||||
|
GstPad *pad, gpointer data) {
|
||||||
|
gchar *name;
|
||||||
|
GstOMVSRtpSrc *rtpsrc = (GstOMVSRtpSrc *)data;
|
||||||
|
|
||||||
|
(void)element;
|
||||||
|
|
||||||
|
name = gst_pad_get_name(pad);
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "adding a pad %s", name);
|
||||||
|
|
||||||
|
if (strncmp(name, "recv_rtp_src_", strlen("recv_rtp_src_")) != 0) {
|
||||||
|
g_free(name);
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "Pad name does not start with recv_rtp_src_");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
if (GST_PAD_DIRECTION(pad) == GST_PAD_SINK) {
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "Pad is not src pad");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_ref(pad);
|
||||||
|
|
||||||
|
if (rtpsrc->n_pads) {
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "Ignore SSRC");
|
||||||
|
gst_ghost_pad_set_target(GST_GHOST_PAD(rtpsrc->ghostpad), pad);
|
||||||
|
gst_object_unref(pad);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtpsrc->ghostpad = gst_ghost_pad_new("src", pad);
|
||||||
|
gst_pad_set_active(rtpsrc->ghostpad, TRUE);
|
||||||
|
gst_element_add_pad(GST_ELEMENT(rtpsrc), rtpsrc->ghostpad);
|
||||||
|
gst_object_unref(pad);
|
||||||
|
|
||||||
|
rtpsrc->n_pads++;
|
||||||
|
|
||||||
|
gst_element_no_more_pads(GST_ELEMENT(rtpsrc));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean gst_omvs_rtpsrc_start(GstOMVSRtpSrc *rtpsrc) {
|
||||||
|
gchar *host;
|
||||||
|
guint16 port;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "Creating elements");
|
||||||
|
|
||||||
|
rtpsrc->udpsrc = gst_element_factory_make("udpsrc", NULL);
|
||||||
|
if (!rtpsrc->udpsrc) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtpsrc->rtpbin = gst_element_factory_make("rtpbin", NULL);
|
||||||
|
if (!rtpsrc->rtpbin) {
|
||||||
|
gst_object_unref(rtpsrc->udpsrc);
|
||||||
|
rtpsrc->udpsrc = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
caps = gst_caps_new_simple("application/x-rtp",
|
||||||
|
"media", G_TYPE_STRING, "video",
|
||||||
|
"clock-rate", G_TYPE_INT, 90000,
|
||||||
|
"payload", G_TYPE_INT, 33,
|
||||||
|
NULL);
|
||||||
|
g_object_set(G_OBJECT(rtpsrc->udpsrc), "caps", caps, NULL);
|
||||||
|
gst_caps_unref(caps);
|
||||||
|
|
||||||
|
if (gst_omvs_rtpsrc_parse_uri(rtpsrc->uri, &host, &port)) {
|
||||||
|
gchar *udpsrc_uri;
|
||||||
|
udpsrc_uri = g_strdup_printf("udp://%s:%u", host, port);
|
||||||
|
g_object_set(G_OBJECT(rtpsrc->udpsrc), "uri", udpsrc_uri, NULL);
|
||||||
|
g_free(host);
|
||||||
|
g_free(udpsrc_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_bin_add_many(GST_BIN(rtpsrc), rtpsrc->udpsrc, rtpsrc->rtpbin, NULL);
|
||||||
|
gst_element_link_pads(rtpsrc->udpsrc, "src", rtpsrc->rtpbin,
|
||||||
|
"recv_rtp_sink_0");
|
||||||
|
|
||||||
|
g_signal_connect(rtpsrc->rtpbin, "pad-added",
|
||||||
|
G_CALLBACK(gst_omvs_rtpsrc_rtpbin_pad_added_cb), rtpsrc);
|
||||||
|
|
||||||
|
if (!gst_element_sync_state_with_parent(rtpsrc->udpsrc)) {
|
||||||
|
GST_ERROR_OBJECT(rtpsrc, "Could not set udpsrc to playing");
|
||||||
|
}
|
||||||
|
if (!gst_element_sync_state_with_parent(rtpsrc->rtpbin)) {
|
||||||
|
GST_ERROR_OBJECT(rtpsrc, "Could not set rtpbin to playing");
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstStateChangeReturn gst_omvs_rtpsrc_change_state(GstElement *element,
|
||||||
|
GstStateChange transition) {
|
||||||
|
GstOMVSRtpSrc *rtpsrc = GST_OMVS_RTPSRC(element);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "Configuring omvsrtpsrc");
|
||||||
|
if (!gst_omvs_rtpsrc_start(rtpsrc)) {
|
||||||
|
GST_DEBUG_OBJECT(rtpsrc, "Start failed");
|
||||||
|
return GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
|
break;
|
||||||
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||||
|
break;
|
||||||
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean omvs_gst_plugin_rtpsrc_init(GstPlugin *plugin) {
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_element_register(plugin, "omvsrtpsrc", GST_RANK_NONE,
|
||||||
|
GST_TYPE_OMVS_RTPSRC);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
58
omvs_gst_plugin_rtpsrc.h
Normal file
58
omvs_gst_plugin_rtpsrc.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Oh! Multicast Video Scanner
|
||||||
|
Copyright (C) 2016 Taeho Oh <ohhara@postech.edu>
|
||||||
|
|
||||||
|
This file is part of Oh! Multicast Video Scanner.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OMVS_GST_PLUGIN_RTPSRC_H_
|
||||||
|
#define _OMVS_GST_PLUGIN_RTPSRC_H_
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#define GST_TYPE_OMVS_RTPSRC (gst_omvs_rtpsrc_get_type())
|
||||||
|
#define GST_OMVS_RTPSRC(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_OMVS_RTPSRC, GstOMVSRtpSrc))
|
||||||
|
#define GST_OMVS_RTPSRC_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_OMVS_RTPSRC, GstOMVSRtpSrcClass))
|
||||||
|
#define GST_IS_OMVS_RTPSRC(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OMVS_RTPSRC))
|
||||||
|
#define GST_IS_OMVS_RTPSRC_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_OMVS_RTPSRC))
|
||||||
|
#define GST_OMVS_RTPSRC_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_OMVS_RTPSRC, GstOMVSRtpSrcClass))
|
||||||
|
|
||||||
|
typedef struct _GstOMVSRtpSrcClass GstOMVSRtpSrcClass;
|
||||||
|
typedef struct _GstOMVSRtpSrc GstOMVSRtpSrc;
|
||||||
|
|
||||||
|
struct _GstOMVSRtpSrcClass {
|
||||||
|
GstBinClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstOMVSRtpSrc {
|
||||||
|
GstBin parent_instance;
|
||||||
|
|
||||||
|
gchar *uri;
|
||||||
|
GstElement *udpsrc;
|
||||||
|
GstElement *rtpbin;
|
||||||
|
GstPad *ghostpad;
|
||||||
|
gint n_pads;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern GType gst_omvs_rtpsrc_get_type(void);
|
||||||
|
extern gboolean omvs_gst_plugin_rtpsrc_init(GstPlugin *plugin);
|
||||||
|
|
||||||
|
#endif /* _OMVS_GST_PLUGIN_RTPSRC_H_ */
|
258
omvs_main.c
258
omvs_main.c
@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
Oh! Multicast Video Scanner
|
||||||
|
Copyright (C) 2016 Taeho Oh <ohhara@postech.edu>
|
||||||
|
|
||||||
|
This file is part of Oh! Multicast Video Scanner.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pcap/pcap.h>
|
#include <pcap/pcap.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@ -7,6 +27,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "omvs_gst.h"
|
#include "omvs_gst.h"
|
||||||
|
#include "omvs_gst_plugin.h"
|
||||||
|
|
||||||
#define _OMVS_IPPROTO_UDP 17
|
#define _OMVS_IPPROTO_UDP 17
|
||||||
|
|
||||||
@ -16,11 +37,16 @@ static gchar *_omvs_outdir = "omvs_out";
|
|||||||
static gint _omvs_jobs = 1;
|
static gint _omvs_jobs = 1;
|
||||||
static gint _omvs_sleep = 1000;
|
static gint _omvs_sleep = 1000;
|
||||||
static gint _omvs_timeout = 10000;
|
static gint _omvs_timeout = 10000;
|
||||||
|
static gboolean _omvs_udp_scan;
|
||||||
static gboolean _omvs_quiet;
|
static gboolean _omvs_quiet;
|
||||||
|
static gboolean _omvs_wait;
|
||||||
|
|
||||||
static gchar **_omvs_net_dev_names;
|
static gchar **_omvs_net_dev_names;
|
||||||
static gchar **_omvs_net_dev_descs;
|
static gchar **_omvs_net_dev_descs;
|
||||||
static gint _omvs_num_net_devs;
|
static gint _omvs_num_net_devs;
|
||||||
|
static FILE *_omvs_m3u_fp;
|
||||||
|
static gint _omvs_m3u_idx;
|
||||||
|
static GMutex _omvs_mutex;
|
||||||
|
|
||||||
static GOptionEntry _omvs_entries[] =
|
static GOptionEntry _omvs_entries[] =
|
||||||
{
|
{
|
||||||
@ -36,8 +62,12 @@ static GOptionEntry _omvs_entries[] =
|
|||||||
"Sleep time(milliseconds) between scans", "ms" },
|
"Sleep time(milliseconds) between scans", "ms" },
|
||||||
{ "timeout", 't', 0, G_OPTION_ARG_INT, &_omvs_timeout,
|
{ "timeout", 't', 0, G_OPTION_ARG_INT, &_omvs_timeout,
|
||||||
"Timeout time(milliseconds) in each scan", "ms" },
|
"Timeout time(milliseconds) in each scan", "ms" },
|
||||||
|
{ "udp", 'u', 0, G_OPTION_ARG_NONE, &_omvs_udp_scan,
|
||||||
|
"Use udp protocol instead of rtp", NULL },
|
||||||
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &_omvs_quiet,
|
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &_omvs_quiet,
|
||||||
"Print no log except for errors", NULL },
|
"Print no log except for errors", NULL },
|
||||||
|
{ "wait", 'w', 0, G_OPTION_ARG_NONE, &_omvs_wait,
|
||||||
|
"Wait for multicast packet", NULL },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,6 +114,7 @@ static gint _omvs_print_net_devs_info(void);
|
|||||||
static gint _omvs_deinit_net_devs_info(void);
|
static gint _omvs_deinit_net_devs_info(void);
|
||||||
static gint _omvs_start_scan(OMVSScanner *scanner);
|
static gint _omvs_start_scan(OMVSScanner *scanner);
|
||||||
static gpointer _omvs_start_scan_job(gpointer data);
|
static gpointer _omvs_start_scan_job(gpointer data);
|
||||||
|
static gint _omvs_wait_for_multicast_packet(void);
|
||||||
|
|
||||||
static gint _omvs_init_net_devs_info(void) {
|
static gint _omvs_init_net_devs_info(void) {
|
||||||
gchar errbuf[PCAP_ERRBUF_SIZE];
|
gchar errbuf[PCAP_ERRBUF_SIZE];
|
||||||
@ -92,7 +123,7 @@ static gint _omvs_init_net_devs_info(void) {
|
|||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
if (pcap_findalldevs(&alldevs, errbuf) != 0) {
|
if (pcap_findalldevs(&alldevs, errbuf) != 0) {
|
||||||
g_print("pcap_findalldevs() fail: %s", errbuf);
|
g_print("pcap_findalldevs() fail: %s\n", errbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dev = alldevs;
|
dev = alldevs;
|
||||||
@ -198,7 +229,7 @@ static gpointer _omvs_start_scan_job(gpointer data) {
|
|||||||
addr[3] = (guint8)((o_ipaddr->addr >> 0) & 0xff);
|
addr[3] = (guint8)((o_ipaddr->addr >> 0) & 0xff);
|
||||||
|
|
||||||
addr_str =
|
addr_str =
|
||||||
g_strdup_printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
|
g_strdup_printf("%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
|
||||||
|
|
||||||
if (!_omvs_quiet) {
|
if (!_omvs_quiet) {
|
||||||
g_print("[%p] start scanning %s\n", (void *)g_thread_self(), addr_str);
|
g_print("[%p] start scanning %s\n", (void *)g_thread_self(), addr_str);
|
||||||
@ -284,7 +315,11 @@ static gpointer _omvs_start_scan_job(gpointer data) {
|
|||||||
if (!is_udp_port_found) {
|
if (!is_udp_port_found) {
|
||||||
gchar *uri;
|
gchar *uri;
|
||||||
gchar *filename;
|
gchar *filename;
|
||||||
|
if (_omvs_udp_scan) {
|
||||||
uri = g_strdup_printf("udp://%s:%d", addr_str, udp_port);
|
uri = g_strdup_printf("udp://%s:%d", addr_str, udp_port);
|
||||||
|
} else {
|
||||||
|
uri = g_strdup_printf("rtp://%s:%d", addr_str, udp_port);
|
||||||
|
}
|
||||||
filename =
|
filename =
|
||||||
g_strdup_printf("%s/%s-%d.png", _omvs_outdir, addr_str, udp_port);
|
g_strdup_printf("%s/%s-%d.png", _omvs_outdir, addr_str, udp_port);
|
||||||
if (!_omvs_quiet) {
|
if (!_omvs_quiet) {
|
||||||
@ -333,6 +368,25 @@ static gpointer _omvs_start_scan_job(gpointer data) {
|
|||||||
omvs_gst_close(o_ipaddr->gsts[j]);
|
omvs_gst_close(o_ipaddr->gsts[j]);
|
||||||
}
|
}
|
||||||
g_free(o_ipaddr->gsts);
|
g_free(o_ipaddr->gsts);
|
||||||
|
for (j = 0; j < o_ipaddr->num_ports; j++) {
|
||||||
|
gchar *filename;
|
||||||
|
filename = g_strdup_printf("%s/%s-%d.png", _omvs_outdir, addr_str,
|
||||||
|
o_ipaddr->ports[j]);
|
||||||
|
if (g_access(filename, F_OK) == 0) {
|
||||||
|
_omvs_m3u_idx++;
|
||||||
|
g_mutex_lock(&_omvs_mutex);
|
||||||
|
fprintf(_omvs_m3u_fp, "#EXTINF:%u,%u\n", _omvs_m3u_idx, _omvs_m3u_idx);
|
||||||
|
if (_omvs_udp_scan) {
|
||||||
|
fprintf(_omvs_m3u_fp, "udp://%s:%u\n", addr_str, o_ipaddr->ports[j]);
|
||||||
|
} else {
|
||||||
|
fprintf(_omvs_m3u_fp, "rtp://%s:%u\n", addr_str, o_ipaddr->ports[j]);
|
||||||
|
}
|
||||||
|
fflush(_omvs_m3u_fp);
|
||||||
|
g_mutex_unlock(&_omvs_mutex);
|
||||||
|
}
|
||||||
|
g_free(filename);
|
||||||
|
}
|
||||||
|
g_free(o_ipaddr->ports);
|
||||||
|
|
||||||
if (!_omvs_quiet) {
|
if (!_omvs_quiet) {
|
||||||
g_print("[%p] finish scanning %s\n", (void *)g_thread_self(), addr_str);
|
g_print("[%p] finish scanning %s\n", (void *)g_thread_self(), addr_str);
|
||||||
@ -392,6 +446,175 @@ static gint _omvs_start_scan(OMVSScanner *scanner) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint _omvs_wait_for_multicast_packet(void) {
|
||||||
|
pcap_t *pcap;
|
||||||
|
gchar errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
const guint8 *packet;
|
||||||
|
struct pcap_pkthdr *header;
|
||||||
|
GHashTable *urihashtable;
|
||||||
|
gint64 time1, time2;
|
||||||
|
OMVSGst gst;
|
||||||
|
gchar *cur_uri;
|
||||||
|
gchar *cur_addr_str;
|
||||||
|
gint udp_port;
|
||||||
|
|
||||||
|
pcap = pcap_open_live(_omvs_net_dev_names[_omvs_net_dev_idx],
|
||||||
|
sizeof(OMVSEthHdr) + sizeof(OMVSIPHdr) + sizeof(OMVSUDPHdr),
|
||||||
|
TRUE, 500, errbuf);
|
||||||
|
if (pcap == NULL) {
|
||||||
|
g_printerr("[%p] can't open pcap: %s\n", (void *)g_thread_self(), errbuf);
|
||||||
|
goto finish_return2;
|
||||||
|
}
|
||||||
|
if (pcap_datalink(pcap) != DLT_EN10MB) {
|
||||||
|
g_printerr("[%p] %s is not ethernet\n", (void *)g_thread_self(),
|
||||||
|
_omvs_net_dev_names[_omvs_net_dev_idx]);
|
||||||
|
goto finish_return3;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst = NULL;
|
||||||
|
cur_uri = NULL;
|
||||||
|
cur_addr_str = NULL;
|
||||||
|
urihashtable =
|
||||||
|
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
time1 = g_get_monotonic_time();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
gint ret;
|
||||||
|
guint caplen;
|
||||||
|
OMVSIPHdr *ip;
|
||||||
|
OMVSUDPHdr *udp;
|
||||||
|
guint ip_hdr_len;
|
||||||
|
GInetAddress *addr;
|
||||||
|
gchar *addr_str;
|
||||||
|
guint32 haddr;
|
||||||
|
gchar *uri;
|
||||||
|
gchar *filename;
|
||||||
|
|
||||||
|
ret = pcap_next_ex(pcap, &header, &packet);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gst) {
|
||||||
|
time2 = g_get_monotonic_time();
|
||||||
|
if (omvs_gst_is_finished(gst) ||
|
||||||
|
time2 - time1 > (gint64)((gint64)_omvs_timeout * 1000)) {
|
||||||
|
if (!_omvs_quiet) {
|
||||||
|
g_print("[%p] finish scanning %s\n", (void *)g_thread_self(),
|
||||||
|
cur_addr_str);
|
||||||
|
}
|
||||||
|
omvs_gst_close(gst);
|
||||||
|
gst = NULL;
|
||||||
|
filename = g_strdup_printf("%s/%s-%d.png", _omvs_outdir, cur_addr_str,
|
||||||
|
udp_port);
|
||||||
|
if (g_access(filename, F_OK) == 0) {
|
||||||
|
_omvs_m3u_idx++;
|
||||||
|
g_mutex_lock(&_omvs_mutex);
|
||||||
|
fprintf(_omvs_m3u_fp, "#EXTINF:%u,%u\n", _omvs_m3u_idx,
|
||||||
|
_omvs_m3u_idx);
|
||||||
|
fprintf(_omvs_m3u_fp, "%s\n", cur_uri);
|
||||||
|
fflush(_omvs_m3u_fp);
|
||||||
|
g_mutex_unlock(&_omvs_mutex);
|
||||||
|
}
|
||||||
|
g_free(filename);
|
||||||
|
g_free(cur_uri);
|
||||||
|
g_free(cur_addr_str);
|
||||||
|
cur_uri = NULL;
|
||||||
|
cur_addr_str = NULL;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
caplen = header->caplen;
|
||||||
|
|
||||||
|
if (caplen < sizeof(OMVSEthHdr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet += sizeof(OMVSEthHdr);
|
||||||
|
caplen -= sizeof(OMVSEthHdr);
|
||||||
|
if (caplen < sizeof(OMVSIPHdr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = (OMVSIPHdr *)packet;
|
||||||
|
ip_hdr_len = (ip->vhl & 0x0f) * 4;
|
||||||
|
if (caplen < ip_hdr_len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip->protocol != _OMVS_IPPROTO_UDP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = g_inet_address_new_from_bytes(
|
||||||
|
(const guint8 *)&ip->daddr, G_SOCKET_FAMILY_IPV4);
|
||||||
|
if (!g_inet_address_get_is_multicast(addr)) {
|
||||||
|
g_object_unref(addr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_object_unref(addr);
|
||||||
|
|
||||||
|
packet += ip_hdr_len;
|
||||||
|
caplen -= ip_hdr_len;
|
||||||
|
|
||||||
|
if (caplen < sizeof(OMVSUDPHdr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
udp = (OMVSUDPHdr *)packet;
|
||||||
|
udp_port = g_ntohs(udp->uh_dport);
|
||||||
|
|
||||||
|
haddr = g_ntohl(ip->daddr);
|
||||||
|
addr_str = g_strdup_printf("%u.%u.%u.%u",
|
||||||
|
(haddr >> 24) & 0xff,
|
||||||
|
(haddr >> 16) & 0xff,
|
||||||
|
(haddr >> 8) & 0xff,
|
||||||
|
(haddr >> 0) & 0xff);
|
||||||
|
if (_omvs_udp_scan) {
|
||||||
|
uri = g_strdup_printf("udp://%s:%u", addr_str, udp_port);
|
||||||
|
} else {
|
||||||
|
uri = g_strdup_printf("rtp://%s:%u", addr_str, udp_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_hash_table_replace(urihashtable, uri, addr_str)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert(cur_uri == NULL);
|
||||||
|
cur_uri = g_strdup(uri);
|
||||||
|
g_assert(cur_addr_str == NULL);
|
||||||
|
cur_addr_str = g_strdup(addr_str);
|
||||||
|
filename =
|
||||||
|
g_strdup_printf("%s/%s-%d.png", _omvs_outdir, cur_addr_str, udp_port);
|
||||||
|
if (!_omvs_quiet) {
|
||||||
|
g_print("[%p] start scanning %s\n", (void *)g_thread_self(),
|
||||||
|
cur_addr_str);
|
||||||
|
g_print("[%p] trying to save %s to %s\n", (void *)g_thread_self(),
|
||||||
|
cur_uri, filename);
|
||||||
|
}
|
||||||
|
time1 = g_get_monotonic_time();
|
||||||
|
g_assert(gst == NULL);
|
||||||
|
gst = omvs_gst_open(cur_uri, filename);
|
||||||
|
g_free(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy(urihashtable);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
finish_return3:
|
||||||
|
pcap_close(pcap);
|
||||||
|
finish_return2:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
@ -400,6 +623,8 @@ int main(int argc, char *argv[]) {
|
|||||||
gint num_ipaddrs;
|
gint num_ipaddrs;
|
||||||
gint idx_ipaddr;
|
gint idx_ipaddr;
|
||||||
OMVSScanner omvs_scanner;
|
OMVSScanner omvs_scanner;
|
||||||
|
gchar *m3u_path;
|
||||||
|
gint64 time;
|
||||||
|
|
||||||
if (_omvs_init_net_devs_info() != 0) {
|
if (_omvs_init_net_devs_info() != 0) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -428,16 +653,38 @@ int main(int argc, char *argv[]) {
|
|||||||
goto finish_return;
|
goto finish_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 2 || _omvs_net_dev_idx >= _omvs_num_net_devs) {
|
if ((!_omvs_wait && argc < 2) || _omvs_net_dev_idx >= _omvs_num_net_devs) {
|
||||||
gchar *help_msg;
|
gchar *help_msg;
|
||||||
help_msg = g_option_context_get_help(context, TRUE, NULL);
|
help_msg = g_option_context_get_help(context, TRUE, NULL);
|
||||||
g_print("%s", help_msg);
|
g_print("%s", help_msg);
|
||||||
g_free(help_msg);
|
g_free(help_msg);
|
||||||
ret = -2;
|
ret = -6;
|
||||||
goto finish_return;
|
goto finish_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
omvs_gst_plugin_register();
|
||||||
|
|
||||||
g_mkdir(_omvs_outdir, 0755);
|
g_mkdir(_omvs_outdir, 0755);
|
||||||
|
time = g_get_real_time();
|
||||||
|
m3u_path = g_strdup_printf("%s/omvs_%" G_GUINT64_FORMAT ".m3u", _omvs_outdir,
|
||||||
|
time);
|
||||||
|
if (!_omvs_quiet) {
|
||||||
|
g_print("openning %s\n", m3u_path);
|
||||||
|
}
|
||||||
|
_omvs_m3u_fp = fopen(m3u_path, "w");
|
||||||
|
if (_omvs_m3u_fp == NULL) {
|
||||||
|
g_print("can't create %s\n", m3u_path);
|
||||||
|
g_free(m3u_path);
|
||||||
|
ret = -7;
|
||||||
|
goto finish_return;
|
||||||
|
}
|
||||||
|
g_free(m3u_path);
|
||||||
|
fprintf(_omvs_m3u_fp, "#EXTM3U\n");
|
||||||
|
|
||||||
|
if (_omvs_wait) {
|
||||||
|
_omvs_wait_for_multicast_packet();
|
||||||
|
goto finish_return;
|
||||||
|
}
|
||||||
|
|
||||||
num_ipaddrs = 0;
|
num_ipaddrs = 0;
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
@ -514,6 +761,9 @@ int main(int argc, char *argv[]) {
|
|||||||
finish_return:
|
finish_return:
|
||||||
g_option_context_free(context);
|
g_option_context_free(context);
|
||||||
_omvs_deinit_net_devs_info();
|
_omvs_deinit_net_devs_info();
|
||||||
|
if (_omvs_m3u_fp) {
|
||||||
|
fclose(_omvs_m3u_fp);
|
||||||
|
}
|
||||||
finish_return2:
|
finish_return2:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user