diff --git a/Makefile.am b/Makefile.am
index 17a124f..97102d4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,13 @@
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 += -std=gnu99 -W -Wall -Wno-unused-result -pedantic
omvs_LDADD = $(GLIB_LIBS) $(GIO_LIBS) $(GSTREAMER_LIBS)
-ACLOCAL_AMFLAGS= -I m4
+ACLOCAL_AMFLAGS = -I m4
diff --git a/Makefile.in b/Makefile.in
index d5c14c1..9f963f3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -100,7 +100,9 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
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)
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_builddir = @top_builddir@
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) \
-std=gnu99 -W -Wall -Wno-unused-result -pedantic
omvs_LDADD = $(GLIB_LIBS) $(GIO_LIBS) $(GSTREAMER_LIBS)
@@ -436,6 +446,8 @@ distclean-compile:
-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_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@
.c.o:
@@ -487,6 +499,34 @@ omvs-omvs_gst.obj: omvs_gst.c
@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`
+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:
-rm -f *.lo
diff --git a/omvs_gst.c b/omvs_gst.c
index 8eb2328..4cc5d26 100644
--- a/omvs_gst.c
+++ b/omvs_gst.c
@@ -18,6 +18,7 @@
along with this program. If not, see .
*/
+#include
#include
#include "omvs_gst.h"
@@ -29,6 +30,9 @@ typedef struct _OMVSGstImpl {
OMVSGst omvs_gst_open(const gchar *uri, const gchar *filename) {
guint flags;
OMVSGstImpl *gst_impl;
+ gchar *protocol;
+ gchar *location;
+ gchar *real_uri;
GstElement *play;
GstElement *conv;
GstElement *png;
@@ -37,9 +41,34 @@ OMVSGst omvs_gst_open(const gchar *uri, const gchar *filename) {
GstPad *pad;
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->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);
flags &= (~0x00000002);
g_object_set(play, "flags", flags, NULL);
diff --git a/omvs_gst_plugin.c b/omvs_gst_plugin.c
new file mode 100644
index 0000000..d68ef91
--- /dev/null
+++ b/omvs_gst_plugin.c
@@ -0,0 +1,53 @@
+/*
+ Oh! Multicast Video Scanner
+ Copyright (C) 2016 Taeho Oh
+
+ 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 .
+*/
+
+#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, omvprtp,
+ "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
diff --git a/omvs_gst_plugin.h b/omvs_gst_plugin.h
new file mode 100644
index 0000000..6c7417f
--- /dev/null
+++ b/omvs_gst_plugin.h
@@ -0,0 +1,28 @@
+/*
+ Oh! Multicast Video Scanner
+ Copyright (C) 2016 Taeho Oh
+
+ 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 .
+*/
+
+#ifndef _OMVS_GST_PLUGIN_H_
+#define _OMVS_GST_PLUGIN_H_
+
+#include
+
+extern gboolean omvs_gst_plugin_register(void);
+
+#endif /* _OMVS_GST_PLUGIN_H_ */
diff --git a/omvs_gst_plugin_rtpsrc.c b/omvs_gst_plugin_rtpsrc.c
new file mode 100644
index 0000000..01bbb64
--- /dev/null
+++ b/omvs_gst_plugin_rtpsrc.c
@@ -0,0 +1,398 @@
+/*
+ Oh! Multicast Video Scanner
+ Copyright (C) 2016 Taeho Oh
+
+ 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 .
+*/
+
+#include
+#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 ");
+
+ 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;
+}
diff --git a/omvs_gst_plugin_rtpsrc.h b/omvs_gst_plugin_rtpsrc.h
new file mode 100644
index 0000000..b5ec75f
--- /dev/null
+++ b/omvs_gst_plugin_rtpsrc.h
@@ -0,0 +1,58 @@
+/*
+ Oh! Multicast Video Scanner
+ Copyright (C) 2016 Taeho Oh
+
+ 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 .
+*/
+
+#ifndef _OMVS_GST_PLUGIN_RTPSRC_H_
+#define _OMVS_GST_PLUGIN_RTPSRC_H_
+
+#include
+
+#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_ */
diff --git a/omvs_main.c b/omvs_main.c
index 2ae6a29..3382a82 100644
--- a/omvs_main.c
+++ b/omvs_main.c
@@ -27,6 +27,7 @@
#include "config.h"
#include "omvs_gst.h"
+#include "omvs_gst_plugin.h"
#define _OMVS_IPPROTO_UDP 17
@@ -308,7 +309,7 @@ static gpointer _omvs_start_scan_job(gpointer data) {
if (!is_udp_port_found) {
gchar *uri;
gchar *filename;
- uri = g_strdup_printf("udp://%s:%d", addr_str, udp_port);
+ uri = g_strdup_printf("rtp://%s:%d", addr_str, udp_port);
filename =
g_strdup_printf("%s/%s-%d.png", _omvs_outdir, addr_str, udp_port);
if (!_omvs_quiet) {
@@ -533,7 +534,7 @@ static gint _omvs_wait_for_multicast_packet(void) {
(haddr >> 16) & 0xff,
(haddr >> 8) & 0xff,
(haddr >> 0) & 0xff);
- uri = g_strdup_printf("udp://%s:%u", addr_str, udp_port);
+ uri = g_strdup_printf("rtp://%s:%u", addr_str, udp_port);
filename =
g_strdup_printf("%s/%s-%d.png", _omvs_outdir, addr_str, udp_port);
g_free(addr_str);
@@ -609,6 +610,8 @@ int main(int argc, char *argv[]) {
goto finish_return;
}
+ omvs_gst_plugin_register();
+
g_mkdir(_omvs_outdir, 0755);
if (_omvs_wait) {