This URL has Read-Only access.

Statistics
| Branch: | Tag: | Revision:

root / src / libsharedvideo / data-writer-from-rtp-example.cpp @ c83c639e

History | View | Annotate | Download (9.1 kB)

1 2daccc89 Alexandre Quessy
/* GStreamer
2 2daccc89 Alexandre Quessy
 * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.com>
3 2daccc89 Alexandre Quessy
 *
4 2daccc89 Alexandre Quessy
 * This library is free software; you can redistribute it and/or
5 2daccc89 Alexandre Quessy
 * modify it under the terms of the GNU Library General Public
6 2daccc89 Alexandre Quessy
 * License as published by the Free Software Foundation; either
7 2daccc89 Alexandre Quessy
 * version 2 of the License, or (at your option) any later version.
8 2daccc89 Alexandre Quessy
 *
9 2daccc89 Alexandre Quessy
 * This library is distributed in the hope that it will be useful,
10 2daccc89 Alexandre Quessy
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 2daccc89 Alexandre Quessy
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 2daccc89 Alexandre Quessy
 * Library General Public License for more details.
13 2daccc89 Alexandre Quessy
 *
14 2daccc89 Alexandre Quessy
 * You should have received a copy of the GNU Library General Public
15 2daccc89 Alexandre Quessy
 * License along with this library; if not, write to the
16 2daccc89 Alexandre Quessy
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 2daccc89 Alexandre Quessy
 * Boston, MA 02111-1307, USA.
18 2daccc89 Alexandre Quessy
 */
19 2daccc89 Alexandre Quessy
20 2daccc89 Alexandre Quessy
#include <string.h>
21 2daccc89 Alexandre Quessy
#include <math.h>
22 2daccc89 Alexandre Quessy
23 2daccc89 Alexandre Quessy
#include <gst/gst.h>
24 2daccc89 Alexandre Quessy
#include <gst/app/gstappsink.h>
25 2daccc89 Alexandre Quessy
#include "shared-video.h"
26 2daccc89 Alexandre Quessy
27 2daccc89 Alexandre Quessy
28 2daccc89 Alexandre Quessy
29 2daccc89 Alexandre Quessy
/*
30 2daccc89 Alexandre Quessy
 * A simple RTP receiver 
31 2daccc89 Alexandre Quessy
 *
32 2daccc89 Alexandre Quessy
 *  receives alaw encoded RTP audio on port 5002, RTCP is received on  port 5003.
33 2daccc89 Alexandre Quessy
 *  the receiver RTCP reports are sent to port 5007
34 2daccc89 Alexandre Quessy
 *
35 2daccc89 Alexandre Quessy
 *             .-------.      .----------.     .---------.   .-------.   .--------.
36 2daccc89 Alexandre Quessy
 *  RTP        |udpsrc |      | rtpbin   |     |         |   |       |   |        |
37 2daccc89 Alexandre Quessy
 *  port=5002  |      src->recv_rtp recv_rtp->sink     src->sink   src->sink      |
38 2daccc89 Alexandre Quessy
 *             '-------'      |          |     '---------'   '-------'   '--------'
39 2daccc89 Alexandre Quessy
 *                            |          |      
40 2daccc89 Alexandre Quessy
 *                            |          |     .-------.
41 2daccc89 Alexandre Quessy
 *                            |          |     |udpsink|  RTCP
42 2daccc89 Alexandre Quessy
 *                            |    send_rtcp->sink     | port=5007
43 2daccc89 Alexandre Quessy
 *             .-------.      |          |     '-------' sync=false
44 2daccc89 Alexandre Quessy
 *  RTCP       |udpsrc |      |          |               async=false
45 2daccc89 Alexandre Quessy
 *  port=5003  |     src->recv_rtcp      |                       
46 2daccc89 Alexandre Quessy
 *             '-------'      '----------'              
47 2daccc89 Alexandre Quessy
 */
48 2daccc89 Alexandre Quessy
49 2daccc89 Alexandre Quessy
/* the caps of the sender RTP stream. This is usually negotiated out of band with
50 2daccc89 Alexandre Quessy
 * SDP or RTSP. */
51 2daccc89 Alexandre Quessy
52 2daccc89 Alexandre Quessy
/* the destination machine to send RTCP to. This is the address of the sender and
53 2daccc89 Alexandre Quessy
 * is used to send back the RTCP reports of this receiver. If the data is sent
54 2daccc89 Alexandre Quessy
 * from another machine, change this address. */
