Sebastian Dröge | d87f6cf | 2013-12-04 21:17:03 +0100 | [diff] [blame] | 1 | /* GStreamer |
| 2 | * Copyright (C) 2013 Sebastian Dröge <sebastian@centricular.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 | /** |
| 21 | * SECTION:element-rtpstreamdepay |
| 22 | * |
| 23 | * Implements stream depayloading of RTP and RTCP packets for connection-oriented |
| 24 | * transport protocols according to RFC4571. |
| 25 | * <refsect2> |
| 26 | * <title>Example launch line</title> |
| 27 | * |[ |
| 28 | * gst-launch-1.0 audiotestsrc ! "audio/x-raw,rate=48000" ! vorbisenc ! rtpvorbispay config-interval=1 ! rtpstreampay ! tcpserversink port=5678 |
| 29 | * gst-launch-1.0 tcpclientsrc port=5678 host=127.0.0.1 do-timestamp=true ! "application/x-rtp-stream,media=audio,clock-rate=48000,encoding-name=VORBIS" ! rtpstreamdepay ! rtpvorbisdepay ! decodebin ! audioconvert ! audioresample ! autoaudiosink |
| 30 | * ]| |
| 31 | * </refsect2> |
| 32 | */ |
| 33 | |
| 34 | #ifdef HAVE_CONFIG_H |
| 35 | #include "config.h" |
| 36 | #endif |
| 37 | |
| 38 | #include "gstrtpstreamdepay.h" |
| 39 | |
| 40 | GST_DEBUG_CATEGORY (gst_rtp_stream_depay_debug); |
| 41 | #define GST_CAT_DEFAULT gst_rtp_stream_depay_debug |
| 42 | |
| 43 | static GstStaticPadTemplate src_template = |
| 44 | GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, |
| 45 | GST_PAD_ALWAYS, |
| 46 | GST_STATIC_CAPS ("application/x-rtp; application/x-rtcp;" |
| 47 | "application/x-srtp; application/x-srtcp") |
| 48 | ); |
| 49 | |
| 50 | static GstStaticPadTemplate sink_template = |
| 51 | GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, |
| 52 | GST_PAD_ALWAYS, |
| 53 | GST_STATIC_CAPS ("application/x-rtp-stream; application/x-rtcp-stream;" |
| 54 | "application/x-srtp-stream; application/x-srtcp-stream") |
| 55 | ); |
| 56 | |
| 57 | #define parent_class gst_rtp_stream_depay_parent_class |
| 58 | G_DEFINE_TYPE (GstRtpStreamDepay, gst_rtp_stream_depay, GST_TYPE_BASE_PARSE); |
| 59 | |
| 60 | static gboolean gst_rtp_stream_depay_set_sink_caps (GstBaseParse * parse, |
| 61 | GstCaps * caps); |
| 62 | static GstCaps *gst_rtp_stream_depay_get_sink_caps (GstBaseParse * parse, |
| 63 | GstCaps * filter); |
| 64 | static GstFlowReturn gst_rtp_stream_depay_handle_frame (GstBaseParse * parse, |
| 65 | GstBaseParseFrame * frame, gint * skipsize); |
| 66 | |
Sebastian Dröge | c9ea954 | 2015-08-04 20:59:17 +0300 | [diff] [blame] | 67 | static gboolean gst_rtp_stream_depay_sink_activate (GstPad * pad, |
| 68 | GstObject * parent); |
| 69 | |
Sebastian Dröge | d87f6cf | 2013-12-04 21:17:03 +0100 | [diff] [blame] | 70 | static void |
| 71 | gst_rtp_stream_depay_class_init (GstRtpStreamDepayClass * klass) |
| 72 | { |
| 73 | GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); |
| 74 | GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass); |
| 75 | |
| 76 | GST_DEBUG_CATEGORY_INIT (gst_rtp_stream_depay_debug, "rtpstreamdepay", 0, |
| 77 | "RTP stream depayloader"); |
| 78 | |
| 79 | gst_element_class_add_pad_template (gstelement_class, |
| 80 | gst_static_pad_template_get (&src_template)); |
| 81 | gst_element_class_add_pad_template (gstelement_class, |
| 82 | gst_static_pad_template_get (&sink_template)); |
| 83 | |
| 84 | gst_element_class_set_static_metadata (gstelement_class, |
| 85 | "RTP Stream Depayloading", "Codec/Depayloader/Network", |
| 86 | "Depayloads RTP/RTCP packets for streaming protocols according to RFC4571", |
| 87 | "Sebastian Dröge <sebastian@centricular.com>"); |
| 88 | |
| 89 | parse_class->set_sink_caps = |
| 90 | GST_DEBUG_FUNCPTR (gst_rtp_stream_depay_set_sink_caps); |
| 91 | parse_class->get_sink_caps = |
| 92 | GST_DEBUG_FUNCPTR (gst_rtp_stream_depay_get_sink_caps); |
| 93 | parse_class->handle_frame = |
| 94 | GST_DEBUG_FUNCPTR (gst_rtp_stream_depay_handle_frame); |
| 95 | } |
| 96 | |
| 97 | static void |
| 98 | gst_rtp_stream_depay_init (GstRtpStreamDepay * self) |
| 99 | { |
| 100 | gst_base_parse_set_min_frame_size (GST_BASE_PARSE (self), 2); |
Sebastian Dröge | c9ea954 | 2015-08-04 20:59:17 +0300 | [diff] [blame] | 101 | |
| 102 | /* Force activation in push mode. We need to get a caps event from upstream |
| 103 | * to know the full RTP caps. */ |
| 104 | gst_pad_set_activate_function (GST_BASE_PARSE_SINK_PAD (self), |
| 105 | gst_rtp_stream_depay_sink_activate); |
Sebastian Dröge | d87f6cf | 2013-12-04 21:17:03 +0100 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | static gboolean |
| 109 | gst_rtp_stream_depay_set_sink_caps (GstBaseParse * parse, GstCaps * caps) |
| 110 | { |
| 111 | GstCaps *othercaps; |
| 112 | GstStructure *structure; |
| 113 | gboolean ret; |
| 114 | |
| 115 | othercaps = gst_caps_copy (caps); |
| 116 | structure = gst_caps_get_structure (othercaps, 0); |
| 117 | |
| 118 | if (gst_structure_has_name (structure, "application/x-rtp-stream")) |
| 119 | gst_structure_set_name (structure, "application/x-rtp"); |
| 120 | else if (gst_structure_has_name (structure, "application/x-rtcp-stream")) |
| 121 | gst_structure_set_name (structure, "application/x-rtcp"); |
| 122 | else if (gst_structure_has_name (structure, "application/x-srtp-stream")) |
| 123 | gst_structure_set_name (structure, "application/x-srtp"); |
| 124 | else |
| 125 | gst_structure_set_name (structure, "application/x-srtcp"); |
| 126 | |
| 127 | ret = gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), othercaps); |
| 128 | gst_caps_unref (othercaps); |
| 129 | |
| 130 | return ret; |
| 131 | } |
| 132 | |
| 133 | static GstCaps * |
| 134 | gst_rtp_stream_depay_get_sink_caps (GstBaseParse * parse, GstCaps * filter) |
| 135 | { |
| 136 | GstCaps *peerfilter = NULL, *peercaps, *templ; |
| 137 | GstCaps *res; |
| 138 | GstStructure *structure; |
| 139 | guint i, n; |
| 140 | |
| 141 | if (filter) { |
| 142 | peerfilter = gst_caps_copy (filter); |
| 143 | n = gst_caps_get_size (peerfilter); |
| 144 | for (i = 0; i < n; i++) { |
| 145 | structure = gst_caps_get_structure (peerfilter, i); |
| 146 | |
| 147 | if (gst_structure_has_name (structure, "application/x-rtp-stream")) |
| 148 | gst_structure_set_name (structure, "application/x-rtp"); |
| 149 | else if (gst_structure_has_name (structure, "application/x-rtcp-stream")) |
| 150 | gst_structure_set_name (structure, "application/x-rtcp"); |
| 151 | else if (gst_structure_has_name (structure, "application/x-srtp-stream")) |
| 152 | gst_structure_set_name (structure, "application/x-srtp"); |
| 153 | else |
| 154 | gst_structure_set_name (structure, "application/x-srtcp"); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)); |
| 159 | peercaps = |
| 160 | gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), peerfilter); |
| 161 | |
| 162 | if (peercaps) { |
| 163 | /* Rename structure names */ |
| 164 | peercaps = gst_caps_make_writable (peercaps); |
| 165 | n = gst_caps_get_size (peercaps); |
| 166 | for (i = 0; i < n; i++) { |
| 167 | structure = gst_caps_get_structure (peercaps, i); |
| 168 | |
| 169 | if (gst_structure_has_name (structure, "application/x-rtp")) |
| 170 | gst_structure_set_name (structure, "application/x-rtp-stream"); |
| 171 | else if (gst_structure_has_name (structure, "application/x-rtcp")) |
| 172 | gst_structure_set_name (structure, "application/x-rtcp-stream"); |
| 173 | else if (gst_structure_has_name (structure, "application/x-srtp")) |
| 174 | gst_structure_set_name (structure, "application/x-srtp-stream"); |
| 175 | else |
| 176 | gst_structure_set_name (structure, "application/x-srtcp-stream"); |
| 177 | } |
| 178 | |
| 179 | res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST); |
| 180 | gst_caps_unref (peercaps); |
| 181 | } else { |
| 182 | res = templ; |
| 183 | } |
| 184 | |
| 185 | if (filter) { |
| 186 | GstCaps *intersection; |
| 187 | |
| 188 | intersection = |
| 189 | gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); |
| 190 | gst_caps_unref (res); |
| 191 | res = intersection; |
| 192 | |
| 193 | gst_caps_unref (peerfilter); |
| 194 | } |
| 195 | |
| 196 | return res; |
| 197 | } |
| 198 | |
| 199 | static GstFlowReturn |
| 200 | gst_rtp_stream_depay_handle_frame (GstBaseParse * parse, |
| 201 | GstBaseParseFrame * frame, gint * skipsize) |
| 202 | { |
| 203 | gsize buf_size; |
| 204 | guint16 size; |
| 205 | |
| 206 | if (gst_buffer_extract (frame->buffer, 0, &size, 2) != 2) |
| 207 | return GST_FLOW_ERROR; |
| 208 | |
| 209 | size = GUINT16_FROM_BE (size); |
| 210 | buf_size = gst_buffer_get_size (frame->buffer); |
| 211 | |
| 212 | /* Need more data */ |
| 213 | if (size + 2 > buf_size) |
| 214 | return GST_FLOW_OK; |
| 215 | |
| 216 | frame->out_buffer = |
| 217 | gst_buffer_copy_region (frame->buffer, GST_BUFFER_COPY_ALL, 2, size); |
| 218 | |
| 219 | return gst_base_parse_finish_frame (parse, frame, size + 2); |
| 220 | } |
| 221 | |
Sebastian Dröge | c9ea954 | 2015-08-04 20:59:17 +0300 | [diff] [blame] | 222 | static gboolean |
| 223 | gst_rtp_stream_depay_sink_activate (GstPad * pad, GstObject * parent) |
| 224 | { |
| 225 | return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); |
| 226 | } |
| 227 | |
Sebastian Dröge | d87f6cf | 2013-12-04 21:17:03 +0100 | [diff] [blame] | 228 | gboolean |
| 229 | gst_rtp_stream_depay_plugin_init (GstPlugin * plugin) |
| 230 | { |
| 231 | return gst_element_register (plugin, "rtpstreamdepay", |
| 232 | GST_RANK_NONE, GST_TYPE_RTP_STREAM_DEPAY); |
| 233 | } |