2 * Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
24 #include <gst/rtp/gstrtpbuffer.h>
27 #include "gstrtpmp4vdepay.h"
29 GST_DEBUG_CATEGORY_STATIC (rtpmp4vdepay_debug);
30 #define GST_CAT_DEFAULT (rtpmp4vdepay_debug)
32 /* elementfactory information */
33 static const GstElementDetails gst_rtp_mp4vdepay_details =
34 GST_ELEMENT_DETAILS ("RTP packet depayloader",
35 "Codec/Depayloader/Network",
36 "Extracts MPEG4 video from RTP packets (RFC 3016)",
37 "Wim Taymans <wim@fluendo.com>");
39 static GstStaticPadTemplate gst_rtp_mp4v_depay_src_template =
40 GST_STATIC_PAD_TEMPLATE ("src",
43 GST_STATIC_CAPS ("video/mpeg,"
44 "mpegversion=(int) 4," "systemstream=(boolean)false")
47 static GstStaticPadTemplate gst_rtp_mp4v_depay_sink_template =
48 GST_STATIC_PAD_TEMPLATE ("sink",
51 GST_STATIC_CAPS ("application/x-rtp, "
52 "media = (string) \"video\", "
53 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
54 "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"MP4V-ES\""
55 /* All optional parameters
57 * "profile-level-id=[1,MAX]"
63 GST_BOILERPLATE (GstRtpMP4VDepay, gst_rtp_mp4v_depay, GstBaseRTPDepayload,
64 GST_TYPE_BASE_RTP_DEPAYLOAD);
66 static void gst_rtp_mp4v_depay_finalize (GObject * object);
68 static gboolean gst_rtp_mp4v_depay_setcaps (GstBaseRTPDepayload * depayload,
70 static GstBuffer *gst_rtp_mp4v_depay_process (GstBaseRTPDepayload * depayload,
73 static GstStateChangeReturn gst_rtp_mp4v_depay_change_state (GstElement *
74 element, GstStateChange transition);
78 gst_rtp_mp4v_depay_base_init (gpointer klass)
80 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
82 gst_element_class_add_pad_template (element_class,
83 gst_static_pad_template_get (&gst_rtp_mp4v_depay_src_template));
84 gst_element_class_add_pad_template (element_class,
85 gst_static_pad_template_get (&gst_rtp_mp4v_depay_sink_template));
87 gst_element_class_set_details (element_class, &gst_rtp_mp4vdepay_details);
91 gst_rtp_mp4v_depay_class_init (GstRtpMP4VDepayClass * klass)
93 GObjectClass *gobject_class;
94 GstElementClass *gstelement_class;
95 GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
97 gobject_class = (GObjectClass *) klass;
98 gstelement_class = (GstElementClass *) klass;
99 gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
101 gobject_class->finalize = gst_rtp_mp4v_depay_finalize;
103 gstelement_class->change_state = gst_rtp_mp4v_depay_change_state;
105 gstbasertpdepayload_class->process = gst_rtp_mp4v_depay_process;
106 gstbasertpdepayload_class->set_caps = gst_rtp_mp4v_depay_setcaps;
108 GST_DEBUG_CATEGORY_INIT (rtpmp4vdepay_debug, "rtpmp4vdepay", 0,
109 "MPEG4 video RTP Depayloader");
113 gst_rtp_mp4v_depay_init (GstRtpMP4VDepay * rtpmp4vdepay,
114 GstRtpMP4VDepayClass * klass)
116 rtpmp4vdepay->adapter = gst_adapter_new ();
120 gst_rtp_mp4v_depay_finalize (GObject * object)
122 GstRtpMP4VDepay *rtpmp4vdepay;
124 rtpmp4vdepay = GST_RTP_MP4V_DEPAY (object);
126 g_object_unref (rtpmp4vdepay->adapter);
127 rtpmp4vdepay->adapter = NULL;
129 G_OBJECT_CLASS (parent_class)->finalize (object);
133 gst_rtp_mp4v_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
135 GstStructure *structure;
136 GstRtpMP4VDepay *rtpmp4vdepay;
139 gint clock_rate = 90000; /* default */
141 rtpmp4vdepay = GST_RTP_MP4V_DEPAY (depayload);
143 structure = gst_caps_get_structure (caps, 0);
145 if (gst_structure_has_field (structure, "clock-rate"))
146 gst_structure_get_int (structure, "clock-rate", &clock_rate);
147 depayload->clock_rate = clock_rate;
149 srccaps = gst_caps_new_simple ("video/mpeg",
150 "mpegversion", G_TYPE_INT, 4,
151 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
153 if ((str = gst_structure_get_string (structure, "config"))) {
156 g_value_init (&v, GST_TYPE_BUFFER);
157 if (gst_value_deserialize (&v, str)) {
160 buffer = gst_value_get_buffer (&v);
161 gst_buffer_ref (buffer);
164 gst_caps_set_simple (srccaps,
165 "codec_data", GST_TYPE_BUFFER, buffer, NULL);
167 g_warning ("cannot convert config to buffer");
170 gst_pad_set_caps (depayload->srcpad, srccaps);
171 gst_caps_unref (srccaps);
177 gst_rtp_mp4v_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
179 GstRtpMP4VDepay *rtpmp4vdepay;
182 rtpmp4vdepay = GST_RTP_MP4V_DEPAY (depayload);
184 if (!gst_rtp_buffer_validate (buf))
187 /* flush remaining data on discont */
188 if (GST_BUFFER_IS_DISCONT (buf))
189 gst_adapter_clear (rtpmp4vdepay->adapter);
191 outbuf = gst_rtp_buffer_get_payload_buffer (buf);
192 gst_adapter_push (rtpmp4vdepay->adapter, outbuf);
194 /* if this was the last packet of the VOP, create and push a buffer */
195 if (gst_rtp_buffer_get_marker (buf)) {
198 avail = gst_adapter_available (rtpmp4vdepay->adapter);
200 outbuf = gst_adapter_take_buffer (rtpmp4vdepay->adapter, avail);
201 gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
203 GST_DEBUG ("gst_rtp_mp4v_depay_chain: pushing buffer of size %d",
204 GST_BUFFER_SIZE (outbuf));
212 GST_ELEMENT_WARNING (rtpmp4vdepay, STREAM, DECODE,
213 ("Packet did not validate"), (NULL));
218 static GstStateChangeReturn
219 gst_rtp_mp4v_depay_change_state (GstElement * element,
220 GstStateChange transition)
222 GstRtpMP4VDepay *rtpmp4vdepay;
223 GstStateChangeReturn ret;
225 rtpmp4vdepay = GST_RTP_MP4V_DEPAY (element);
227 switch (transition) {
228 case GST_STATE_CHANGE_READY_TO_PAUSED:
229 gst_adapter_clear (rtpmp4vdepay->adapter);
235 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
237 switch (transition) {
245 gst_rtp_mp4v_depay_plugin_init (GstPlugin * plugin)
247 return gst_element_register (plugin, "rtpmp4vdepay",
248 GST_RANK_MARGINAL, GST_TYPE_RTP_MP4V_DEPAY);