55 2daccc89 Alexandre Quessy
#define DEST_HOST "127.0.0.1"
56 2daccc89 Alexandre Quessy
57 2daccc89 Alexandre Quessy
typedef struct _App App;
58 2daccc89 Alexandre Quessy
struct _App
59 2daccc89 Alexandre Quessy
{
60 2daccc89 Alexandre Quessy
    GstElement *pipeline;
61 2daccc89 Alexandre Quessy
    ScenicSharedVideo::Writer *writer;
62 2daccc89 Alexandre Quessy
    std::string socketName;
63 2daccc89 Alexandre Quessy
};
64 2daccc89 Alexandre Quessy
65 2daccc89 Alexandre Quessy
App app;
66 2daccc89 Alexandre Quessy
67 2daccc89 Alexandre Quessy
68 2daccc89 Alexandre Quessy
/* print the stats of a source */
69 2daccc89 Alexandre Quessy
 static void
70 2daccc89 Alexandre Quessy
 print_source_stats (GObject * source)
71 2daccc89 Alexandre Quessy
 {
72 2daccc89 Alexandre Quessy
   GstStructure *stats;
73 2daccc89 Alexandre Quessy
   gchar *str;
74 2daccc89 Alexandre Quessy
75 2daccc89 Alexandre Quessy
   g_return_if_fail (source != NULL);
76 2daccc89 Alexandre Quessy
77 2daccc89 Alexandre Quessy
   /* get the source stats */
78 2daccc89 Alexandre Quessy
   g_object_get (source, "stats", &stats, NULL);
79 2daccc89 Alexandre Quessy
80 2daccc89 Alexandre Quessy
   /* simply dump the stats structure */
81 2daccc89 Alexandre Quessy
   str = gst_structure_to_string (stats);
82 2daccc89 Alexandre Quessy
   g_print ("source stats: %s\n", str);
83 2daccc89 Alexandre Quessy
84 2daccc89 Alexandre Quessy
   gst_structure_free (stats);
85 2daccc89 Alexandre Quessy
   g_free (str);
86 2daccc89 Alexandre Quessy
 }
87 2daccc89 Alexandre Quessy
88 2daccc89 Alexandre Quessy
/* will be called when gstrtpbin signals on-ssrc-active. It means that an RTCP*/
89 2daccc89 Alexandre Quessy
/* packet was received from another source. */
90 2daccc89 Alexandre Quessy
 static void
91 2daccc89 Alexandre Quessy
 on_ssrc_active_cb (GstElement * rtpbin, guint sessid, guint ssrc,
92 2daccc89 Alexandre Quessy
                    gpointer user_data/*GstElement * depay*/)
93 2daccc89 Alexandre Quessy
 {
94 2daccc89 Alexandre Quessy
   GObject *session, *isrc, *osrc;
95 2daccc89 Alexandre Quessy
96 2daccc89 Alexandre Quessy
   g_print ("got RTCP from session %u, SSRC %u\n", sessid, ssrc);
97 2daccc89 Alexandre Quessy
98 2daccc89 Alexandre Quessy
   /* get the right session */
99 2daccc89 Alexandre Quessy
   g_signal_emit_by_name (rtpbin, "get-internal-session", sessid, &session);
100 2daccc89 Alexandre Quessy
101 2daccc89 Alexandre Quessy
   /* get the internal source (the SSRC allocated to us, the receiver */
102 2daccc89 Alexandre Quessy
   g_object_get (session, "internal-source", &isrc, NULL);
103 2daccc89 Alexandre Quessy
   print_source_stats (isrc);
104 2daccc89 Alexandre Quessy
105 2daccc89 Alexandre Quessy
   /* get the remote source that sent us RTCP */
106 2daccc89 Alexandre Quessy
   g_signal_emit_by_name (session, "get-source-by-ssrc", ssrc, &osrc);
107 2daccc89 Alexandre Quessy
   print_source_stats (osrc);
108 2daccc89 Alexandre Quessy
 }
109 2daccc89 Alexandre Quessy
110 2daccc89 Alexandre Quessy
 static void
111 2daccc89 Alexandre Quessy
 pad_removed_cb (GstElement * rtpbin, GstPad * new_pad, gpointer user_data/*GstElement * depay*/)
112 2daccc89 Alexandre Quessy
 {
113 2daccc89 Alexandre Quessy
     g_print ("pad removed: %s\n", GST_PAD_NAME (new_pad));
114 2daccc89 Alexandre Quessy
   
115 2daccc89 Alexandre Quessy
 }
116 2daccc89 Alexandre Quessy
 /* will be called when rtpbin has validated a payload that we can depayload */
117 2daccc89 Alexandre Quessy
 static void
118 2daccc89 Alexandre Quessy
 pad_added_cb (GstElement * rtpbin, GstPad * new_pad, gpointer user_data/*GstElement * depay*/)
