• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer AVTP Plugin
3  * Copyright (C) 2019 Intel Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later
9  * version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * plugin-avtp:
24  *
25  * ## Audio Video Transport Protocol (AVTP) Plugin
26  *
27  * The AVTP plugin implements typical Talker and Listener functionalities that
28  * can be leveraged by GStreamer-based applications in order to implement TSN
29  * audio/video applications.
30  *
31  * ### Dependencies
32  *
33  * The plugin uses libavtp to handle AVTP packetization. Libavtp source code can
34  * be found in https://github.com/AVnu/libavtp as well as instructions to build
35  * and install it.
36  *
37  * If libavtp isn't detected by configure, the plugin isn't built.
38  *
39  * ### The application/x-avtp mime type
40  *
41  * For valid AVTPDUs encapsulated in GstBuffers, we use the caps with mime type
42  * application/x-avtp.
43  *
44  * AVTP mime type is pretty simple and has no fields.
45  *
46  * ### gPTP Setup
47  *
48  * The Linuxptp project provides the ptp4l daemon, which synchronizes the PTP
49  * clock from NIC, and the pmc tool which communicates with ptp4l to get/set
50  * some runtime settings. The project also provides the phc2sys daemon which
51  * synchronizes the PTP clock and system clock.
52  *
53  * The AVTP plugin requires system clock is synchronized with PTP clock and
54  * TAI offset is properly set in the kernel. ptp4l and phc2sys can be set up
55  * in many different ways, below we provide an example that fullfils the plugin
56  * requirements. For further information check ptp4l(8) and phc2sys(8).
57  *
58  * In the following instructions, replace $IFNAME by your PTP capable NIC
59  * interface. The gPTP.cfg file mentioned below can be found in /usr/share/
60  * doc/linuxptp/ (depending on your distro).
61  *
62  * Synchronize PTP clock with PTP time:
63  *
64  *	$ ptp4l -f gPTP.cfg -i $IFNAME
65  *
66  * Enable TAI offset to be automatically set by phc2sys:
67  *
68  *	$ pmc -u -t 1 -b 0 'SET GRANDMASTER_SETTINGS_NP \
69  * 		clockClass 248 clockAccuracy 0xfe \
70  * 		offsetScaledLogVariance 0xffff \
71  * 		currentUtcOffset 37 leap61 0 leap59 0 \
72  * 		currentUtcOffsetValid 1 ptpTimescale 1 \
73  * 		timeTraceable 1 frequencyTraceable 0 timeSource 0xa0'
74  *
75  * Synchronize system clock with PTP clock:
76  *
77  * 	$ phc2sys -f gPTP.cfg -s $IFNAME -c CLOCK_REALTIME -w
78  *
79  * The commands above should be run on both AVTP Talker and Listener hosts.
80  *
81  * With clocks properly synchronized, applications using the AVTP plugin
82  * should use GstSytemClock with GST_CLOCK_TYPE_REALTIME as the pipeline
83  * clock.
84  *
85  * ### Clock Reference Format (CRF)
86  *
87  * Even though the systems are synchronized by PTP, it is possible that
88  * different talkers can send media streams which are out of phase or the
89  * frequencies do not exactly match. This is partcularly important when there
90  * is a single listener processing data from multiple talkers. The systems in
91  * this scenario can benefit if a common clock is distributed among the
92  * systems.
93  *
94  * This can be achieved by using the avtpcrfsync element which implements CRF
95  * as described in Chapter 10 of IEEE 1722-2016. avtpcrfcheck can also be used
96  * to validate that the adjustment conforms to the criteria specified in the
97  * spec. For further details, look at the documentation for the respective
98  * elements.
99  *
100  * ### Traffic Control Setup
101  *
102  * FQTSS (Forwarding and Queuing Enhancements for Time-Sensitive Streams) can be
103  * enabled on Linux with the help of the mqprio and cbs qdiscs provided by the
104  * Linux Traffic Control. Below we provide an example to configure those qdiscs
105  * in order to transmit a CVF H.264 stream 1280x720@30fps. For further
106  * information on how to configure these qdiscs check tc-mqprio(8) and
107  * tc-cbs(8) man pages.
108  *
109  * On the host that will run as AVTP Talker (pipeline that generates the video
110  * stream), run the following commands:
111  *
112  * Configure mpqrio qdisc (replace $MQPRIO_HANDLE_ID by an unused handle ID):
113  *
114  *     $ tc qdisc add dev $IFNAME parent root handle $MQPRIO_HANDLE_ID mqprio \
115  *         num_tc 3 map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \
116  *         queues 1@0 1@1 2@2 hw 0
117  *
118  * Configure cbs qdisc (replace $CBS_HANDLE_ID by an unused handle ID):
119  *
120  *     $ tc qdisc replace dev $IFNAME parent $MQPRIO_HANDLE_ID:1 \
121  *         handle $CBS_HANDLE_ID cbs idleslope 27756 sendslope -972244 \
122  *         hicredit 42 locredit -1499 offload 1
123  *
124  * Also, the plugin implements a transmission scheduling mechanism that relies
125  * on ETF qdisc so make sure it is properly configured in your system. It could
126  * be configured in many ways, below follows an example.
127  *
128  *     $ tc qdisc add dev $IFNAME parent $CBS_HANDLE_ID:1 etf \
129  *         clockid CLOCK_TAI delta 500000 offload
130  *
131  * No Traffic Control configuration is required at the host running as AVTP
132  * Listener.
133  *
134  * ### Capabilities
135  *
136  * The `avtpsink` and `avtpsrc` elements open `AF_PACKET` sockets, which require
137  * `CAP_NET_RAW` capability. Also, `avtpsink` needs `CAP_NET_ADMIN` to use ETF.
138  * Therefore, applications must have those capabilities in order to successfully
139  * use these elements. For instance, one can use:
140  *
141  *     $ sudo setcap cap_net_raw,cap_net_admin+ep <application>
142  *
143  * Applications can drop these capabilities after the sockets are open, after
144  * `avtpsrc` or `avtpsink` elements transition to PAUSED state. See setcap(8)
145  * man page for more information.
146  *
147  * ### Elements configuration
148  *
149  * Each element has its own configuration properties, with some being common
150  * to several elements. Basic properties are:
151  *
152  *   * streamid (avtpaafpay, avtpcvfpay, avtpaafdepay, avtpcvfdepay,
153  *     avtpcrfsync, avtpcrfcheck): Stream ID associated with the stream.
154  *
155  *   * ifname (avtpsink, avtpsrc, avtpcrfsync, avtpcrfcheck): Network interface
156  *     used to send/receive AVTP packets.
157  *
158  *   * dst-macaddr (avtpsink, avtpsrc): Destination MAC address for the stream.
159  *
160  *   * priority (avtpsink): Priority used by the plugin to transmit AVTP
161  *     traffic.
162  *
163  *   * mtt (avtpaafpay, avtpcvfpay): Maximum Transit Time, in nanoseconds, as
164  *     defined in AVTP spec.
165  *
166  *   * tu (avtpaafpay, avtpcvfpay): Maximum Time Uncertainty, in nanoseconds, as
167  *     defined in AVTP spec.
168  *
169  *   * processing-deadline (avtpaafpay, avtpcvfpay, avtpsink): Maximum amount of
170  *     time, in nanoseconds, that the pipeline is expected to process any
171  *     buffer. This value should be in sync between the one used on the
172  *     payloader and the sink, as this time is also taken into consideration to
173  *     define the correct presentation time of the packets on the AVTP listener
174  *     side. It should be as low as possible (zero if possible).
175  *
176  *   * timestamp-mode (avtpaafpay): AAF timestamping mode, as defined in AVTP spec.
177  *
178  *   * mtu (avtpcvfpay): Maximum Transmit Unit of the underlying network, used
179  *     to determine when to fragment a CVF packet and how big it should be.
180  *
181  * Check each element documentation for more details.
182  *
183  *
184  * ### Running a sample pipeline
185  *
186  * The following pipelines uses debugutilsbad "clockselect" element to force
187  * the pipeline clock to be GstPtpClock. A real application would
188  * programmatically define GstPtpClock as the pipeline clock (see next section).
189  * It is also assumes that `gst-launch-1.0` has CAP_NET_RAW and CAP_NET_ADMIN
190  * capabilities.
191  *
192  * On the AVTP talker, the following pipeline can be used to generate an H.264
193  * stream to be sent via network using AVTP:
194  *
195  *     $ gst-launch-1.0 clockselect. \( clockid=ptp \
196  *         videotestsrc is-live=true ! clockoverlay ! x264enc ! \
197  *         avtpcvfpay processing-deadline=20000000 ! \
198  *         avtpcrfsync ifname=$IFNAME ! avtpsink ifname=$IFNAME \)
199  *
200  * On the AVTP listener host, the following pipeline can be used to get the
201  * AVTP stream, depacketize it and show it on the screen:
202  *
203  *     $ gst-launch-1.0 clockselect. \( clockid=ptp avtpsrc ifname=$IFNAME ! \
204  *         avtpcrfcheck ifname=$IFNAME ! avtpcvfdepay ! \
205  *         vaapih264dec ! videoconvert ! clockoverlay halignment=right ! \
206  *         queue ! autovideosink \)
207  *
208  * ### Pipeline clock
209  *
210  * The AVTP plugin elements require that the pipeline clock is in sync with
211  * the network PTP clock. As GStreamer has a GstPtpClock, using it should be
212  * the simplest way of achieving that.
213  *
214  * However, as there's no way of forcing a clock to a pipeline using
215  * gst-launch-1.0 application, even for quick tests, it's necessary to have
216  * an application. One can refer to GStreamer "hello world" application,
217  * remembering to set the pipeline clock to GstPtpClock before putting the
218  * pipeline on "PLAYING" state. Some code like:
219  *
220  *     GstClock *clk = gst_ptp_clock_new("ptp-clock", 0);
221  *     gst_clock_wait_for_sync(clk, GST_CLOCK_TIME_NONE);
222  *     gst_pipeline_use_clock (GST_PIPELINE (pipeline), clk);
223  *
224  * Would do the trick.
225  *
226  * ### Disclaimer
227  *
228  * It's out of scope for the AVTP plugin to verify how it is invoked, should
229  * a malicious software do it for Denial of Service attempts, or other
230  * compromises attempts.
231  *
232  * Since: 1.18
233  */
234 #ifdef HAVE_CONFIG_H
235 #include <config.h>
236 #endif
237 
238 #include <gst/gst.h>
239 
240 #include "gstavtpaafdepay.h"
241 #include "gstavtpaafpay.h"
242 #include "gstavtpcvfdepay.h"
243 #include "gstavtpcvfpay.h"
244 #include "gstavtpsink.h"
245 #include "gstavtpsrc.h"
246 #include "gstavtpcrfsync.h"
247 #include "gstavtpcrfcheck.h"
248 
249 static gboolean
plugin_init(GstPlugin * plugin)250 plugin_init (GstPlugin * plugin)
251 {
252   gboolean ret = FALSE;
253 
254   ret |= GST_ELEMENT_REGISTER (avtpaafpay, plugin);
255   ret |= GST_ELEMENT_REGISTER (avtpaafdepay, plugin);
256   ret |= GST_ELEMENT_REGISTER (avtpsink, plugin);
257   ret |= GST_ELEMENT_REGISTER (avtpsrc, plugin);
258   ret |= GST_ELEMENT_REGISTER (avtpcvfpay, plugin);
259   ret |= GST_ELEMENT_REGISTER (avtpcvfdepay, plugin);
260   ret |= GST_ELEMENT_REGISTER (avtpcrfsync, plugin);
261   ret |= GST_ELEMENT_REGISTER (avtpcrfcheck, plugin);
262 
263   return ret;
264 }
265 
266 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
267     avtp, "Audio/Video Transport Protocol (AVTP) plugin",
268     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
269