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 /* FIXME: add framed=(boolean)true once our encoders have this field set
34 * on their output caps */
35 static GstStaticPadTemplate gst_rtp_mp4a_pay_sink_template =
36 GST_STATIC_PAD_TEMPLATE ("sink",
39 GST_STATIC_CAPS ("audio/mpeg, mpegversion=(int)4, "
40 "stream-format=(string)raw")
43 static GstStaticPadTemplate gst_rtp_mp4a_pay_src_template =
44 GST_STATIC_PAD_TEMPLATE ("src",
47 GST_STATIC_CAPS ("application/x-rtp, "
48 "media = (string) \"audio\", "
49 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
50 "clock-rate = (int) [1, MAX ], "
51 "encoding-name = (string) \"MP4A-LATM\""
52 /* All optional parameters
54 * "cpresent = (string) \"0\""
60 static void gst_rtp_mp4a_pay_finalize (GObject * object);
62 static gboolean gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload,
64 static GstFlowReturn gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload *
65 payload, GstBuffer * buffer);
67 GST_BOILERPLATE (GstRtpMP4APay, gst_rtp_mp4a_pay, GstBaseRTPPayload,
68 GST_TYPE_BASE_RTP_PAYLOAD)
70 static void gst_rtp_mp4a_pay_base_init (gpointer klass)
72 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
74 gst_element_class_add_static_pad_template (element_class,
75 &gst_rtp_mp4a_pay_src_template);
76 gst_element_class_add_static_pad_template (element_class,
77 &gst_rtp_mp4a_pay_sink_template);
79 gst_element_class_set_details_simple (element_class,
80 "RTP MPEG4 audio payloader", "Codec/Payloader/Network/RTP",
81 "Payload MPEG4 audio as RTP packets (RFC 3016)",
82 "Wim Taymans <wim.taymans@gmail.com>");
86 gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
88 GObjectClass *gobject_class;
89 GstBaseRTPPayloadClass *gstbasertppayload_class;
91 gobject_class = (GObjectClass *) klass;
92 gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
94 gobject_class->finalize = gst_rtp_mp4a_pay_finalize;
96 gstbasertppayload_class->set_caps = gst_rtp_mp4a_pay_setcaps;
97 gstbasertppayload_class->handle_buffer = gst_rtp_mp4a_pay_handle_buffer;
99 GST_DEBUG_CATEGORY_INIT (rtpmp4apay_debug, "rtpmp4apay", 0,
100 "MP4A-LATM RTP Payloader");
104 gst_rtp_mp4a_pay_init (GstRtpMP4APay * rtpmp4apay, GstRtpMP4APayClass * klass)
106 rtpmp4apay->rate = 90000;
107 rtpmp4apay->profile = g_strdup ("1");
111 gst_rtp_mp4a_pay_finalize (GObject * object)
113 GstRtpMP4APay *rtpmp4apay;
115 rtpmp4apay = GST_RTP_MP4A_PAY (object);
117 g_free (rtpmp4apay->params);
118 rtpmp4apay->params = NULL;
120 if (rtpmp4apay->config)
121 gst_buffer_unref (rtpmp4apay->config);
122 rtpmp4apay->config = NULL;
124 g_free (rtpmp4apay->profile);
125 rtpmp4apay->profile = NULL;
127 G_OBJECT_CLASS (parent_class)->finalize (object);
130 static const unsigned int sampling_table[16] = {
131 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
132 16000, 12000, 11025, 8000, 7350, 0, 0, 0
136 gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
145 data = GST_BUFFER_DATA (buffer);
146 size = GST_BUFFER_SIZE (buffer);
151 /* any object type is fine, we need to copy it to the profile-level-id field. */
152 objectType = (data[0] & 0xf8) >> 3;
156 samplingIdx = ((data[0] & 0x07) << 1) | ((data[1] & 0x80) >> 7);
157 /* only fixed values for now */
158 if (samplingIdx > 12 && samplingIdx != 15)
161 channelCfg = ((data[1] & 0x78) >> 3);
165 /* rtp rate depends on sampling rate of the audio */
166 if (samplingIdx == 15) {
170 /* index of 15 means we get the rate in the next 24 bits */
171 rtpmp4apay->rate = ((data[1] & 0x7f) << 17) |
172 ((data[2]) << 9) | ((data[3]) << 1) | ((data[4] & 0x80) >> 7);
174 /* else use the rate from the table */
175 rtpmp4apay->rate = sampling_table[samplingIdx];
177 /* extra rtp params contain the number of channels */
178 g_free (rtpmp4apay->params);
179 rtpmp4apay->params = g_strdup_printf ("%d", channelCfg);
180 /* audio stream type */
181 rtpmp4apay->streamtype = "5";
183 g_free (rtpmp4apay->profile);
184 rtpmp4apay->profile = g_strdup_printf ("%d", objectType);
186 GST_DEBUG_OBJECT (rtpmp4apay,
187 "objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
188 samplingIdx, rtpmp4apay->rate, channelCfg);
195 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
196 (NULL), ("config string too short, expected 2 bytes, got %d", size));
201 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
202 (NULL), ("invalid object type 0"));
207 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
208 (NULL), ("unsupported frequency index %d", samplingIdx));
213 GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
214 (NULL), ("unsupported number of channels %d, must < 8", channelCfg));
220 gst_rtp_mp4a_pay_new_caps (GstRtpMP4APay * rtpmp4apay)
226 g_value_init (&v, GST_TYPE_BUFFER);
227 gst_value_set_buffer (&v, rtpmp4apay->config);
228 config = gst_value_serialize (&v);
230 res = gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4apay),
231 "cpresent", G_TYPE_STRING, "0", "config", G_TYPE_STRING, config, NULL);
240 gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
242 GstRtpMP4APay *rtpmp4apay;
243 GstStructure *structure;
244 const GValue *codec_data;
245 gboolean res, framed = TRUE;
246 const gchar *stream_format;
248 rtpmp4apay = GST_RTP_MP4A_PAY (payload);
250 structure = gst_caps_get_structure (caps, 0);
252 /* this is already handled by the template caps, but it is better
253 * to leave here to have meaningful warning messages when linking
255 stream_format = gst_structure_get_string (structure, "stream-format");
257 if (strcmp (stream_format, "raw") != 0) {
258 GST_WARNING_OBJECT (rtpmp4apay, "AAC's stream-format must be 'raw', "
259 "%s is not supported", stream_format);
263 GST_WARNING_OBJECT (rtpmp4apay, "AAC's stream-format not specified, "
267 codec_data = gst_structure_get_value (structure, "codec_data");
269 GST_LOG_OBJECT (rtpmp4apay, "got codec_data");
270 if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) {
271 GstBuffer *buffer, *cbuffer;
276 buffer = gst_value_get_buffer (codec_data);
277 GST_LOG_OBJECT (rtpmp4apay, "configuring codec_data");
280 res = gst_rtp_mp4a_pay_parse_audio_config (rtpmp4apay, buffer);
285 size = GST_BUFFER_SIZE (buffer);
286 data = GST_BUFFER_DATA (buffer);
288 /* make the StreamMuxConfig, we need 15 bits for the header */
289 config = g_malloc0 (size + 2);
291 /* Create StreamMuxConfig according to ISO/IEC 14496-3:
293 * audioMuxVersion == 0 (1 bit)
294 * allStreamsSameTimeFraming == 1 (1 bit)
295 * numSubFrames == numSubFrames (6 bits)
296 * numProgram == 0 (4 bits)
297 * numLayer == 0 (3 bits)
302 /* append the config bits, shifting them 1 bit left */
303 for (i = 0; i < size; i++) {
304 config[i + 1] |= ((data[i] & 0x80) >> 7);
305 config[i + 2] |= ((data[i] & 0x7f) << 1);
308 cbuffer = gst_buffer_new ();
309 GST_BUFFER_DATA (cbuffer) = config;
310 GST_BUFFER_MALLOCDATA (cbuffer) = config;
311 GST_BUFFER_SIZE (cbuffer) = size + 2;
313 /* now we can configure the buffer */
314 if (rtpmp4apay->config)
315 gst_buffer_unref (rtpmp4apay->config);
316 rtpmp4apay->config = cbuffer;
320 if (gst_structure_get_boolean (structure, "framed", &framed) && !framed) {
321 GST_WARNING_OBJECT (payload, "Need framed AAC data as input!");
324 gst_basertppayload_set_options (payload, "audio", TRUE, "MP4A-LATM",
327 res = gst_rtp_mp4a_pay_new_caps (rtpmp4apay);
334 GST_DEBUG_OBJECT (rtpmp4apay, "failed to parse config");
339 /* we expect buffers as exactly one complete AU
342 gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload * basepayload,
345 GstRtpMP4APay *rtpmp4apay;
348 guint count, mtu, size;
351 GstClockTime timestamp;
355 rtpmp4apay = GST_RTP_MP4A_PAY (basepayload);
357 size = GST_BUFFER_SIZE (buffer);
358 data = GST_BUFFER_DATA (buffer);
359 timestamp = GST_BUFFER_TIMESTAMP (buffer);
362 mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpmp4apay);
370 /* this will be the total lenght of the packet */
371 packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
374 /* first packet calculate space for the packet including the header */
376 while (count >= 0xff) {
383 /* fill one MTU or all available bytes */
384 towrite = MIN (packet_len, mtu);
386 /* this is the payload length */
387 payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);
389 GST_DEBUG_OBJECT (rtpmp4apay,
390 "avail %d, towrite %d, packet_len %d, payload_len %d", size, towrite,
391 packet_len, payload_len);
393 /* create buffer to hold the payload. */
394 outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
397 payload = gst_rtp_buffer_get_payload (outbuf);
400 /* first packet write the header */
402 while (count >= 0xff) {
411 /* copy data to payload */
412 memcpy (payload, data, payload_len);
416 /* marker only if the packet is complete */
417 gst_rtp_buffer_set_marker (outbuf, size == 0);
419 /* copy incomming timestamp (if any) to outgoing buffers */
420 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
422 ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmp4apay), outbuf);
427 gst_buffer_unref (buffer);
433 gst_rtp_mp4a_pay_plugin_init (GstPlugin * plugin)
435 return gst_element_register (plugin, "rtpmp4apay",
436 GST_RANK_SECONDARY, GST_TYPE_RTP_MP4A_PAY);