119 2daccc89 Alexandre Quessy
 {
120 2daccc89 Alexandre Quessy
   GstPad *sinkpad;
121 2daccc89 Alexandre Quessy
   GstPadLinkReturn lres;
122 2daccc89 Alexandre Quessy
123 2daccc89 Alexandre Quessy
   App *app = (App *)user_data;
124 2daccc89 Alexandre Quessy
 
125 2daccc89 Alexandre Quessy
   g_print ("new payload on pad: %s\n", GST_PAD_NAME (new_pad));
126 2daccc89 Alexandre Quessy
   
127 2daccc89 Alexandre Quessy
   
128 2daccc89 Alexandre Quessy
129 2daccc89 Alexandre Quessy
  /* the depayloading and decoding */
130 2daccc89 Alexandre Quessy
   GstElement *gstdepay = gst_element_factory_make ("rtpgstdepay" , NULL);
131 2daccc89 Alexandre Quessy
   g_assert (gstdepay);
132 2daccc89 Alexandre Quessy
133 2daccc89 Alexandre Quessy
134 2daccc89 Alexandre Quessy
   gst_element_set_state (gstdepay,GST_STATE_PLAYING);
135 2daccc89 Alexandre Quessy
   
136 2daccc89 Alexandre Quessy
   /* add depayloading and playback to the pipeline and link */
137 2daccc89 Alexandre Quessy
   gst_bin_add (GST_BIN (app->pipeline), gstdepay);
138 2daccc89 Alexandre Quessy
   
139 2daccc89 Alexandre Quessy
    sinkpad = gst_element_get_static_pad (gstdepay, "sink");
140 2daccc89 Alexandre Quessy
    g_assert (sinkpad);
141 2daccc89 Alexandre Quessy
142 2daccc89 Alexandre Quessy
    lres = gst_pad_link (new_pad, sinkpad);
143 2daccc89 Alexandre Quessy
    g_assert (lres == GST_PAD_LINK_OK);
144 2daccc89 Alexandre Quessy
    gst_object_unref (sinkpad);
145 2daccc89 Alexandre Quessy
146 2daccc89 Alexandre Quessy
    app->writer = new ScenicSharedVideo::Writer (app->pipeline,gstdepay,app->socketName);
147 2daccc89 Alexandre Quessy
 }
148 2daccc89 Alexandre Quessy
149 2daccc89 Alexandre Quessy
150 2daccc89 Alexandre Quessy
151 2daccc89 Alexandre Quessy
void
152 2daccc89 Alexandre Quessy
leave(int sig) {
153 2daccc89 Alexandre Quessy
    gst_element_set_state (app.pipeline, GST_STATE_NULL);
154 2daccc89 Alexandre Quessy
    gst_object_unref (GST_OBJECT (app.pipeline));
155 2daccc89 Alexandre Quessy
    exit(sig);
156 2daccc89 Alexandre Quessy
}
157 2daccc89 Alexandre Quessy
158 2daccc89 Alexandre Quessy
/* build a pipeline equivalent to:
159 2daccc89 Alexandre Quessy
 *
160 2daccc89 Alexandre Quessy
 * gst-launch -v gstrtpbin name=rtpbin                                                \
161 2daccc89 Alexandre Quessy
 *      udpsrc caps=$AUDIO_CAPS port=5002 ! rtpbin.recv_rtp_sink_0              \
162 2daccc89 Alexandre Quessy
 *        rtpbin. ! rtpgstdepay ! appsink \
163 2daccc89 Alexandre Quessy
 *      udpsrc port=5003 ! rtpbin.recv_rtcp_sink_0                              \
164 2daccc89 Alexandre Quessy
 *        rtpbin.send_rtcp_src_0 ! udpsink port=5007 host=$DEST sync=false async=false
165 2daccc89 Alexandre Quessy
 */
