2 * Copyright (C) <2008> Wim Taymans <wim.taymans@gmail.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.
26 #include <gst/rtp/gstrtpbuffer.h>
28 #include "gstrtpmp4apay.h"
30 GST_DEBUG_CATEGORY_STATIC (rtpmp4apay_debug);
31 #define GST_CAT_DEFAULT (rtpmp4apay_debug)
33 /* elementfactory information */
34 static const GstElementDetails gst_rtp_mp4apay_details =
35 GST_ELEMENT_DETAILS ("RTP MPEG4 audio payloader",
36 "Codec/Payloader/Network",
37 "Payload MPEG4 audio as RTP packets (RFC 3016)",
38 "Wim Taymans <wim.taymans@gmail.com>");
40 /* FIXME: add framed=(boolean)true once our encoders have this field set
41 * on their output caps */
42 static GstStaticPadTemplate gst_rtp_mp4a_pay_sink_template =
43 GST_STATIC_PAD_TEMPLATE ("sink",
46 GST_STATIC_CAPS ("audio/mpeg, mpegversion=(int)4")
49 static GstStaticPadTemplate gst_rtp_mp4a_pay_src_template =
50 GST_STATIC_PAD_TEMPLATE ("src",
53 GST_STATIC_CAPS ("application/x-rtp, "
54 "media = (string) \"audio\", "
55 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
56 "clock-rate = (int) [1, MAX ], "
57 "encoding-name = (string) \"MP4A-LATM\""
58 /* All optional parameters
60 * "cpresent = (string) \"0\""
66 static void gst_rtp_mp4a_pay_finalize (GObject * object);
68 static gboolean gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload,
70 static GstFlowReturn gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload *
71 payload, GstBuffer * buffer);
73 GST_BOILERPLATE (GstRtpMP4APay, gst_rtp_mp4a_pay, GstBaseRTPPayload,
74 GST_TYPE_BASE_RTP_PAYLOAD)
76 static void gst_rtp_mp4a_pay_base_init (gpointer klass)
78 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
80 gst_element_class_add_pad_template (element_class,
81 gst_static_pad_template_get (&gst_rtp_mp4a_pay_src_template));
82 gst_element_class_add_pad_template (element_class,
83 gst_static_pad_template_get (&gst_rtp_mp4a_pay_sink_template));
85 gst_element_class_set_details (element_class, &gst_rtp_mp4apay_details);
89 gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
91 GObjectClass *gobject_class;
92 GstBaseRTPPayloadClass *gstbasertppayload_class;
94 gobject_class = (GObjectClass *) klass;
95 gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
97 gobject_class->finalize = gst_rtp_mp4a_pay_finalize;
99 gstbasertppayload_class->set_caps = gst_rtp_mp4a_pay_setcaps;
100 gstbasertppayload_class->handle_buffer = gst_rtp_mp4a_pay_handle_buffer;
102 GST_DEBUG_CATEGORY_INIT (rtpmp4apay_debug, "rtpmp4apay", 0,
103 "MP4A-LATM RTP Payloader");
107 gst_rtp_mp4a_pay_init (GstRtpMP4APay * rtpmp4apay, GstRtpMP4APayClass * klass)
109 rtpmp4apay->rate = 90000;
110 rtpmp4apay->profile = g_strdup ("1");
114 gst_rtp_mp4a_pay_finalize (GObject * object)
116 GstRtpMP4APay *rtpmp4apay;
118 rtpmp4apay = GST_RTP_MP4A_PAY (object);
120 g_free (rtpmp4apay->params);
121 rtpmp4apay->params = NULL;
123 if (rtpmp4apay->config)
124 gst_buffer_unref (rtpmp4apay->config);
125 rtpmp4apay->config = NULL;
127 g_free (rtpmp4apay->profile);
128 rtpmp4apay->profile = NULL;
130 G_OBJECT_CLASS (parent_class)->finalize (object);
133 static unsigned sampling_table[16] = {
134 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
135 16000, 12000, 11025, 8000, 7350, 0, 0, 0
139 gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
148 data = GST_BUFFER_DATA (buffer);
149 size = GST_BUFFER_SIZE (buffer);
154 /* any object type is fine, we need to copy it to the profile-level-id field. */
155 objectType = (data[0] & 0xf8) >> 3;
159 samplingIdx = ((data[0] & 0x07) << 1) | ((data[1] & 0x80) >> 7);
160 /* only fixed values for now */
161 if (samplingIdx > 12 && samplingIdx != 15)
164 channelCfg = ((data[1] & 0x78) >> 3);
168 /* rtp rate depends on sampling rate of the audio */
169 if (samplingIdx == 15) {
173 /* index of 15 means we get the rate in the next 24 bits */
174 rtpmp4apay->rate = ((data[1] & 0x7f) << 17) |
175 ((data[2]) << 9) | ((data[3]) << 1) | ((data[4] & 0x80) >> 7);
177 /* else use the rate from the table */
178 rtpmp4apay->rate = sampling_table[samplingIdx];
180 /* extra rtp params contain the number of channels */
181 g_free (rtpmp4apay->params);
182 rtpmp4apay->params = g_strdup_printf ("%d", channelCfg);
183 /* audio stream type */
184 rtpmp4apay->streamtype = "5";
186 g_free (rtpmp4apay->profile);
187 rtpmp4apay->profile = g_strdup_printf ("%d", objectType);
189 GST_DEBUG_OBJECT (rtpmp4apay,
190 "objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
191 samplingIdx, rtpmp4apay->rate, channelCfg);
198 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
199 (NULL), ("config string too short, expected 2 bytes, got %d", size));
204 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
205 (NULL), ("invalid object type 0"));
210 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
211 (NULL), ("unsupported frequency index %d", samplingIdx));
216 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
217 (NULL), ("unsupported number of channels %d, must < 8", channelCfg));
223 gst_rtp_mp4a_pay_new_caps (GstRtpMP4APay * rtpmp4apay)
229 g_value_init (&v, GST_TYPE_BUFFER);
230 gst_value_set_buffer (&v, rtpmp4apay->config);
231 config = gst_value_serialize (&v);
233 res = gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4apay),
234 "cpresent", G_TYPE_STRING, "0", "config", G_TYPE_STRING, config, NULL);
243 gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
245 GstRtpMP4APay *rtpmp4apay;
246 GstStructure *structure;
247 const GValue *codec_data;
248 gboolean res, framed = TRUE;
250 rtpmp4apay = GST_RTP_MP4A_PAY (payload);
252 structure = gst_caps_get_structure (caps, 0);
254 codec_data = gst_structure_get_value (structure, "codec_data");
256 GST_LOG_OBJECT (rtpmp4apay, "got codec_data");
257 if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) {
258 GstBuffer *buffer, *cbuffer;
263 buffer = gst_value_get_buffer (codec_data);
264 GST_LOG_OBJECT (rtpmp4apay, "configuring codec_data");
267 res = gst_rtp_mp4a_pay_parse_audio_config (rtpmp4apay, buffer);
272 size = GST_BUFFER_SIZE (buffer);
273 data = GST_BUFFER_DATA (buffer);
275 /* make the StreamMuxConfig, we need 15 bits for the header */
276 config = g_malloc0 (size + 2);
278 /* Create StreamMuxConfig according to ISO/IEC 14496-3:
280 * audioMuxVersion == 0 (1 bit)
281 * allStreamsSameTimeFraming == 1 (1 bit)
282 * numSubFrames == numSubFrames (6 bits)
283 * numProgram == 0 (4 bits)
284 * numLayer == 0 (3 bits)
289 /* append the config bits, shifting them 1 bit left */
290 for (i = 0; i < size; i++) {
291 config[i + 1] |= ((data[i] & 0x80) >> 7);
292 config[i + 2] |= ((data[i] & 0x7f) << 1);
295 cbuffer = gst_buffer_new ();
296 GST_BUFFER_DATA (cbuffer) = config;
297 GST_BUFFER_MALLOCDATA (cbuffer) = config;
298 GST_BUFFER_SIZE (cbuffer) = size + 2;
300 /* now we can configure the buffer */
301 if (rtpmp4apay->config)
302 gst_buffer_unref (rtpmp4apay->config);
303 rtpmp4apay->config = cbuffer;
307 if (gst_structure_get_boolean (structure, "framed", &framed) && !framed) {
308 GST_WARNING_OBJECT (payload, "Need framed AAC data as input!");
311 gst_basertppayload_set_options (payload, "audio", TRUE, "MP4A-LATM",
314 res = gst_rtp_mp4a_pay_new_caps (rtpmp4apay);
321 GST_DEBUG_OBJECT (rtpmp4apay, "failed to parse config");
326 /* we expect buffers as exactly one complete AU
329 gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload * basepayload,
332 GstRtpMP4APay *rtpmp4apay;
335 guint count, mtu, size;
338 GstClockTime timestamp;
342 rtpmp4apay = GST_RTP_MP4A_PAY (basepayload);
344 size = GST_BUFFER_SIZE (buffer);
345 data = GST_BUFFER_DATA (buffer);
346 timestamp = GST_BUFFER_TIMESTAMP (buffer);
349 mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpmp4apay);
357 /* this will be the total lenght of the packet */
358 packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
361 /* first packet calculate space for the packet including the header */
363 while (count >= 0xff) {
370 /* fill one MTU or all available bytes */
371 towrite = MIN (packet_len, mtu);
373 /* this is the payload length */
374 payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);
376 GST_DEBUG_OBJECT (rtpmp4apay,
377 "avail %d, towrite %d, packet_len %d, payload_len %d", size, towrite,
378 packet_len, payload_len);
380 /* create buffer to hold the payload. */
381 outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
384 payload = gst_rtp_buffer_get_payload (outbuf);
387 /* first packet write the header */
389 while (count >= 0xff) {
398 /* copy data to payload */
399 memcpy (payload, data, payload_len);
403 /* marker only if the packet is complete */
404 gst_rtp_buffer_set_marker (outbuf, size == 0);
406 /* copy incomming timestamp (if any) to outgoing buffers */
407 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
409 ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmp4apay), outbuf);
414 gst_buffer_unref (buffer);
420 gst_rtp_mp4a_pay_plugin_init (GstPlugin * plugin)
422 return gst_element_register (plugin, "rtpmp4apay",
423 GST_RANK_NONE, GST_TYPE_RTP_MP4A_PAY);