summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2014-10-03 00:35:36 +0200
committerChristian Pointner <equinox@spreadspace.org>2014-10-03 00:35:36 +0200
commit22faabe30c07598d0c3aeaed3b861d8f94e6ac0f (patch)
tree212ea1447ac05bcbe98b4d75234e05ef4a8f9031
parentbetter distinction between sydra and sydra-rtp (diff)
reflector works now
-rw-r--r--src/options.c17
-rw-r--r--src/options.h2
-rw-r--r--src/pipelines.c129
3 files changed, 120 insertions, 28 deletions
diff --git a/src/options.c b/src/options.c
index e6101aa..7d03d1d 100644
--- a/src/options.c
+++ b/src/options.c
@@ -81,6 +81,8 @@ static void options_defaults(options_t* opt)
opt->rtp_port_base_ = 5000;
opt->rtp_addr_local_ = NULL;
opt->rtp_port_base_local_ = 5000;
+ opt->rtp_host_reflector_ = NULL;
+ opt->rtp_port_base_reflector_ = 6000;
opt->auto_client_ = TRUE;
opt->timeout_ = 30;
opt->keepalive_int_ = 10;
@@ -165,6 +167,10 @@ static GOptionGroup* options_get_rtp_group(options_t* opt)
"local address to bind to", "ADDRESS" },
{ "rtp-port-base-local", 'O', 0, G_OPTION_ARG_INT, &opt->rtp_port_base_local_,
"base number for local ports to bind to", "PORT" },
+ { "rtp-host-reflector", 0, 0, G_OPTION_ARG_STRING, &opt->rtp_host_reflector_,
+ "remote host where incoming RTP packets should be reflected to - receiver mode only!", "HOST" },
+ { "rtp-port-base-reflector", 0, 0, G_OPTION_ARG_INT, &opt->rtp_port_base_reflector_,
+ "base number for ports where incoming RTP packets should be reflected to - receiver mode only!", "PORT" },
{ "no-auto-client", 'c', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt->auto_client_,
"disable auto-detection for clients (aka. ignore incoming keepalives) - sender mode only!", NULL },
{ "timeout", 't', 0, G_OPTION_ARG_INT, &opt->timeout_,
@@ -294,7 +300,8 @@ int options_parse(options_t* opt, int argc, char* argv[])
static int options_parse_post(options_t* opt)
{
if(opt->rtp_port_base_ < 1 || opt->rtp_port_base_ > 65535 ||
- opt->rtp_port_base_local_ < 1 || opt->rtp_port_base_local_ > 65535) {
+ opt->rtp_port_base_local_ < 1 || opt->rtp_port_base_local_ > 65535 ||
+ opt->rtp_port_base_reflector_ < 1 || opt->rtp_port_base_reflector_ > 65535) {
printf("ERROR: Failed to initialize: rtp port is invalid\n");
return -2;
}
@@ -321,6 +328,11 @@ static int options_parse_post(options_t* opt)
" not what you intended - please check your configuration.\n\n");
}
+ if(opt->mode_ == SENDER && opt->rtp_host_reflector_) {
+ printf("WARNING: The mode of operation is set to sender and the RTP packet reflector has a remote\n" \
+ " host configured. Mind that in sender mode the reflector will not be used!\n\n");
+ }
+
if(opt->debug_) {
opt->daemonize_ = 0;
g_strfreev(opt->log_targets_);
@@ -368,6 +380,7 @@ void options_clear(options_t* opt)
g_free(opt->audio_dec_);
g_free(opt->rtp_host_);
g_free(opt->rtp_addr_local_);
+ g_free(opt->rtp_host_reflector_);
g_free(opt->preview_videosink_);
g_free(opt->video_enc_rec_);
g_free(opt->audio_enc_rec_);
@@ -433,6 +446,8 @@ void options_print(options_t* opt)
printf(" rtp_port_base: %d\n", opt->rtp_port_base_);
printf(" rtp_addr_local: >>%s<<\n", opt->rtp_addr_local_);
printf(" rtp_port_base_local: %d\n", opt->rtp_port_base_local_);
+ printf(" rtp_host_reflector: >>%s<<\n", opt->rtp_host_reflector_);
+ printf(" rtp_port_base_reflector: %d\n", opt->rtp_port_base_reflector_);
printf(" auto_client: %s\n", opt->auto_client_ ? "true" : "false");
printf(" timeout: %d\n", opt->timeout_);
printf(" keepalive_int: %d\n", opt->keepalive_int_);
diff --git a/src/options.h b/src/options.h
index 1f93360..d7f7daf 100644
--- a/src/options.h
+++ b/src/options.h
@@ -69,6 +69,8 @@ struct options_struct {
gint rtp_port_base_;
gchar* rtp_addr_local_;
gint rtp_port_base_local_;
+ gchar* rtp_host_reflector_;
+ gint rtp_port_base_reflector_;
gboolean auto_client_;
gint timeout_;
gint keepalive_int_;
diff --git a/src/pipelines.c b/src/pipelines.c
index cc0c44c..c8eae3e 100644
--- a/src/pipelines.c
+++ b/src/pipelines.c
@@ -100,7 +100,7 @@ static gboolean create_avsend_elements(struct av_elements *ave, GstElement* pipe
return FALSE;
}
- log_printf(DEBUG, "%s path created successfully!", ave->name_);
+ log_printf(INFO, "%s path created successfully!", ave->name_);
gst_bin_add_many(GST_BIN(pipeline), ave->tee_raw_, qr, ave->encdec_, ave->tee_enc_, qe, ave->payloader_, NULL);
if(!sydra_link_static_static(ave->srcsink_, ave->name_, ave->tee_raw_, "sink")) return FALSE;
@@ -115,7 +115,7 @@ static gboolean create_avsend_elements(struct av_elements *ave, GstElement* pipe
return FALSE;
}
- log_printf(DEBUG, "%s path linked successfully!", ave->name_);
+ log_printf(INFO, "%s path linked successfully!", ave->name_);
return TRUE;
}
@@ -162,13 +162,13 @@ static gboolean create_avrecv_elements(struct av_elements *ave, GstElement* pipe
return FALSE;
}
- log_printf(DEBUG, "%s path created successfully!", ave->name_);
+ log_printf(INFO, "%s path created successfully!", ave->name_);
gst_bin_add_many (GST_BIN(pipeline), ave->tee_raw_, qr, ave->encdec_, ave->tee_enc_, qe, ave->payloader_, NULL);
gst_element_link_many(ave->payloader_, ave->tee_enc_, qe, ave->encdec_, ave->tee_raw_, qr, NULL);
if(!sydra_link_static_static(qr, "src", ave->srcsink_, ave->name_)) return FALSE;
- log_printf(DEBUG, "%s path linked successfully!", ave->name_);
+ log_printf(INFO, "%s path linked successfully!", ave->name_);
return TRUE;
}
@@ -182,7 +182,7 @@ static gboolean create_udp_sinks(options_t* opt, GstElement* pipeline, GstElemen
if(!(sinks->rtp_video_.udp_) || !(sinks->rtcp_video_.udp_) || !(sinks->rtp_audio_.udp_) || !(sinks->rtcp_audio_.udp_))
return FALSE;
- log_printf(DEBUG, "udp sinks created successfully!");
+ log_printf(INFO, "udp sinks created successfully!");
int rtp_port_local = opt->rtp_port_base_local_;
g_object_set(G_OBJECT(sinks->rtp_video_.udp_), "bind-port", rtp_port_local++, NULL);
@@ -204,7 +204,7 @@ static gboolean create_udp_sinks(options_t* opt, GstElement* pipeline, GstElemen
g_object_set(G_OBJECT(sinks->rtcp_audio_.udp_), "bind-address", opt->rtp_addr_local_, NULL);
}
- log_printf(DEBUG, "udp sinks configured successfully!");
+ log_printf(INFO, "udp sinks configured successfully!");
gst_bin_add_many(GST_BIN(pipeline), sinks->rtp_video_.udp_, sinks->rtcp_video_.udp_, sinks->rtp_audio_.udp_, sinks->rtcp_audio_.udp_, NULL);
@@ -214,22 +214,83 @@ static gboolean create_udp_sinks(options_t* opt, GstElement* pipeline, GstElemen
!sydra_link_request_static(rtp, "send_rtcp_src_1", sinks->rtcp_audio_.udp_, "sink"))
return FALSE;
- log_printf(DEBUG, "udp sinks linked successfully!");
+ log_printf(INFO, "udp sinks linked successfully!");
+
+ return TRUE;
+}
+
+struct udpsrc_tees {
+ GstElement* rtpv_;
+ GstElement* rtcpv_;
+ GstElement* rtpa_;
+ GstElement* rtcpa_;
+};
+
+static gboolean create_rtp_reflector(options_t* opt, GstElement* pipeline, struct udpsrc_tees *tees)
+{
+ GstElement* rtp_video = sydra_create_element("udpsink", "udprtpvref");
+ GstElement* qrtpv = sydra_create_element("queue", NULL);
+ GstElement* rtcp_video = sydra_create_element("udpsink", "udprtcpvref");
+ GstElement* qrtcpv = sydra_create_element("queue", NULL);
+ GstElement* rtp_audio = sydra_create_element("udpsink", "udprtparef");
+ GstElement* qrtpa = sydra_create_element("queue", NULL);
+ GstElement* rtcp_audio = sydra_create_element("udpsink", "udprtcparef");
+ GstElement* qrtcpa = sydra_create_element("queue", NULL);
+
+ if(!rtp_video || !rtcp_video || !rtp_audio || !rtcp_audio || !qrtpv || !qrtcpv || !qrtpa || !qrtcpa)
+ return FALSE;
+
+ log_printf(INFO, "udp reflector sinks created successfully!");
+
+ int rtp_port_reflector = opt->rtp_port_base_reflector_;
+ g_object_set(G_OBJECT(rtp_video), "host", opt->rtp_host_reflector_, "port", rtp_port_reflector++, "sync", FALSE, NULL);
+ g_object_set(G_OBJECT(rtcp_video), "host", opt->rtp_host_reflector_, "port", rtp_port_reflector++, "sync", FALSE, NULL);
+ g_object_set(G_OBJECT(rtp_audio), "host", opt->rtp_host_reflector_, "port", rtp_port_reflector++, "sync", FALSE, NULL);
+ g_object_set(G_OBJECT(rtcp_audio), "host", opt->rtp_host_reflector_, "port", rtp_port_reflector++, "sync", FALSE, NULL);
+
+ log_printf(INFO, "udp reflector sinks configured successfully!");
+
+ gst_bin_add_many(GST_BIN(pipeline), rtp_video, rtcp_video, rtp_audio, rtcp_audio, NULL);
+ gst_bin_add_many(GST_BIN(pipeline), qrtpv, qrtcpv, qrtpa, qrtcpa, NULL);
+
+ gst_element_link(qrtpv, rtp_video);
+ gst_element_link(qrtcpv, rtcp_video);
+ gst_element_link(qrtpa, rtp_audio);
+ gst_element_link(qrtcpa, rtcp_audio);
+
+ if(!sydra_link_request_static(tees->rtpv_, "src_%u", qrtpv, "sink") ||
+ !sydra_link_request_static(tees->rtcpv_, "src_%u", qrtcpv, "sink") ||
+ !sydra_link_request_static(tees->rtpa_, "src_%u", qrtpa, "sink") ||
+ !sydra_link_request_static(tees->rtcpa_, "src_%u", qrtcpa, "sink"))
+ return FALSE;
+
+ log_printf(INFO, "udp reflector sinks linked successfully!");
return TRUE;
}
static gboolean create_udp_sources(options_t* opt, GstElement* pipeline, GstElement* rtp, struct udp_sources *sources)
{
+ struct udpsrc_tees tees;
+
sources->rtp_video_ = sydra_create_element("udpsrc", "udprtpv");
+ tees.rtpv_ = sydra_create_element("tee", "rtpvt");
+ GstElement* qrtpv = sydra_create_element("queue", NULL);
sources->rtcp_video_ = sydra_create_element("udpsrc", "udprtcpv");
+ tees.rtcpv_ = sydra_create_element("tee", "rtcpvt");
+ GstElement* qrtcpv = sydra_create_element("queue", NULL);
sources->rtp_audio_ = sydra_create_element("udpsrc", "udprtpa");
+ tees.rtpa_ = sydra_create_element("tee", "rtpat");
+ GstElement* qrtpa = sydra_create_element("queue", NULL);
sources->rtcp_audio_ = sydra_create_element("udpsrc", "udprtcpa");
+ tees.rtcpa_ = sydra_create_element("tee", "rtcpat");
+ GstElement* qrtcpa = sydra_create_element("queue", NULL);
- if(!(sources->rtp_video_) || !(sources->rtcp_video_) || !(sources->rtp_audio_) || !(sources->rtcp_audio_))
+ if(!(sources->rtp_video_) || !(sources->rtcp_video_) || !(sources->rtp_audio_) || !(sources->rtcp_audio_) ||
+ !(tees.rtpv_) || !(tees.rtcpv_) || !(tees.rtpa_) || !(tees.rtcpa_) || !qrtpv || !qrtcpv || !qrtpa || !qrtcpa)
return FALSE;
- log_printf(DEBUG, "udp sources created successfully!");
+ log_printf(INFO, "udp sources created successfully!");
GstCaps *video_caps = gst_caps_from_string(opt->video_caps_);
GstCaps *audio_caps = gst_caps_from_string(opt->audio_caps_);
@@ -252,17 +313,31 @@ static gboolean create_udp_sources(options_t* opt, GstElement* pipeline, GstElem
g_object_set(G_OBJECT(sources->rtcp_audio_), "address", opt->rtp_addr_local_, NULL);
}
- log_printf(DEBUG, "udp sources configured successfully!");
+ log_printf(INFO, "udp sources configured successfully!");
gst_bin_add_many(GST_BIN(pipeline), sources->rtp_video_, sources->rtcp_video_, sources->rtp_audio_, sources->rtcp_audio_, NULL);
-
- if(!sydra_link_static_request(sources->rtp_video_, "src", rtp, "recv_rtp_sink_0") ||
- !sydra_link_static_request(sources->rtcp_video_, "src", rtp, "recv_rtcp_sink_0") ||
- !sydra_link_static_request(sources->rtp_audio_, "src", rtp, "recv_rtp_sink_1") ||
- !sydra_link_static_request(sources->rtcp_audio_, "src", rtp, "recv_rtcp_sink_1"))
+ gst_bin_add_many(GST_BIN(pipeline), tees.rtpv_, tees.rtcpv_, tees.rtpa_, tees.rtcpa_, NULL);
+ gst_bin_add_many(GST_BIN(pipeline), qrtpv, qrtcpv, qrtpa, qrtcpa, NULL);
+
+ gst_element_link(sources->rtp_video_, tees.rtpv_);
+ gst_element_link(sources->rtcp_video_, tees.rtcpv_);
+ gst_element_link(sources->rtp_audio_, tees.rtpa_);
+ gst_element_link(sources->rtcp_audio_, tees.rtcpa_);
+
+ if(!sydra_link_request_static(tees.rtpv_, "src_%u", qrtpv, "sink") ||
+ !sydra_link_static_request(qrtpv, "src", rtp, "recv_rtp_sink_0") ||
+ !sydra_link_request_static(tees.rtcpv_, "src_%u", qrtcpv, "sink") ||
+ !sydra_link_static_request(qrtcpv, "src", rtp, "recv_rtcp_sink_0") ||
+ !sydra_link_request_static(tees.rtpa_, "src_%u", qrtpa, "sink") ||
+ !sydra_link_static_request(qrtpa, "src", rtp, "recv_rtp_sink_1") ||
+ !sydra_link_request_static(tees.rtcpa_, "src_%u", qrtcpa, "sink") ||
+ !sydra_link_static_request(qrtcpa, "src", rtp, "recv_rtcp_sink_1"))
return FALSE;
- log_printf(DEBUG, "udp sources linked successfully!");
+ log_printf(INFO, "udp sources linked successfully!");
+
+ if(opt->rtp_host_reflector_)
+ return create_rtp_reflector(opt, pipeline, &tees);
return TRUE;
}
@@ -276,7 +351,7 @@ static gboolean create_preview_elements(const char* preview_bin_desc, GstElement
return FALSE;
}
- log_printf(DEBUG, "preview path created successfully!");
+ log_printf(INFO, "preview path created successfully!");
gst_bin_add_many (GST_BIN(pipeline), qr, preview_bin, NULL);
gst_element_link(qr, preview_bin);
@@ -285,7 +360,7 @@ static gboolean create_preview_elements(const char* preview_bin_desc, GstElement
return FALSE;
}
- log_printf(DEBUG, "preview path linked successfully!");
+ log_printf(INFO, "preview path linked successfully!");
return TRUE;
}
@@ -313,7 +388,7 @@ static gboolean create_recorder_elements(options_t* opt, GstElement* pipeline, s
ta = ae->tee_raw_;
}
- log_printf(DEBUG, "recorder path created successfully!");
+ log_printf(INFO, "recorder path created successfully!");
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
@@ -346,7 +421,7 @@ static gboolean create_recorder_elements(options_t* opt, GstElement* pipeline, s
return FALSE;
}
- log_printf(DEBUG, "recorder path linked successfully!");
+ log_printf(INFO, "recorder path linked successfully!");
return TRUE;
}
@@ -359,11 +434,11 @@ GstElement* create_sender_pipeline(options_t* opt, struct udp_sinks *udp)
}
GstElement *rtp = sydra_create_element("rtpbin", "rtpbin");
if(!rtp || !gst_bin_add(GST_BIN(pipeline), rtp)) return NULL;
- log_printf(DEBUG, "rtpbin created successfully!");
+ log_printf(INFO, "rtpbin created successfully!");
GstElement* src = create_avsend_src(opt->source_, pipeline);
if(!src) return NULL;
- log_printf(DEBUG, "source bin created successfully!");
+ log_printf(INFO, "source bin created successfully!");
struct av_elements video = { "video", src, NULL, opt->video_enc_, NULL, NULL,
opt->video_payloader_, NULL };
@@ -385,7 +460,7 @@ GstElement* create_sender_pipeline(options_t* opt, struct udp_sinks *udp)
return NULL;
}
- log_printf(DEBUG, "sender pipeline created successfully!");
+ log_printf(INFO, "sender pipeline created successfully!");
return pipeline;
}
@@ -402,7 +477,7 @@ static void rtpbin_pad_added(GstElement* rtp, GstPad* pad, gpointer user_data)
gst_object_unref(GST_OBJECT(pad_template));
gchar* src_pad_name = gst_element_get_name(pad);
- log_printf(DEBUG, "rtpbin: new pad created %s", src_pad_name);
+ log_printf(INFO, "rtpbin: new pad created %s", src_pad_name);
guint i;
for(i = 0; i < 2; i++) {
@@ -442,11 +517,11 @@ GstElement* create_receiver_pipeline(options_t* opt, struct udp_sources *udp)
if(!rtp || !gst_bin_add(GST_BIN(pipeline), rtp)) {
return NULL;
}
- log_printf(DEBUG, "rtpbin created successfully!");
+ log_printf(INFO, "rtpbin created successfully!");
GstElement* sink = create_avrecv_sink(opt->sink_, pipeline);
if(!sink) return NULL;
- log_printf(DEBUG, "sink bin created successfully!");
+ log_printf(INFO, "sink bin created successfully!");
struct av_elements video = { "video", sink, NULL, opt->video_dec_, NULL, NULL,
opt->video_depayloader_, NULL };
@@ -467,6 +542,6 @@ GstElement* create_receiver_pipeline(options_t* opt, struct udp_sources *udp)
return NULL;
}
- log_printf(DEBUG, "receiver pipeline created successfully!");
+ log_printf(INFO, "receiver pipeline created successfully!");
return pipeline;
}