166 2daccc89 Alexandre Quessy
int
167 2daccc89 Alexandre Quessy
main (int argc, char *argv[])
168 2daccc89 Alexandre Quessy
{
169 2daccc89 Alexandre Quessy
    GstElement *rtpbin, *rtcpsrc, *rtcpsink;
170 2daccc89 Alexandre Quessy
    GstElement *rtpsrc;
171 2daccc89 Alexandre Quessy
    GMainLoop *loop;
172 2daccc89 Alexandre Quessy
    GstCaps *caps;
173 2daccc89 Alexandre Quessy
    GstPadLinkReturn lres;
174 2daccc89 Alexandre Quessy
    GstPad *srcpad, *sinkpad;
175 2daccc89 Alexandre Quessy
    
176 2daccc89 Alexandre Quessy
     /* Check input arguments */
177 2daccc89 Alexandre Quessy
    if (argc != 2) {
178 2daccc89 Alexandre Quessy
        g_printerr ("Usage: %s <socket-path>\n", argv[0]);
179 2daccc89 Alexandre Quessy
        return -1;
180 2daccc89 Alexandre Quessy
    }
181 2daccc89 Alexandre Quessy
    app.socketName.append (argv[1]);
182 2daccc89 Alexandre Quessy
183 2daccc89 Alexandre Quessy
    (void) signal(SIGINT,leave);
184 2daccc89 Alexandre Quessy
185 2daccc89 Alexandre Quessy
  /* always init first */
186 2daccc89 Alexandre Quessy
  gst_init (&argc, &argv);
187 2daccc89 Alexandre Quessy
188 2daccc89 Alexandre Quessy
  /* the pipeline to hold everything */
189 2daccc89 Alexandre Quessy
  app.pipeline = gst_pipeline_new (NULL);
190 2daccc89 Alexandre Quessy
  g_assert (app.pipeline);
191 2daccc89 Alexandre Quessy
192 2daccc89 Alexandre Quessy
  /* the udp src and source we will use for RTP and RTCP */
193 2daccc89 Alexandre Quessy
   rtpsrc = gst_element_factory_make ("udpsrc", "rtpsrc");
194 2daccc89 Alexandre Quessy
   g_assert (rtpsrc);
195 2daccc89 Alexandre Quessy
   g_object_set (rtpsrc, "port", 5002, NULL);
196 2daccc89 Alexandre Quessy
   /* we need to set caps on the udpsrc for the RTP data */
197 2daccc89 Alexandre Quessy
   // caps inside caps is obtained with "echo application/nicolas | base64", removing the "0=" at the end
198 2daccc89 Alexandre Quessy
     caps = gst_caps_from_string ("application/x-rtp,media=(string)application,payload=(int)96,clock-rate=(int)90000,encoding-name=(string)X-GST,caps=(string)YXBwbGljYXRpb24vc2NlbmljZGF0YV8K");
199 2daccc89 Alexandre Quessy
     g_object_set (rtpsrc, "caps", caps, NULL);
200 2daccc89 Alexandre Quessy
     gst_caps_unref (caps);
201 2daccc89 Alexandre Quessy
202 2daccc89 Alexandre Quessy
203 2daccc89 Alexandre Quessy
   rtcpsrc = gst_element_factory_make ("udpsrc", "rtcpsrc");
204 2daccc89 Alexandre Quessy
   g_assert (rtcpsrc);
205 2daccc89 Alexandre Quessy
    g_object_set (rtcpsrc, "port", 5003, NULL);
206 2daccc89 Alexandre Quessy
207 2daccc89 Alexandre Quessy
   rtcpsink = gst_element_factory_make ("udpsink", "rtcpsink");
208 2daccc89 Alexandre Quessy
   g_assert (rtcpsink);
209 2daccc89 Alexandre Quessy
   g_object_set (rtcpsink, "port", 5007, "host", DEST_HOST, NULL);
210 2daccc89 Alexandre Quessy
   /* no need for synchronisation or preroll on the RTCP sink */
211 2daccc89 Alexandre Quessy
   g_object_set (rtcpsink, "async", FALSE, "sync", FALSE, NULL);
212 2daccc89 Alexandre Quessy
213 2daccc89 Alexandre Quessy
   gst_bin_add_many (GST_BIN (app.pipeline), rtpsrc, 
214 2daccc89 Alexandre Quessy
                       rtcpsrc, rtcpsink, 
215 2daccc89 Alexandre Quessy
                       NULL);
216 2daccc89 Alexandre Quessy
217 2daccc89 Alexandre Quessy
    /* the rtpbin element */
218 2daccc89 Alexandre Quessy
    rtpbin = gst_element_factory_make ("gstrtpbin", "rtpbin");
219 2daccc89 Alexandre Quessy
    g_assert (rtpbin);
220 2daccc89 Alexandre Quessy
221 2daccc89 Alexandre Quessy
    gst_bin_add (GST_BIN (app.pipeline), rtpbin);
222 2daccc89 Alexandre Quessy
223 2daccc89 Alexandre Quessy
    g_print ("rtp sinkpad\n");
224 2daccc89 Alexandre Quessy
  
225 2daccc89 Alexandre Quessy
    /* now link all to the rtpbin, start by getting an RTP sinkpad for session 0 */
226 2daccc89 Alexandre Quessy
     srcpad = gst_element_get_static_pad (rtpsrc, "src");
227 2daccc89 Alexandre Quessy
     g_assert (srcpad);
228 2daccc89 Alexandre Quessy
     sinkpad = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_0");
229 2daccc89 Alexandre Quessy
     g_assert (sinkpad);
230 2daccc89 Alexandre Quessy
     lres = gst_pad_link (srcpad, sinkpad);
231 2daccc89 Alexandre Quessy
     g_print ("%d \n",lres);
232 2daccc89 Alexandre Quessy
     g_assert (lres == GST_PAD_LINK_OK);
233 2daccc89 Alexandre Quessy
     gst_object_unref (srcpad);
234 2daccc89 Alexandre Quessy
235 2daccc89 Alexandre Quessy
    g_print ("rtcp sinkpad\n");
236 2daccc89 Alexandre Quessy
237 2daccc89 Alexandre Quessy
    /* get an RTCP sinkpad in session 0 */
238 2daccc89 Alexandre Quessy
    srcpad = gst_element_get_static_pad (rtcpsrc, "src");
239 2daccc89 Alexandre Quessy
    sinkpad = gst_element_get_request_pad (rtpbin, "recv_rtcp_sink_0");
240 2daccc89 Alexandre Quessy
    lres = gst_pad_link (srcpad, sinkpad);
241 2daccc89 Alexandre Quessy
    g_assert (lres == GST_PAD_LINK_OK);
242 2daccc89 Alexandre Quessy
    gst_object_unref (srcpad);
243 2daccc89 Alexandre Quessy
    gst_object_unref (sinkpad);
244 2daccc89 Alexandre Quessy
245 2daccc89 Alexandre Quessy
    g_print ("rtcp srcpad\n");
246 2daccc89 Alexandre Quessy
  
247 2daccc89 Alexandre Quessy
    /* get an RTCP srcpad for sending RTCP back to the sender */
248 2daccc89 Alexandre Quessy
    srcpad = gst_element_get_request_pad (rtpbin, "send_rtcp_src_0");
249 2daccc89 Alexandre Quessy
    sinkpad = gst_element_get_static_pad (rtcpsink, "sink");
250 2daccc89 Alexandre Quessy
    lres = gst_pad_link (srcpad, sinkpad);
251 2daccc89 Alexandre Quessy
    g_assert (lres == GST_PAD_LINK_OK);
252 2daccc89 Alexandre Quessy
    gst_object_unref (sinkpad);
253 2daccc89 Alexandre Quessy
254 2daccc89 Alexandre Quessy
    /* the RTP pad that we have to connect to the depayloader will be created
255 2daccc89 Alexandre Quessy
     * dynamically so we connect to the pad-added signal, pass the depayloader as
256 2daccc89 Alexandre Quessy
     * user_data so that we can link to it. */
257 2daccc89 Alexandre Quessy
    g_signal_connect (rtpbin, "pad-added", G_CALLBACK (pad_added_cb), &app);
258 2daccc89 Alexandre Quessy
    g_signal_connect (rtpbin, "pad-removed", G_CALLBACK (pad_removed_cb), &app);
259 2daccc89 Alexandre Quessy
260 2daccc89 Alexandre Quessy
    /* give some stats when we receive RTCP */
261 c2489c3b Alexandre Quessy
    g_signal_connect (rtpbin, "on-ssrc-active", G_CALLBACK (on_ssrc_active_cb),
262 c2489c3b Alexandre Quessy
                           NULL);
263 2daccc89 Alexandre Quessy
264 2daccc89 Alexandre Quessy
  /* set the pipeline to playing */
265 2daccc89 Alexandre Quessy
  g_print ("starting receiver pipeline\n");
266 2daccc89 Alexandre Quessy
  gst_element_set_state (app.pipeline, GST_STATE_PLAYING);
267 2daccc89 Alexandre Quessy
268 2daccc89 Alexandre Quessy
  /* we need to run a GLib main loop to get the messages */
269 2daccc89 Alexandre Quessy
  loop = g_main_loop_new (NULL, FALSE);
270 2daccc89 Alexandre Quessy
  g_main_loop_run (loop);
271 2daccc89 Alexandre Quessy
272 2daccc89 Alexandre Quessy
  g_print ("stopping receiver pipeline\n");
273 2daccc89 Alexandre Quessy
  gst_element_set_state (app.pipeline, GST_STATE_NULL);
274 2daccc89 Alexandre Quessy
275 2daccc89 Alexandre Quessy
  gst_object_unref (app.pipeline);
276 2daccc89 Alexandre Quessy
277 2daccc89 Alexandre Quessy
  return 0;
278 2daccc89 Alexandre Quessy
}