rtpac3depay: should output audio/x-ac3 not audio/ac3
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / rtp / gstrtpmp4apay.c
1 /* GStreamer
2  * Copyright (C) <2008> 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/rtp/gstrtpbuffer.h>
27 #include <gst/audio/audio.h>
28
29 #include "gstrtpelements.h"
30 #include "gstrtpmp4apay.h"
31 #include "gstrtputils.h"
32
33 GST_DEBUG_CATEGORY_STATIC (rtpmp4apay_debug);
34 #define GST_CAT_DEFAULT (rtpmp4apay_debug)
35
36 /* FIXME: add framed=(boolean)true once our encoders have this field set
37  * on their output caps */
38 static GstStaticPadTemplate gst_rtp_mp4a_pay_sink_template =
39 GST_STATIC_PAD_TEMPLATE ("sink",
40     GST_PAD_SINK,
41     GST_PAD_ALWAYS,
42     GST_STATIC_CAPS ("audio/mpeg, mpegversion=(int)4, "
43         "stream-format=(string)raw")
44     );
45
46 static GstStaticPadTemplate gst_rtp_mp4a_pay_src_template =
47 GST_STATIC_PAD_TEMPLATE ("src",
48     GST_PAD_SRC,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS ("application/x-rtp, "
51         "media = (string) \"audio\", "
52         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
53         "clock-rate = (int) [1, MAX ], "
54         "encoding-name = (string) \"MP4A-LATM\""
55         /* All optional parameters
56          *
57          * "cpresent = (string) \"0\""
58          * "config=" 
59          */
60     )
61     );
62
63 static void gst_rtp_mp4a_pay_finalize (GObject * object);
64
65 static gboolean gst_rtp_mp4a_pay_setcaps (GstRTPBasePayload * payload,
66     GstCaps * caps);
67 static GstFlowReturn gst_rtp_mp4a_pay_handle_buffer (GstRTPBasePayload *
68     payload, GstBuffer * buffer);
69
70 #define gst_rtp_mp4a_pay_parent_class parent_class
71 G_DEFINE_TYPE (GstRtpMP4APay, gst_rtp_mp4a_pay, GST_TYPE_RTP_BASE_PAYLOAD);
72 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (rtpmp4apay, "rtpmp4apay",
73     GST_RANK_SECONDARY, GST_TYPE_RTP_MP4A_PAY, rtp_element_init (plugin));
74
75 static void
76 gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
77 {
78   GObjectClass *gobject_class;
79   GstElementClass *gstelement_class;
80   GstRTPBasePayloadClass *gstrtpbasepayload_class;
81
82   gobject_class = (GObjectClass *) klass;
83   gstelement_class = (GstElementClass *) klass;
84   gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
85
86   gobject_class->finalize = gst_rtp_mp4a_pay_finalize;
87
88   gstrtpbasepayload_class->set_caps = gst_rtp_mp4a_pay_setcaps;
89   gstrtpbasepayload_class->handle_buffer = gst_rtp_mp4a_pay_handle_buffer;
90
91   gst_element_class_add_static_pad_template (gstelement_class,
92       &gst_rtp_mp4a_pay_src_template);
93   gst_element_class_add_static_pad_template (gstelement_class,
94       &gst_rtp_mp4a_pay_sink_template);
95
96   gst_element_class_set_static_metadata (gstelement_class,
97       "RTP MPEG4 audio payloader", "Codec/Payloader/Network/RTP",
98       "Payload MPEG4 audio as RTP packets (RFC 3016)",
99       "Wim Taymans <wim.taymans@gmail.com>");
100
101   GST_DEBUG_CATEGORY_INIT (rtpmp4apay_debug, "rtpmp4apay", 0,
102       "MP4A-LATM RTP Payloader");
103 }
104
105 static void
106 gst_rtp_mp4a_pay_init (GstRtpMP4APay * rtpmp4apay)
107 {
108   rtpmp4apay->rate = 90000;
109   rtpmp4apay->profile = g_strdup ("1");
110 }
111
112 static void
113 gst_rtp_mp4a_pay_finalize (GObject * object)
114 {
115   GstRtpMP4APay *rtpmp4apay;
116
117   rtpmp4apay = GST_RTP_MP4A_PAY (object);
118
119   g_free (rtpmp4apay->params);
120   rtpmp4apay->params = NULL;
121
122   if (rtpmp4apay->config)
123     gst_buffer_unref (rtpmp4apay->config);
124   rtpmp4apay->config = NULL;
125
126   g_free (rtpmp4apay->profile);
127   rtpmp4apay->profile = NULL;
128
129   G_OBJECT_CLASS (parent_class)->finalize (object);
130 }
131
132 static const unsigned int sampling_table[16] = {
133   96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
134   16000, 12000, 11025, 8000, 7350, 0, 0, 0
135 };
136
137 static gboolean
138 gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
139     GstBuffer * buffer)
140 {
141   GstMapInfo map;
142   guint8 *data;
143   gsize size;
144   guint8 objectType;
145   guint8 samplingIdx;
146   guint8 channelCfg;
147
148   gst_buffer_map (buffer, &map, GST_MAP_READ);
149   data = map.data;
150   size = map.size;
151
152   if (size < 2)
153     goto too_short;
154
155   /* any object type is fine, we need to copy it to the profile-level-id field. */
156   objectType = (data[0] & 0xf8) >> 3;
157   if (objectType == 0)
158     goto invalid_object;
159
160   samplingIdx = ((data[0] & 0x07) << 1) | ((data[1] & 0x80) >> 7);
161   /* only fixed values for now */
162   if (samplingIdx > 12 && samplingIdx != 15)
163     goto wrong_freq;
164
165   channelCfg = ((data[1] & 0x78) >> 3);
166   if (channelCfg > 7)
167     goto wrong_channels;
168
169   /* rtp rate depends on sampling rate of the audio */
170   if (samplingIdx == 15) {
171     if (size < 5)
172       goto too_short;
173
174     /* index of 15 means we get the rate in the next 24 bits */
175     rtpmp4apay->rate = ((data[1] & 0x7f) << 17) |
176         ((data[2]) << 9) | ((data[3]) << 1) | ((data[4] & 0x80) >> 7);
177   } else {
178     /* else use the rate from the table */
179     rtpmp4apay->rate = sampling_table[samplingIdx];
180   }
181   /* extra rtp params contain the number of channels */
182   g_free (rtpmp4apay->params);
183   rtpmp4apay->params = g_strdup_printf ("%d", channelCfg);
184   /* audio stream type */
185   rtpmp4apay->streamtype = "5";
186   /* profile */
187   g_free (rtpmp4apay->profile);
188   rtpmp4apay->profile = g_strdup_printf ("%d", objectType);
189
190   GST_DEBUG_OBJECT (rtpmp4apay,
191       "objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
192       samplingIdx, rtpmp4apay->rate, channelCfg);
193
194   gst_buffer_unmap (buffer, &map);
195
196   return TRUE;
197
198   /* ERROR */
199 too_short:
200   {
201     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
202         (NULL),
203         ("config string too short, expected 2 bytes, got %" G_GSIZE_FORMAT,
204             size));
205     gst_buffer_unmap (buffer, &map);
206     return FALSE;
207   }
208 invalid_object:
209   {
210     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
211         (NULL), ("invalid object type 0"));
212     gst_buffer_unmap (buffer, &map);
213     return FALSE;
214   }
215 wrong_freq:
216   {
217     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
218         (NULL), ("unsupported frequency index %d", samplingIdx));
219     gst_buffer_unmap (buffer, &map);
220     return FALSE;
221   }
222 wrong_channels:
223   {
224     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
225         (NULL), ("unsupported number of channels %d, must < 8", channelCfg));
226     gst_buffer_unmap (buffer, &map);
227     return FALSE;
228   }
229 }
230
231 static gboolean
232 gst_rtp_mp4a_pay_new_caps (GstRtpMP4APay * rtpmp4apay)
233 {
234   gchar *config;
235   GValue v = { 0 };
236   gboolean res;
237
238   g_value_init (&v, GST_TYPE_BUFFER);
239   gst_value_set_buffer (&v, rtpmp4apay->config);
240   config = gst_value_serialize (&v);
241
242   res = gst_rtp_base_payload_set_outcaps (GST_RTP_BASE_PAYLOAD (rtpmp4apay),
243       "cpresent", G_TYPE_STRING, "0", "config", G_TYPE_STRING, config, NULL);
244
245   g_value_unset (&v);
246   g_free (config);
247
248   return res;
249 }
250
251 static gboolean
252 gst_rtp_mp4a_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
253 {
254   GstRtpMP4APay *rtpmp4apay;
255   GstStructure *structure;
256   const GValue *codec_data;
257   gboolean res, framed = TRUE;
258   const gchar *stream_format;
259
260   rtpmp4apay = GST_RTP_MP4A_PAY (payload);
261
262   structure = gst_caps_get_structure (caps, 0);
263
264   /* this is already handled by the template caps, but it is better
265    * to leave here to have meaningful warning messages when linking
266    * fails */
267   stream_format = gst_structure_get_string (structure, "stream-format");
268   if (stream_format) {
269     if (strcmp (stream_format, "raw") != 0) {
270       GST_WARNING_OBJECT (rtpmp4apay, "AAC's stream-format must be 'raw', "
271           "%s is not supported", stream_format);
272       return FALSE;
273     }
274   } else {
275     GST_WARNING_OBJECT (rtpmp4apay, "AAC's stream-format not specified, "
276         "assuming 'raw'");
277   }
278
279   codec_data = gst_structure_get_value (structure, "codec_data");
280   if (codec_data) {
281     GST_LOG_OBJECT (rtpmp4apay, "got codec_data");
282     if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) {
283       GstBuffer *buffer, *cbuffer;
284       GstMapInfo map;
285       GstMapInfo cmap;
286       guint i;
287
288       buffer = gst_value_get_buffer (codec_data);
289       GST_LOG_OBJECT (rtpmp4apay, "configuring codec_data");
290
291       /* parse buffer */
292       res = gst_rtp_mp4a_pay_parse_audio_config (rtpmp4apay, buffer);
293
294       if (!res)
295         goto config_failed;
296
297       gst_buffer_map (buffer, &map, GST_MAP_READ);
298
299       /* make the StreamMuxConfig, we need 15 bits for the header */
300       cbuffer = gst_buffer_new_and_alloc (map.size + 2);
301       gst_buffer_map (cbuffer, &cmap, GST_MAP_WRITE);
302
303       memset (cmap.data, 0, map.size + 2);
304
305       /* Create StreamMuxConfig according to ISO/IEC 14496-3:
306        *
307        * audioMuxVersion           == 0 (1 bit)
308        * allStreamsSameTimeFraming == 1 (1 bit)
309        * numSubFrames              == numSubFrames (6 bits)
310        * numProgram                == 0 (4 bits)
311        * numLayer                  == 0 (3 bits)
312        */
313       cmap.data[0] = 0x40;
314       cmap.data[1] = 0x00;
315
316       /* append the config bits, shifting them 1 bit left */
317       for (i = 0; i < map.size; i++) {
318         cmap.data[i + 1] |= ((map.data[i] & 0x80) >> 7);
319         cmap.data[i + 2] |= ((map.data[i] & 0x7f) << 1);
320       }
321
322       gst_buffer_unmap (cbuffer, &cmap);
323       gst_buffer_unmap (buffer, &map);
324
325       /* now we can configure the buffer */
326       if (rtpmp4apay->config)
327         gst_buffer_unref (rtpmp4apay->config);
328       rtpmp4apay->config = cbuffer;
329     }
330   }
331
332   if (gst_structure_get_boolean (structure, "framed", &framed) && !framed) {
333     GST_WARNING_OBJECT (payload, "Need framed AAC data as input!");
334   }
335
336   gst_rtp_base_payload_set_options (payload, "audio", TRUE, "MP4A-LATM",
337       rtpmp4apay->rate);
338
339   res = gst_rtp_mp4a_pay_new_caps (rtpmp4apay);
340
341   return res;
342
343   /* ERRORS */
344 config_failed:
345   {
346     GST_DEBUG_OBJECT (rtpmp4apay, "failed to parse config");
347     return FALSE;
348   }
349 }
350
351 #define RTP_HEADER_LEN 12
352
353 /* we expect buffers as exactly one complete AU
354  */
355 static GstFlowReturn
356 gst_rtp_mp4a_pay_handle_buffer (GstRTPBasePayload * basepayload,
357     GstBuffer * buffer)
358 {
359   GstRtpMP4APay *rtpmp4apay;
360   GstFlowReturn ret;
361   GstBufferList *list;
362   guint mtu;
363   guint offset;
364   gsize size;
365   gboolean fragmented;
366   GstClockTime timestamp;
367
368   ret = GST_FLOW_OK;
369
370   rtpmp4apay = GST_RTP_MP4A_PAY (basepayload);
371
372   offset = 0;
373   size = gst_buffer_get_size (buffer);
374
375   timestamp = GST_BUFFER_PTS (buffer);
376
377   fragmented = FALSE;
378   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtpmp4apay);
379
380   list = gst_buffer_list_new_sized (size / (mtu - RTP_HEADER_LEN) + 1);
381
382   while (size > 0) {
383     guint towrite;
384     GstBuffer *outbuf;
385     guint payload_len;
386     guint packet_len;
387     guint header_len;
388     GstBuffer *paybuf;
389     GstRTPBuffer rtp = { NULL };
390
391     header_len = 0;
392     if (!fragmented) {
393       guint count;
394       /* first packet calculate space for the packet including the header */
395       count = size;
396       while (count >= 0xff) {
397         header_len++;
398         count -= 0xff;
399       }
400       header_len++;
401     }
402
403     packet_len = gst_rtp_buffer_calc_packet_len (header_len + size, 0, 0);
404     towrite = MIN (packet_len, mtu);
405     payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);
406     payload_len -= header_len;
407
408     GST_DEBUG_OBJECT (rtpmp4apay,
409         "avail %" G_GSIZE_FORMAT
410         ", header_len %d, packet_len %d, payload_len %d", size, header_len,
411         packet_len, payload_len);
412
413     /* create buffer to hold the payload. */
414     outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload,
415         header_len, 0, 0);
416
417     /* copy payload */
418     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
419
420     if (!fragmented) {
421       guint8 *payload = gst_rtp_buffer_get_payload (&rtp);
422       guint count;
423
424       /* first packet write the header */
425       count = size;
426       while (count >= 0xff) {
427         *payload++ = 0xff;
428         count -= 0xff;
429       }
430       *payload++ = count;
431     }
432
433     /* marker only if the packet is complete */
434     gst_rtp_buffer_set_marker (&rtp, size == payload_len);
435     if (size == payload_len)
436       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_MARKER);
437
438     gst_rtp_buffer_unmap (&rtp);
439
440     /* create a new buf to hold the payload */
441     paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
442         offset, payload_len);
443
444     /* join memory parts */
445     gst_rtp_copy_audio_meta (rtpmp4apay, outbuf, paybuf);
446     outbuf = gst_buffer_append (outbuf, paybuf);
447     gst_buffer_list_add (list, outbuf);
448     offset += payload_len;
449     size -= payload_len;
450
451     /* copy incoming timestamp (if any) to outgoing buffers */
452     GST_BUFFER_PTS (outbuf) = timestamp;
453
454     fragmented = TRUE;
455   }
456
457   ret =
458       gst_rtp_base_payload_push_list (GST_RTP_BASE_PAYLOAD (rtpmp4apay), list);
459
460   gst_buffer_unref (buffer);
461
462   return ret;
463 }