webrtc/nice: support consent-freshness RFC7675
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / rtp / gstrtpklvpay.c
1 /* GStreamer RTP KLV Payloader
2  * Copyright (C) 2014-2015 Tim-Philipp Müller <tim@centricular.com>>
3  * Copyright (C) 2014-2015 Centricular Ltd
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
21 /**
22  * SECTION:element-rtpklvpay
23  * @title: rtpklvpay
24  * @see_also: rtpklvdepay
25  *
26  * Payloads KLV metadata into RTP packets according to RFC 6597.
27  * For detailed information see: http://tools.ietf.org/html/rfc6597
28  *
29  * ## Example pipeline
30  * |[
31  * gst-launch-1.0 filesrc location=video-with-klv.ts ! tsdemux ! rtpklvpay ! udpsink
32  * ]| This example pipeline will payload an RTP KLV stream extracted from an
33  * MPEG-TS stream and send it via UDP to an RTP receiver.
34  *
35  */
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "gstrtpelements.h"
41 #include "gstrtpklvpay.h"
42 #include "gstrtputils.h"
43
44 #include <string.h>
45
46 GST_DEBUG_CATEGORY_STATIC (klvpay_debug);
47 #define GST_CAT_DEFAULT (klvpay_debug)
48
49 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
50     GST_PAD_SRC,
51     GST_PAD_ALWAYS,
52     GST_STATIC_CAPS ("application/x-rtp, "
53         "media = (string) application, clock-rate = (int) [1, MAX], "
54         "encoding-name = (string) SMPTE336M")
55     );
56
57 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
58     GST_PAD_SINK,
59     GST_PAD_ALWAYS,
60     GST_STATIC_CAPS ("meta/x-klv, parsed = (bool) true"));
61
62 #define gst_rtp_klv_pay_parent_class parent_class
63 G_DEFINE_TYPE (GstRtpKlvPay, gst_rtp_klv_pay, GST_TYPE_RTP_BASE_PAYLOAD);
64 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (rtpklvpay, "rtpklvpay",
65     GST_RANK_SECONDARY, GST_TYPE_RTP_KLV_PAY, rtp_element_init (plugin));
66
67 static gboolean gst_rtp_klv_pay_setcaps (GstRTPBasePayload * pay,
68     GstCaps * caps);
69 static GstFlowReturn gst_rtp_klv_pay_handle_buffer (GstRTPBasePayload * pay,
70     GstBuffer * buf);
71
72 static void
73 gst_rtp_klv_pay_class_init (GstRtpKlvPayClass * klass)
74 {
75   GstElementClass *element_class = (GstElementClass *) klass;
76   GstRTPBasePayloadClass *rtpbasepay_class;
77
78   GST_DEBUG_CATEGORY_INIT (klvpay_debug, "klvpay", 0, "RTP KLV Payloader");
79
80   gst_element_class_add_static_pad_template (element_class, &src_template);
81   gst_element_class_add_static_pad_template (element_class, &sink_template);
82
83   gst_element_class_set_static_metadata (element_class,
84       "RTP KLV Payloader", "Codec/Payloader/Network/RTP",
85       "Payloads KLV (SMPTE ST 336) metadata as RTP packets",
86       "Tim-Philipp Müller <tim@centricular.com>");
87
88   rtpbasepay_class = (GstRTPBasePayloadClass *) klass;
89
90   rtpbasepay_class->set_caps = gst_rtp_klv_pay_setcaps;
91   rtpbasepay_class->handle_buffer = gst_rtp_klv_pay_handle_buffer;
92 }
93
94 static void
95 gst_rtp_klv_pay_init (GstRtpKlvPay * klvpay)
96 {
97   /* nothing to do here yet */
98 }
99
100 static gboolean
101 gst_rtp_klv_pay_setcaps (GstRTPBasePayload * pay, GstCaps * caps)
102 {
103   /* FIXME: allow other clock rates */
104   gst_rtp_base_payload_set_options (pay, "application", TRUE, "SMPTE336M",
105       90000);
106
107   return gst_rtp_base_payload_set_outcaps (pay, NULL);
108 }
109
110 static GstFlowReturn
111 gst_rtp_klv_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buf)
112 {
113   GstFlowReturn ret = GST_FLOW_OK;
114   GstBufferList *list = NULL;
115   GstRtpKlvPay *pay;
116   GstMapInfo map;
117   GstBuffer *outbuf = NULL;
118   gsize offset;
119   guint mtu, rtp_header_size, max_payload_size;
120
121   pay = GST_RTP_KLV_PAY (basepayload);
122   mtu = GST_RTP_BASE_PAYLOAD_MTU (basepayload);
123
124   rtp_header_size = gst_rtp_buffer_calc_header_len (0);
125   max_payload_size = mtu - rtp_header_size;
126
127   gst_buffer_map (buf, &map, GST_MAP_READ);
128
129   if (map.size == 0)
130     goto done;
131
132   /* KLV coding shall use and only use a fixed 16-byte SMPTE-administered
133    * Universal Label, according to SMPTE 298M as Key (Rec. ITU R-BT.1653-1) */
134   if (map.size < 16 || GST_READ_UINT32_BE (map.data) != 0x060E2B34)
135     goto bad_input;
136
137   if (map.size > max_payload_size)
138     list = gst_buffer_list_new ();
139
140   GST_LOG_OBJECT (pay, "%" G_GSIZE_FORMAT " bytes of data to payload",
141       map.size);
142
143   offset = 0;
144   while (offset < map.size) {
145     GstBuffer *payloadbuf;
146     GstRTPBuffer rtp = { NULL };
147     guint payload_size;
148     guint bytes_left;
149
150     bytes_left = map.size - offset;
151     payload_size = MIN (bytes_left, max_payload_size);
152
153     outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload, 0, 0, 0);
154
155     if (payload_size == bytes_left) {
156       GST_LOG_OBJECT (pay, "last packet of KLV unit");
157       gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
158       gst_rtp_buffer_set_marker (&rtp, 1);
159       gst_rtp_buffer_unmap (&rtp);
160       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_MARKER);
161     }
162
163     GST_LOG_OBJECT (pay, "packet with payload size %u", payload_size);
164
165     gst_rtp_copy_meta (GST_ELEMENT_CAST (pay), outbuf, buf, 0);
166
167     payloadbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_MEMORY,
168         offset, payload_size);
169
170     /* join rtp header + payload memory parts */
171     outbuf = gst_buffer_append (outbuf, payloadbuf);
172
173     GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
174     GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buf);
175
176     /* and add to list */
177     if (list != NULL)
178       gst_buffer_list_insert (list, -1, outbuf);
179
180     offset += payload_size;
181   }
182
183 done:
184
185   gst_buffer_unmap (buf, &map);
186   gst_buffer_unref (buf);
187
188   if (list != NULL)
189     ret = gst_rtp_base_payload_push_list (basepayload, list);
190   else if (outbuf != NULL)
191     ret = gst_rtp_base_payload_push (basepayload, outbuf);
192
193   return ret;
194
195 /* ERRORS */
196 bad_input:
197   {
198     GST_ERROR_OBJECT (pay, "Input doesn't look like a KLV packet, ignoring");
199     goto done;
200   }
201 }