• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2005> Wim Taymans <wim.taymans@gmail.com>
3  *
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.
8  *
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.
13  *
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <gst/rtp/gstrtpbuffer.h>
25 
26 #include <string.h>
27 #include "gstrtpelements.h"
28 #include "gstrtpmp2tdepay.h"
29 #include "gstrtputils.h"
30 
31 /* RtpMP2TDepay signals and args */
32 enum
33 {
34   /* FILL ME */
35   LAST_SIGNAL
36 };
37 
38 #define DEFAULT_SKIP_FIRST_BYTES	0
39 
40 enum
41 {
42   PROP_0,
43   PROP_SKIP_FIRST_BYTES
44 };
45 
46 static GstStaticPadTemplate gst_rtp_mp2t_depay_src_template =
47 GST_STATIC_PAD_TEMPLATE ("src",
48     GST_PAD_SRC,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS ("video/mpegts,"
51         "packetsize=(int)188," "systemstream=(boolean)true")
52     );
53 
54 static GstStaticPadTemplate gst_rtp_mp2t_depay_sink_template =
55     GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("application/x-rtp, "
59         "media = (string) \"video\", "
60         "clock-rate = (int) [1, MAX ], "
61         "encoding-name = (string) { MP2T, MP2T-ES } ;"
62         /* All optional parameters
63          *
64          * "profile-level-id=[1,MAX]"
65          * "config="
66          */
67         "application/x-rtp, "
68         "media = (string) \"video\", "
69         "payload = (int) " GST_RTP_PAYLOAD_MP2T_STRING ", "
70         "clock-rate = (int) [1, MAX ]")
71     );
72 
73 G_DEFINE_TYPE (GstRtpMP2TDepay, gst_rtp_mp2t_depay,
74     GST_TYPE_RTP_BASE_DEPAYLOAD);
75 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (rtpmp2tdepay, "rtpmp2tdepay",
76     GST_RANK_SECONDARY, GST_TYPE_RTP_MP2T_DEPAY, rtp_element_init (plugin));
77 
78 static gboolean gst_rtp_mp2t_depay_setcaps (GstRTPBaseDepayload * depayload,
79     GstCaps * caps);
80 static GstBuffer *gst_rtp_mp2t_depay_process (GstRTPBaseDepayload * depayload,
81     GstRTPBuffer * rtp);
82 
83 static void gst_rtp_mp2t_depay_set_property (GObject * object, guint prop_id,
84     const GValue * value, GParamSpec * pspec);
85 static void gst_rtp_mp2t_depay_get_property (GObject * object, guint prop_id,
86     GValue * value, GParamSpec * pspec);
87 
88 static void
gst_rtp_mp2t_depay_class_init(GstRtpMP2TDepayClass * klass)89 gst_rtp_mp2t_depay_class_init (GstRtpMP2TDepayClass * klass)
90 {
91   GObjectClass *gobject_class;
92   GstElementClass *gstelement_class;
93   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
94 
95   gobject_class = (GObjectClass *) klass;
96   gstelement_class = (GstElementClass *) klass;
97   gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
98 
99   gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_mp2t_depay_process;
100   gstrtpbasedepayload_class->set_caps = gst_rtp_mp2t_depay_setcaps;
101 
102   gobject_class->set_property = gst_rtp_mp2t_depay_set_property;
103   gobject_class->get_property = gst_rtp_mp2t_depay_get_property;
104 
105   gst_element_class_add_static_pad_template (gstelement_class,
106       &gst_rtp_mp2t_depay_src_template);
107   gst_element_class_add_static_pad_template (gstelement_class,
108       &gst_rtp_mp2t_depay_sink_template);
109 
110   gst_element_class_set_static_metadata (gstelement_class,
111       "RTP MPEG Transport Stream depayloader", "Codec/Depayloader/Network/RTP",
112       "Extracts MPEG2 TS from RTP packets (RFC 2250)",
113       "Wim Taymans <wim.taymans@gmail.com>, "
114       "Thijs Vermeir <thijs.vermeir@barco.com>");
115 
116   g_object_class_install_property (gobject_class, PROP_SKIP_FIRST_BYTES,
117       g_param_spec_uint ("skip-first-bytes",
118           "Skip first bytes",
119           "The amount of bytes that need to be skipped at the beginning of the payload",
120           0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
121 
122 }
123 
124 static void
gst_rtp_mp2t_depay_init(GstRtpMP2TDepay * rtpmp2tdepay)125 gst_rtp_mp2t_depay_init (GstRtpMP2TDepay * rtpmp2tdepay)
126 {
127   rtpmp2tdepay->skip_first_bytes = DEFAULT_SKIP_FIRST_BYTES;
128 }
129 
130 static gboolean
gst_rtp_mp2t_depay_setcaps(GstRTPBaseDepayload * depayload,GstCaps * caps)131 gst_rtp_mp2t_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
132 {
133   GstCaps *srccaps;
134   GstStructure *structure;
135   gint clock_rate;
136   gboolean res;
137 
138   structure = gst_caps_get_structure (caps, 0);
139   if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
140     clock_rate = 90000;         /* default */
141   depayload->clock_rate = clock_rate;
142 
143   srccaps = gst_caps_new_simple ("video/mpegts",
144       "packetsize", G_TYPE_INT, 188,
145       "systemstream", G_TYPE_BOOLEAN, TRUE, NULL);
146   res = gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps);
147   gst_caps_unref (srccaps);
148 
149   return res;
150 }
151 
152 static GstBuffer *
gst_rtp_mp2t_depay_process(GstRTPBaseDepayload * depayload,GstRTPBuffer * rtp)153 gst_rtp_mp2t_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
154 {
155   GstRtpMP2TDepay *rtpmp2tdepay;
156   GstBuffer *outbuf;
157   gint payload_len, leftover;
158 
159   rtpmp2tdepay = GST_RTP_MP2T_DEPAY (depayload);
160 
161   payload_len = gst_rtp_buffer_get_payload_len (rtp);
162 
163   if (G_UNLIKELY (payload_len <= rtpmp2tdepay->skip_first_bytes))
164     goto empty_packet;
165 
166   payload_len -= rtpmp2tdepay->skip_first_bytes;
167 
168   /* RFC 2250
169    *
170    * 2. Encapsulation of MPEG System and Transport Streams
171    *
172    * For MPEG2 Transport Streams the RTP payload will contain an integral
173    * number of MPEG transport packets.
174    */
175   leftover = payload_len % 188;
176   if (G_UNLIKELY (leftover)) {
177     GST_WARNING ("We don't have an integral number of buffers (leftover: %d)",
178         leftover);
179 
180     payload_len -= leftover;
181   }
182 
183   outbuf =
184       gst_rtp_buffer_get_payload_subbuffer (rtp,
185       rtpmp2tdepay->skip_first_bytes, payload_len);
186 
187   if (outbuf) {
188     GST_DEBUG ("gst_rtp_mp2t_depay_chain: pushing buffer of size %"
189         G_GSIZE_FORMAT, gst_buffer_get_size (outbuf));
190 
191     gst_rtp_drop_meta (GST_ELEMENT_CAST (depayload), outbuf, 0);
192   }
193 
194   return outbuf;
195 
196   /* ERRORS */
197 empty_packet:
198   {
199     GST_ELEMENT_WARNING (rtpmp2tdepay, STREAM, DECODE,
200         (NULL), ("Packet was empty"));
201     return NULL;
202   }
203 }
204 
205 static void
gst_rtp_mp2t_depay_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)206 gst_rtp_mp2t_depay_set_property (GObject * object, guint prop_id,
207     const GValue * value, GParamSpec * pspec)
208 {
209   GstRtpMP2TDepay *rtpmp2tdepay;
210 
211   rtpmp2tdepay = GST_RTP_MP2T_DEPAY (object);
212 
213   switch (prop_id) {
214     case PROP_SKIP_FIRST_BYTES:
215       rtpmp2tdepay->skip_first_bytes = g_value_get_uint (value);
216       break;
217     default:
218       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
219       break;
220   }
221 }
222 
223 static void
gst_rtp_mp2t_depay_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)224 gst_rtp_mp2t_depay_get_property (GObject * object, guint prop_id,
225     GValue * value, GParamSpec * pspec)
226 {
227   GstRtpMP2TDepay *rtpmp2tdepay;
228 
229   rtpmp2tdepay = GST_RTP_MP2T_DEPAY (object);
230 
231   switch (prop_id) {
232     case PROP_SKIP_FIRST_BYTES:
233       g_value_set_uint (value, rtpmp2tdepay->skip_first_bytes);
234       break;
235     default:
236       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
237       break;
238   }
239 }
240