1 /* GStreamer
2 * Copyright (C) <2010> 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 <string.h>
25
26 #include <gst/audio/audio.h>
27 #include <gst/rtp/gstrtpbuffer.h>
28
29 #include "gstrtpg722pay.h"
30 #include "gstrtpchannels.h"
31
32 GST_DEBUG_CATEGORY_STATIC (rtpg722pay_debug);
33 #define GST_CAT_DEFAULT (rtpg722pay_debug)
34
35 static GstStaticPadTemplate gst_rtp_g722_pay_sink_template =
36 GST_STATIC_PAD_TEMPLATE ("sink",
37 GST_PAD_SINK,
38 GST_PAD_ALWAYS,
39 GST_STATIC_CAPS ("audio/G722, " "rate = (int) 16000, " "channels = (int) 1")
40 );
41
42 static GstStaticPadTemplate gst_rtp_g722_pay_src_template =
43 GST_STATIC_PAD_TEMPLATE ("src",
44 GST_PAD_SRC,
45 GST_PAD_ALWAYS,
46 GST_STATIC_CAPS ("application/x-rtp, "
47 "media = (string) \"audio\", "
48 "encoding-name = (string) \"G722\", "
49 "payload = (int) " GST_RTP_PAYLOAD_G722_STRING ", "
50 "encoding-params = (string) 1, "
51 "clock-rate = (int) 8000; "
52 "application/x-rtp, "
53 "media = (string) \"audio\", "
54 "encoding-name = (string) \"G722\", "
55 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
56 "encoding-params = (string) 1, " "clock-rate = (int) 8000")
57 );
58
59 static gboolean gst_rtp_g722_pay_setcaps (GstRTPBasePayload * basepayload,
60 GstCaps * caps);
61 static GstCaps *gst_rtp_g722_pay_getcaps (GstRTPBasePayload * rtppayload,
62 GstPad * pad, GstCaps * filter);
63
64 #define gst_rtp_g722_pay_parent_class parent_class
65 G_DEFINE_TYPE (GstRtpG722Pay, gst_rtp_g722_pay,
66 GST_TYPE_RTP_BASE_AUDIO_PAYLOAD);
67
68 static void
gst_rtp_g722_pay_class_init(GstRtpG722PayClass * klass)69 gst_rtp_g722_pay_class_init (GstRtpG722PayClass * klass)
70 {
71 GstElementClass *gstelement_class;
72 GstRTPBasePayloadClass *gstrtpbasepayload_class;
73
74 GST_DEBUG_CATEGORY_INIT (rtpg722pay_debug, "rtpg722pay", 0,
75 "G722 RTP Payloader");
76
77 gstelement_class = (GstElementClass *) klass;
78 gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
79
80 gst_element_class_add_static_pad_template (gstelement_class,
81 &gst_rtp_g722_pay_src_template);
82 gst_element_class_add_static_pad_template (gstelement_class,
83 &gst_rtp_g722_pay_sink_template);
84
85 gst_element_class_set_static_metadata (gstelement_class,
86 "RTP audio payloader", "Codec/Payloader/Network/RTP",
87 "Payload-encode Raw audio into RTP packets (RFC 3551)",
88 "Wim Taymans <wim.taymans@gmail.com>");
89
90 gstrtpbasepayload_class->set_caps = gst_rtp_g722_pay_setcaps;
91 gstrtpbasepayload_class->get_caps = gst_rtp_g722_pay_getcaps;
92 }
93
94 static void
gst_rtp_g722_pay_init(GstRtpG722Pay * rtpg722pay)95 gst_rtp_g722_pay_init (GstRtpG722Pay * rtpg722pay)
96 {
97 GstRTPBaseAudioPayload *rtpbaseaudiopayload;
98
99 rtpbaseaudiopayload = GST_RTP_BASE_AUDIO_PAYLOAD (rtpg722pay);
100
101 GST_RTP_BASE_PAYLOAD (rtpg722pay)->pt = GST_RTP_PAYLOAD_G722;
102
103 /* tell rtpbaseaudiopayload that this is a sample based codec */
104 gst_rtp_base_audio_payload_set_sample_based (rtpbaseaudiopayload);
105 }
106
107 static gboolean
gst_rtp_g722_pay_setcaps(GstRTPBasePayload * basepayload,GstCaps * caps)108 gst_rtp_g722_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
109 {
110 GstRtpG722Pay *rtpg722pay;
111 GstStructure *structure;
112 gint rate, channels, clock_rate;
113 gboolean res;
114 gchar *params;
115 #if 0
116 GstAudioChannelPosition *pos;
117 const GstRTPChannelOrder *order;
118 #endif
119 GstRTPBaseAudioPayload *rtpbaseaudiopayload;
120
121 rtpbaseaudiopayload = GST_RTP_BASE_AUDIO_PAYLOAD (basepayload);
122 rtpg722pay = GST_RTP_G722_PAY (basepayload);
123
124 structure = gst_caps_get_structure (caps, 0);
125
126 /* first parse input caps */
127 if (!gst_structure_get_int (structure, "rate", &rate))
128 goto no_rate;
129
130 if (!gst_structure_get_int (structure, "channels", &channels))
131 goto no_channels;
132
133 /* FIXME: Do something with the channel positions */
134 #if 0
135 /* get the channel order */
136 pos = gst_audio_get_channel_positions (structure);
137 if (pos)
138 order = gst_rtp_channels_get_by_pos (channels, pos);
139 else
140 order = NULL;
141 #endif
142
143 /* Clock rate is always 8000 Hz for G722 according to
144 * RFC 3551 although the sampling rate is 16000 Hz */
145 clock_rate = 8000;
146
147 gst_rtp_base_payload_set_options (basepayload, "audio",
148 basepayload->pt != GST_RTP_PAYLOAD_G722, "G722", clock_rate);
149 params = g_strdup_printf ("%d", channels);
150
151 #if 0
152 if (!order && channels > 2) {
153 GST_ELEMENT_WARNING (rtpg722pay, STREAM, DECODE,
154 (NULL), ("Unknown channel order for %d channels", channels));
155 }
156
157 if (order && order->name) {
158 res = gst_rtp_base_payload_set_outcaps (basepayload,
159 "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
160 channels, "channel-order", G_TYPE_STRING, order->name, NULL);
161 } else {
162 #endif
163 res = gst_rtp_base_payload_set_outcaps (basepayload,
164 "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
165 channels, NULL);
166 #if 0
167 }
168 #endif
169
170 g_free (params);
171 #if 0
172 g_free (pos);
173 #endif
174
175 rtpg722pay->rate = rate;
176 rtpg722pay->channels = channels;
177
178 /* bits-per-sample is 4 * channels for G722, but as the RTP clock runs at
179 * half speed (8 instead of 16 khz), pretend it's 8 bits per sample
180 * channels. */
181 gst_rtp_base_audio_payload_set_samplebits_options (rtpbaseaudiopayload,
182 8 * rtpg722pay->channels);
183
184 return res;
185
186 /* ERRORS */
187 no_rate:
188 {
189 GST_DEBUG_OBJECT (rtpg722pay, "no rate given");
190 return FALSE;
191 }
192 no_channels:
193 {
194 GST_DEBUG_OBJECT (rtpg722pay, "no channels given");
195 return FALSE;
196 }
197 }
198
199 static GstCaps *
gst_rtp_g722_pay_getcaps(GstRTPBasePayload * rtppayload,GstPad * pad,GstCaps * filter)200 gst_rtp_g722_pay_getcaps (GstRTPBasePayload * rtppayload, GstPad * pad,
201 GstCaps * filter)
202 {
203 GstCaps *otherpadcaps;
204 GstCaps *caps;
205
206 otherpadcaps = gst_pad_get_allowed_caps (rtppayload->srcpad);
207 caps = gst_pad_get_pad_template_caps (pad);
208
209 if (otherpadcaps) {
210 if (!gst_caps_is_empty (otherpadcaps)) {
211 caps = gst_caps_make_writable (caps);
212 gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL);
213 gst_caps_set_simple (caps, "rate", G_TYPE_INT, 16000, NULL);
214 }
215 gst_caps_unref (otherpadcaps);
216 }
217
218 if (filter) {
219 GstCaps *tmp;
220
221 GST_DEBUG_OBJECT (rtppayload, "Intersect %" GST_PTR_FORMAT " and filter %"
222 GST_PTR_FORMAT, caps, filter);
223 tmp = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
224 gst_caps_unref (caps);
225 caps = tmp;
226 }
227
228 return caps;
229 }
230
231 gboolean
gst_rtp_g722_pay_plugin_init(GstPlugin * plugin)232 gst_rtp_g722_pay_plugin_init (GstPlugin * plugin)
233 {
234 return gst_element_register (plugin, "rtpg722pay",
235 GST_RANK_SECONDARY, GST_TYPE_RTP_G722_PAY);
236 }
237