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