2 * gstrtpvp8depay.c - Source for GstRtpVP8Depay
3 * Copyright (C) 2011 Sjoerd Simons <sjoerd@luon.net>
4 * Copyright (C) 2011 Collabora Ltd.
5 * Contact: Youness Alaoui <youness.alaoui@collabora.co.uk>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "gstrtpvp8depay.h"
29 GST_DEBUG_CATEGORY_STATIC (gst_rtp_vp8_depay_debug);
30 #define GST_CAT_DEFAULT gst_rtp_vp8_depay_debug
32 G_DEFINE_TYPE (GstRtpVP8Depay, gst_rtp_vp8_depay, GST_TYPE_RTP_BASE_DEPAYLOAD);
34 static GstStaticPadTemplate gst_rtp_vp8_depay_src_template =
35 GST_STATIC_PAD_TEMPLATE ("src",
38 GST_STATIC_CAPS ("video/x-vp8"));
40 static GstStaticPadTemplate gst_rtp_vp8_depay_sink_template =
41 GST_STATIC_PAD_TEMPLATE ("sink",
44 GST_STATIC_CAPS ("application/x-rtp, "
45 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ","
46 "clock-rate = (int) 90000,"
47 "media = (string) \"video\","
48 "encoding-name = (string) \"VP8-DRAFT-IETF-01\""));
51 gst_rtp_vp8_depay_init (GstRtpVP8Depay * self)
53 self->adapter = gst_adapter_new ();
54 self->started = FALSE;
57 static void gst_rtp_vp8_depay_dispose (GObject * object);
58 static GstBuffer *gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depayload,
60 static gboolean gst_rtp_vp8_depay_set_caps (GstRTPBaseDepayload * depayload,
64 gst_rtp_vp8_depay_class_init (GstRtpVP8DepayClass * gst_rtp_vp8_depay_class)
66 GObjectClass *object_class = G_OBJECT_CLASS (gst_rtp_vp8_depay_class);
67 GstElementClass *element_class = GST_ELEMENT_CLASS (gst_rtp_vp8_depay_class);
68 GstRTPBaseDepayloadClass *depay_class =
69 (GstRTPBaseDepayloadClass *) (gst_rtp_vp8_depay_class);
72 gst_element_class_add_pad_template (element_class,
73 gst_static_pad_template_get (&gst_rtp_vp8_depay_sink_template));
74 gst_element_class_add_pad_template (element_class,
75 gst_static_pad_template_get (&gst_rtp_vp8_depay_src_template));
77 gst_element_class_set_metadata (element_class, "RTP VP8 depayloader",
78 "Codec/Depayloader/Network/RTP",
79 "Extracts VP8 video from RTP packets)",
80 "Sjoerd Simons <sjoerd@luon.net>");
82 object_class->dispose = gst_rtp_vp8_depay_dispose;
84 depay_class->process = gst_rtp_vp8_depay_process;
85 depay_class->set_caps = gst_rtp_vp8_depay_set_caps;
87 GST_DEBUG_CATEGORY_INIT (gst_rtp_vp8_depay_debug, "rtpvp8depay", 0,
88 "VP8 Video RTP Depayloader");
92 gst_rtp_vp8_depay_dispose (GObject * object)
94 GstRtpVP8Depay *self = GST_RTP_VP8_DEPAY (object);
96 if (self->adapter != NULL)
97 g_object_unref (self->adapter);
100 /* release any references held by the object here */
102 if (G_OBJECT_CLASS (gst_rtp_vp8_depay_parent_class)->dispose)
103 G_OBJECT_CLASS (gst_rtp_vp8_depay_parent_class)->dispose (object);
107 gst_rtp_vp8_depay_process (GstRTPBaseDepayload * depay, GstBuffer * buf)
109 GstRtpVP8Depay *self = GST_RTP_VP8_DEPAY (depay);
114 GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
116 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
117 GST_LOG_OBJECT (self, "Discontinuity, flushing adapter");
118 gst_adapter_clear (self->adapter);
119 self->started = FALSE;
122 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuffer);
123 size = gst_rtp_buffer_get_payload_len (&rtpbuffer);
125 /* At least one header and one vp8 byte */
126 if (G_UNLIKELY (size < 2))
129 data = gst_rtp_buffer_get_payload (&rtpbuffer);
131 if (G_UNLIKELY (!self->started)) {
132 /* Check if this is the start of a VP8 frame, otherwise bail */
133 /* S=1 and PartID= 0 */
134 if ((data[0] & 0x1F) != 0x10)
137 self->started = TRUE;
141 /* Check X optional header */
142 if ((data[0] & 0x80) != 0) {
144 /* Check I optional header */
145 if ((data[1] & 0x80) != 0) {
147 if (G_UNLIKELY (offset + 2 >= size))
149 /* Check for 16 bits PictureID */
150 if ((data[2] & 0x80) != 0)
153 /* Check L optional header */
154 if ((data[1] & 0x40) != 0)
156 /* Check T optional header */
157 if ((data[1] & 0x20) != 0)
161 if (G_UNLIKELY (offset >= size))
164 payload = gst_rtp_buffer_get_payload_subbuffer (&rtpbuffer, offset, -1);
165 gst_adapter_push (self->adapter, payload);
167 /* Marker indicates that it was the last rtp packet for this frame */
168 if (gst_rtp_buffer_get_marker (&rtpbuffer)) {
171 out = gst_adapter_take_buffer (self->adapter,
172 gst_adapter_available (self->adapter));
174 self->started = FALSE;
175 gst_rtp_buffer_unmap (&rtpbuffer);
180 gst_rtp_buffer_unmap (&rtpbuffer);
184 GST_LOG_OBJECT (self, "Invalid rtp packet (too small), ignoring");
185 gst_adapter_clear (self->adapter);
186 self->started = FALSE;
192 gst_rtp_vp8_depay_set_caps (GstRTPBaseDepayload * depayload, GstCaps * caps)
194 GstCaps *srccaps = gst_caps_new_simple ("video/x-vp8",
195 "framerate", GST_TYPE_FRACTION, 0, 1,
198 gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps);
199 gst_caps_unref (srccaps);
205 gst_rtp_vp8_depay_plugin_init (GstPlugin * plugin)
207 return gst_element_register (plugin, "rtpvp8depay",
208 GST_RANK_MARGINAL, GST_TYPE_RTP_VP8_DEPAY);