rtpbin: receive bundle support
[platform/upstream/gst-plugins-good.git] / tests / examples / rtp / server-rtpbundle.c
1 /* GStreamer
2  * Copyright (C) 2016 Igalia S.L
3  *   @author Philippe Normand <philn@igalia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 #include <gst/gst.h>
21
22 /*
23  * An bundling RTP server
24  *  creates two sessions and streams audio on one, video on the other, with RTCP
25  *  on both sessions. The destination is 127.0.0.1.
26  *
27  *  The RTP streams are bundled to a single outgoing connection. Same for the RTCP streams.
28  *
29  *  .-------.    .-------.    .-------.      .------------.         .------.
30  *  |audiots|    |alawenc|    |pcmapay|      | rtpbin     |         |funnel|
31  *  |      src->sink    src->sink    src->send_rtp_0 send_rtp_0--->sink_0  |    .-------.
32  *  '-------'    '-------'    '-------'      |            |         |      |    |udpsink|
33  *                                           |            |         |     src->sink     |
34  *  .-------.               .---------.      |            |         |      |    '-------'
35  *  |videots|               | vrawpay |      |            |         |      |
36  *  |      src------------>sink      src->send_rtp_1 send_rtp_1--->sink_1  |
37  *  '-------'               '---------'      |            |         '------'
38  *                                           |            |
39  *                               .------.    |            |
40  *                               |udpsrc|    |            |         .------.
41  *                               |     src->recv_rtcp_0   |         |funnel|
42  *                               '------'    |       send_rtcp_0-->sink_0  |   .-------.
43  *                                           |            |         |      |   |udpsink|
44  *                               .------.    |            |         |    src->sink     |
45  *                               |udpsrc|    |            |         |      |   '-------'
46  *                               |     src->recv_rtcp_1   |         |      |
47  *                               '------'    |       send_rtcp_1-->sink_1  |
48  *                                           '------------'         '------'
49  *
50  */
51
52 static GstElement *
53 create_pipeline (void)
54 {
55   GstElement *pipeline, *rtpbin, *audiosrc, *audio_encoder,
56       *audio_rtppayloader, *sendrtp_udpsink,
57       *send_rtcp_udpsink, *sendrtcp_funnel, *sendrtp_funnel;
58   GstElement *videosrc, *video_rtppayloader, *time_overlay;
59   gint rtp_udp_port = 5001;
60   gint rtcp_udp_port = 5002;
61   gint recv_audio_rtcp_port = 5003;
62   gint recv_video_rtcp_port = 5004;
63   GstElement *audio_rtcp_udpsrc, *video_rtcp_udpsrc;
64
65   pipeline = gst_pipeline_new (NULL);
66
67   rtpbin = gst_element_factory_make ("rtpbin", NULL);
68
69   audiosrc = gst_element_factory_make ("audiotestsrc", NULL);
70   g_object_set (audiosrc, "is-live", TRUE, NULL);
71   audio_encoder = gst_element_factory_make ("alawenc", NULL);
72   audio_rtppayloader = gst_element_factory_make ("rtppcmapay", NULL);
73   g_object_set (audio_rtppayloader, "pt", 96, NULL);
74
75   videosrc = gst_element_factory_make ("videotestsrc", NULL);
76   g_object_set (videosrc, "is-live", TRUE, NULL);
77   time_overlay = gst_element_factory_make ("timeoverlay", NULL);
78   video_rtppayloader = gst_element_factory_make ("rtpvrawpay", NULL);
79   g_object_set (video_rtppayloader, "pt", 100, NULL);
80
81   /* muxed rtcp */
82   sendrtcp_funnel = gst_element_factory_make ("funnel", "send_rtcp_funnel");
83   send_rtcp_udpsink = gst_element_factory_make ("udpsink", NULL);
84   g_object_set (send_rtcp_udpsink, "host", "127.0.0.1", NULL);
85   g_object_set (send_rtcp_udpsink, "port", rtcp_udp_port, NULL);
86   g_object_set (send_rtcp_udpsink, "sync", FALSE, NULL);
87   g_object_set (send_rtcp_udpsink, "async", FALSE, NULL);
88
89   /* outgoing bundled stream */
90   sendrtp_funnel = gst_element_factory_make ("funnel", "send_rtp_funnel");
91   sendrtp_udpsink = gst_element_factory_make ("udpsink", NULL);
92   g_object_set (sendrtp_udpsink, "host", "127.0.0.1", NULL);
93   g_object_set (sendrtp_udpsink, "port", rtp_udp_port, NULL);
94   g_object_set (sendrtp_udpsink, "sync", FALSE, NULL);
95   g_object_set (sendrtp_udpsink, "async", FALSE, NULL);
96
97   gst_bin_add_many (GST_BIN (pipeline), rtpbin, audiosrc, audio_encoder,
98       audio_rtppayloader, sendrtp_udpsink, send_rtcp_udpsink,
99       sendrtp_funnel, sendrtcp_funnel, videosrc, video_rtppayloader, NULL);
100
101   if (time_overlay)
102     gst_bin_add (GST_BIN (pipeline), time_overlay);
103
104   gst_element_link_many (audiosrc, audio_encoder, audio_rtppayloader, NULL);
105   gst_element_link_pads (audio_rtppayloader, "src", rtpbin, "send_rtp_sink_0");
106
107   if (time_overlay) {
108     gst_element_link_many (videosrc, time_overlay, video_rtppayloader, NULL);
109   } else {
110     gst_element_link (videosrc, video_rtppayloader);
111   }
112
113   gst_element_link_pads (video_rtppayloader, "src", rtpbin, "send_rtp_sink_1");
114
115   gst_element_link_pads (sendrtp_funnel, "src", sendrtp_udpsink, "sink");
116   gst_element_link_pads (rtpbin, "send_rtp_src_0", sendrtp_funnel, "sink_%u");
117   gst_element_link_pads (rtpbin, "send_rtp_src_1", sendrtp_funnel, "sink_%u");
118   gst_element_link_pads (sendrtcp_funnel, "src", send_rtcp_udpsink, "sink");
119   gst_element_link_pads (rtpbin, "send_rtcp_src_0", sendrtcp_funnel, "sink_%u");
120   gst_element_link_pads (rtpbin, "send_rtcp_src_1", sendrtcp_funnel, "sink_%u");
121
122   audio_rtcp_udpsrc = gst_element_factory_make ("udpsrc", NULL);
123   g_object_set (audio_rtcp_udpsrc, "port", recv_audio_rtcp_port, NULL);
124   video_rtcp_udpsrc = gst_element_factory_make ("udpsrc", NULL);
125   g_object_set (video_rtcp_udpsrc, "port", recv_video_rtcp_port, NULL);
126   gst_bin_add_many (GST_BIN (pipeline), audio_rtcp_udpsrc, video_rtcp_udpsrc,
127       NULL);
128   gst_element_link_pads (audio_rtcp_udpsrc, "src", rtpbin, "recv_rtcp_sink_0");
129   gst_element_link_pads (video_rtcp_udpsrc, "src", rtpbin, "recv_rtcp_sink_1");
130
131   return pipeline;
132 }
133
134 /*
135  * Used to generate informative messages during pipeline startup
136  */
137 static void
138 cb_state (GstBus * bus, GstMessage * message, gpointer data)
139 {
140   GstObject *pipe = GST_OBJECT (data);
141   GstState old, new, pending;
142   gst_message_parse_state_changed (message, &old, &new, &pending);
143   if (message->src == pipe) {
144     g_print ("Pipeline %s changed state from %s to %s\n",
145         GST_OBJECT_NAME (message->src),
146         gst_element_state_get_name (old), gst_element_state_get_name (new));
147   }
148 }
149
150 int
151 main (int argc, char **argv)
152 {
153   GstElement *pipe;
154   GstBus *bus;
155   GMainLoop *loop;
156
157   gst_init (&argc, &argv);
158
159   loop = g_main_loop_new (NULL, FALSE);
160
161   pipe = create_pipeline ();
162   bus = gst_element_get_bus (pipe);
163   g_signal_connect (bus, "message::state-changed", G_CALLBACK (cb_state), pipe);
164   gst_bus_add_signal_watch (bus);
165   gst_object_unref (bus);
166
167   g_print ("starting server pipeline\n");
168   gst_element_set_state (pipe, GST_STATE_PLAYING);
169
170   g_main_loop_run (loop);
171
172   g_print ("stopping server pipeline\n");
173   gst_element_set_state (pipe, GST_STATE_NULL);
174
175   gst_object_unref (pipe);
176   g_main_loop_unref (loop);
177
178   return 0;
179 }