webrtc/nice: support consent-freshness RFC7675
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / rtp / gstrtph261depay.c
1 /* GStreamer
2  *
3  * Copyright (C) <2014> Stian Selnes <stian@pexip.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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:element-rtph261depay
23  * @title: rtph261depay
24  * @see_also: rtph261pay
25  *
26  * Extract encoded H.261 video frames from RTP packets according to RFC 4587.
27  * For detailed information see: https://www.rfc-editor.org/rfc/rfc4587.txt
28  *
29  * The depayloader takes an RTP packet and extracts its H.261 stream. It
30  * aggregates the extracted stream until a complete frame is received before
31  * it pushes it downstream.
32  *
33  * ## Example pipeline
34  * |[
35  * gst-launch-1.0 udpsrc caps='application/x-rtp, payload=31' ! rtph261depay ! avdec_h261 ! autovideosink
36  * ]| This example pipeline will depayload and decode an RTP H.261 video stream.
37  * Refer to the rtph261pay example to create the RTP stream.
38  *
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #  include "config.h"
43 #endif
44
45 #include <string.h>
46
47 #include <gst/rtp/gstrtpbuffer.h>
48 #include <gst/video/video.h>
49 #include "gstrtpelements.h"
50 #include "gstrtph261depay.h"
51 #include "gstrtph261pay.h"      /* GstRtpH261PayHeader */
52 #include "gstrtputils.h"
53
54 GST_DEBUG_CATEGORY_STATIC (rtph261depay_debug);
55 #define GST_CAT_DEFAULT (rtph261depay_debug)
56
57 static const guint8 NO_LEFTOVER = 0xFF;
58
59 static GstStaticPadTemplate gst_rtp_h261_depay_src_template =
60 GST_STATIC_PAD_TEMPLATE ("src",
61     GST_PAD_SRC,
62     GST_PAD_ALWAYS,
63     GST_STATIC_CAPS ("video/x-h261")
64     );
65
66 static GstStaticPadTemplate gst_rtp_h261_depay_sink_template =
67     GST_STATIC_PAD_TEMPLATE ("sink",
68     GST_PAD_SINK,
69     GST_PAD_ALWAYS,
70     GST_STATIC_CAPS ("application/x-rtp, "
71         "media = (string) \"video\", "
72         "payload = (int) " GST_RTP_PAYLOAD_H261_STRING ", "
73         "clock-rate = (int) 90000, " "encoding-name = (string) \"H261\"; "
74         "application/x-rtp, "
75         "media = (string) \"video\", "
76         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
77         "clock-rate = (int) 90000, " "encoding-name = (string) \"H261\"")
78     );
79 #define parent_class gst_rtp_h261_depay_parent_class
80 G_DEFINE_TYPE (GstRtpH261Depay, gst_rtp_h261_depay,
81     GST_TYPE_RTP_BASE_DEPAYLOAD);
82 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (rtph261depay, "rtph261depay",
83     GST_RANK_SECONDARY, GST_TYPE_RTP_H261_DEPAY, rtp_element_init (plugin));
84
85 static GstBuffer *
86 gst_rtp_h261_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
87 {
88   GstRtpH261Depay *depay;
89   GstBuffer *outbuf = NULL;
90   gint payload_len;
91   guint8 *payload;
92   const guint header_len = GST_RTP_H261_PAYLOAD_HEADER_LEN;
93   gboolean marker;
94   GstRtpH261PayHeader *header;
95
96   depay = GST_RTP_H261_DEPAY (depayload);
97
98   if (GST_BUFFER_IS_DISCONT (rtp->buffer)) {
99     GST_DEBUG_OBJECT (depay, "Discont buffer, flushing adapter");
100     gst_adapter_clear (depay->adapter);
101     depay->leftover = NO_LEFTOVER;
102     depay->start = FALSE;
103   }
104
105   payload_len = gst_rtp_buffer_get_payload_len (rtp);
106   payload = gst_rtp_buffer_get_payload (rtp);
107
108   marker = gst_rtp_buffer_get_marker (rtp);
109
110   if (payload_len < header_len + 1) {
111     /* Must have at least one byte payload */
112     GST_WARNING_OBJECT (depay, "Dropping packet with invalid payload length");
113     return NULL;
114   }
115
116   header = (GstRtpH261PayHeader *) payload;
117
118   GST_DEBUG_OBJECT (depay,
119       "payload_len: %d, header_len: %d, sbit: %d, ebit: %d, marker %d",
120       payload_len, header_len, header->sbit, header->ebit, marker);
121
122   payload += header_len;
123   payload_len -= header_len;
124
125   if (!depay->start) {
126     /* Check for picture start code */
127     guint32 bits = GST_READ_UINT32_BE (payload) << header->sbit;
128     if (payload_len > 4 && bits >> 12 == 0x10) {
129       GST_DEBUG_OBJECT (depay, "Found picture start code");
130       depay->start = TRUE;
131     } else {
132       GST_DEBUG_OBJECT (depay, "No picture start code yet, skipping payload");
133       goto skip;
134     }
135   }
136
137   if (header->sbit != 0) {
138     /* Take the leftover from previous packet and merge it at the beginning */
139     payload[0] &= 0xFF >> header->sbit;
140     if (depay->leftover != NO_LEFTOVER) {
141       /* Happens if sbit is set for first packet in frame. Then previous byte
142        * has already been flushed. */
143       payload[0] |= depay->leftover;
144     }
145     depay->leftover = NO_LEFTOVER;
146   }
147
148   if (header->ebit == 0) {
149     /* H.261 stream ends on byte boundary, take entire packet */
150     gst_adapter_push (depay->adapter,
151         gst_rtp_buffer_get_payload_subbuffer (rtp, header_len, payload_len));
152   } else {
153     /* Take the entire buffer except for the last byte, which will be kept to
154      * merge with next packet */
155     gst_adapter_push (depay->adapter,
156         gst_rtp_buffer_get_payload_subbuffer (rtp, header_len,
157             payload_len - 1));
158     depay->leftover = payload[payload_len - 1] & (0xFF << header->ebit);
159   }
160
161 skip:
162   if (marker) {
163     if (depay->start) {
164       guint avail;
165
166       if (depay->leftover != NO_LEFTOVER) {
167         GstBuffer *buf = gst_buffer_new_and_alloc (1);
168         gst_buffer_memset (buf, 0, depay->leftover, 1);
169         gst_adapter_push (depay->adapter, buf);
170         depay->leftover = NO_LEFTOVER;
171       }
172
173       avail = gst_adapter_available (depay->adapter);
174       outbuf = gst_adapter_take_buffer (depay->adapter, avail);
175       gst_rtp_drop_non_video_meta (depay, outbuf);
176
177       /* Note that the I flag does not mean intra frame, but that the entire
178        * stream is intra coded. */
179       if (header->i)
180         GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
181       else
182         GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
183
184       GST_DEBUG_OBJECT (depay, "Pushing out a buffer of %u bytes", avail);
185       depay->start = FALSE;
186     } else {
187       depay->start = TRUE;
188     }
189   }
190
191   return outbuf;
192 }
193
194 static gboolean
195 gst_rtp_h261_depay_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps)
196 {
197   GstCaps *srccaps;
198
199   srccaps = gst_caps_new_empty_simple ("video/x-h261");
200   gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (filter), srccaps);
201   gst_caps_unref (srccaps);
202
203   return TRUE;
204 }
205
206 static GstStateChangeReturn
207 gst_rtp_h261_depay_change_state (GstElement * element,
208     GstStateChange transition)
209 {
210   GstRtpH261Depay *depay;
211   GstStateChangeReturn ret;
212
213   depay = GST_RTP_H261_DEPAY (element);
214
215   switch (transition) {
216     case GST_STATE_CHANGE_NULL_TO_READY:
217       break;
218     case GST_STATE_CHANGE_READY_TO_PAUSED:
219       gst_adapter_clear (depay->adapter);
220       depay->start = FALSE;
221       break;
222     default:
223       break;
224   }
225
226   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
227
228   switch (transition) {
229     case GST_STATE_CHANGE_READY_TO_NULL:
230       break;
231     default:
232       break;
233   }
234   return ret;
235 }
236
237 static void
238 gst_rtp_h261_depay_dispose (GObject * object)
239 {
240   GstRtpH261Depay *depay;
241
242   depay = GST_RTP_H261_DEPAY (object);
243
244   if (depay->adapter) {
245     gst_object_unref (depay->adapter);
246     depay->adapter = NULL;
247   }
248
249   G_OBJECT_CLASS (parent_class)->dispose (object);
250 }
251
252 static void
253 gst_rtp_h261_depay_class_init (GstRtpH261DepayClass * klass)
254 {
255   GObjectClass *gobject_class;
256   GstElementClass *gstelement_class;
257   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
258
259   gobject_class = G_OBJECT_CLASS (klass);
260   gstelement_class = GST_ELEMENT_CLASS (klass);
261   gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
262
263   gst_element_class_add_static_pad_template (gstelement_class,
264       &gst_rtp_h261_depay_src_template);
265   gst_element_class_add_static_pad_template (gstelement_class,
266       &gst_rtp_h261_depay_sink_template);
267
268   gst_element_class_set_static_metadata (gstelement_class,
269       "RTP H261 depayloader", "Codec/Depayloader/Network/RTP",
270       "Extracts H261 video from RTP packets (RFC 4587)",
271       "Stian Selnes <stian@pexip.com>");
272
273   gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_h261_depay_process;
274   gstrtpbasedepayload_class->set_caps = gst_rtp_h261_depay_setcaps;
275
276   gobject_class->dispose = gst_rtp_h261_depay_dispose;
277
278   gstelement_class->change_state = gst_rtp_h261_depay_change_state;
279
280   GST_DEBUG_CATEGORY_INIT (rtph261depay_debug, "rtph261depay", 0,
281       "H261 Video RTP Depayloader");
282 }
283
284 static void
285 gst_rtp_h261_depay_init (GstRtpH261Depay * depay)
286 {
287   depay->adapter = gst_adapter_new ();
288   depay->leftover = NO_LEFTOVER;
289 }