Initialize Tizen 2.3
[framework/multimedia/gst-plugins-base0.10.git] / wearable / gst-libs / gst / audio / gstaudioiec61937.c
1 /* GStreamer audio helper functions for IEC 61937 payloading
2  * (c) 2011 Intel Corporation
3  *     2011 Collabora Multimedia
4  *     2011 Arun Raghavan <arun.raghavan@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstaudioiec61937
24  * @short_description: Utility functions for IEC 61937 payloading
25  * @since: 0.10.36
26  *
27  * This module contains some helper functions for encapsulating various
28  * audio formats in IEC 61937 headers and padding.
29  *
30  */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <string.h>
37 #include "gstaudioiec61937.h"
38
39 #define IEC61937_HEADER_SIZE      8
40 #define IEC61937_PAYLOAD_SIZE_AC3 (1536 * 4)
41 #define IEC61937_PAYLOAD_SIZE_EAC3 (6144 * 4)
42
43 static gint
44 caps_get_int_field (const GstCaps * caps, const gchar * field)
45 {
46   const GstStructure *st;
47   gint ret = 0;
48
49   st = gst_caps_get_structure (caps, 0);
50   gst_structure_get_int (st, field, &ret);
51
52   return ret;
53 }
54
55 static const gchar *
56 caps_get_string_field (const GstCaps * caps, const gchar * field)
57 {
58   const GstStructure *st = gst_caps_get_structure (caps, 0);
59   return gst_structure_get_string (st, field);
60 }
61
62 /**
63  * gst_audio_iec61937_frame_size:
64  * @spec: the ringbufer spec
65  *
66  * Calculated the size of the buffer expected by gst_audio_iec61937_payload() for
67  * payloading type from @spec.
68  *
69  * Returns: the size or 0 if the given @type is not supported or cannot be
70  * payloaded.
71  *
72  * Since: 0.10.36
73  */
74 guint
75 gst_audio_iec61937_frame_size (const GstRingBufferSpec * spec)
76 {
77   switch (spec->type) {
78     case GST_BUFTYPE_AC3:
79       return IEC61937_PAYLOAD_SIZE_AC3;
80
81     case GST_BUFTYPE_EAC3:
82       /* Check that the parser supports /some/ alignment. Need to be less
83        * strict about this at checking time since the alignment is dynamically
84        * set at the moment. */
85       if (caps_get_string_field (spec->caps, "alignment"))
86         return IEC61937_PAYLOAD_SIZE_EAC3;
87       else
88         return 0;
89
90     case GST_BUFTYPE_DTS:
91     {
92       gint dts_frame_size = caps_get_int_field (spec->caps, "frame-size");
93       gint iec_frame_size = caps_get_int_field (spec->caps, "block-size") * 4;
94
95       /* Note: this will also (correctly) fail if either field is missing */
96       if (iec_frame_size >= (dts_frame_size + IEC61937_HEADER_SIZE))
97         return iec_frame_size;
98       else
99         return 0;
100     }
101
102     case GST_BUFTYPE_MPEG:
103     {
104       int version, layer, channels, frames;
105
106       version = caps_get_int_field (spec->caps, "mpegaudioversion");
107       layer = caps_get_int_field (spec->caps, "layer");
108       channels = caps_get_int_field (spec->caps, "channels");
109
110       /* Bail out if we can't figure out either, if it's MPEG 2.5, or if it's
111        * MP3 with multichannel audio */
112       if (!version || !layer || version == 3 || channels > 2)
113         return 0;
114
115       if (version == 1 && layer == 1)
116         frames = 384;
117       else if (version == 2 && layer == 1 && spec->rate < 32000)
118         frames = 768;
119       else if (version == 2 && layer == 1 && spec->rate < 32000)
120         frames = 2304;
121       else
122         frames = 1152;
123
124       return frames * 4;
125     }
126
127     default:
128       return 0;
129   }
130 }
131
132 /**
133  * gst_audio_iec61937_payload:
134  * @src: a buffer containing the data to payload
135  * @src_n: size of @src in bytes
136  * @dst: the destination buffer to store the payloaded contents in. Should not
137  *       overlap with @src
138  * @dst_n: size of @dst in bytes
139  * @spec: the ringbufer spec for @src
140  *
141  * Payloads @src in the form specified by IEC 61937 for the type from @spec and
142  * stores the result in @dst. @src must contain exactly one frame of data and
143  * the frame is not checked for errors.
144  *
145  * Returns: transfer-full: %TRUE if the payloading was successful, %FALSE
146  * otherwise.
147  *
148  * Since: 0.10.36
149  */
150 gboolean
151 gst_audio_iec61937_payload (const guint8 * src, guint src_n, guint8 * dst,
152     guint dst_n, const GstRingBufferSpec * spec)
153 {
154   guint i, tmp;
155 #if G_BYTE_ORDER == G_BIG_ENDIAN
156   guint8 zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, six = 6,
157       seven = 7;
158 #else
159   /* We need to send the data byte-swapped */
160   guint8 zero = 1, one = 0, two = 3, three = 2, four = 5, five = 4, six = 7,
161       seven = 6;
162 #endif
163
164   g_return_val_if_fail (src != NULL, FALSE);
165   g_return_val_if_fail (dst != NULL, FALSE);
166   g_return_val_if_fail (src != dst, FALSE);
167   g_return_val_if_fail (dst_n >= gst_audio_iec61937_frame_size (spec), FALSE);
168
169   if (dst_n < src_n + IEC61937_HEADER_SIZE)
170     return FALSE;
171
172   /* Pa, Pb */
173   dst[zero] = 0xF8;
174   dst[one] = 0x72;
175   dst[two] = 0x4E;
176   dst[three] = 0x1F;
177
178   switch (spec->type) {
179     case GST_BUFTYPE_AC3:
180     {
181       g_return_val_if_fail (src_n >= 6, FALSE);
182
183       /* Pc: bit 13-15 - stream number (0)
184        *     bit 11-12 - reserved (0)
185        *     bit  8-10 - bsmod from AC3 frame */
186       dst[four] = src[5] & 0x7;
187       /* Pc: bit    7  - error bit (0)
188        *     bit  5-6  - subdata type (0)
189        *     bit  0-4  - data type (1) */
190       dst[five] = 1;
191       /* Pd: bit 15-0  - frame size in bits */
192       tmp = src_n * 8;
193       dst[six] = (guint8) (tmp >> 8);
194       dst[seven] = (guint8) (tmp & 0xff);
195
196       break;
197     }
198
199     case GST_BUFTYPE_EAC3:
200     {
201       if (g_str_equal (caps_get_string_field (spec->caps, "alignment"),
202               "iec61937"))
203         return FALSE;
204
205       /* Pc: bit 13-15 - stream number (0)
206        *     bit 11-12 - reserved (0)
207        *     bit  8-10 - bsmod from E-AC3 frame if present */
208       /* FIXME: this works, but nicer if we can put in the actual bsmod */
209       dst[four] = 0;
210       /* Pc: bit    7  - error bit (0)
211        *     bit  5-6  - subdata type (0)
212        *     bit  0-4  - data type (21) */
213       dst[five] = 21;
214       /* Pd: bit 15-0  - frame size in bytes */
215       dst[six] = ((guint16) src_n) >> 8;
216       dst[seven] = ((guint16) src_n) & 0xff;
217
218       break;
219     }
220
221     case GST_BUFTYPE_DTS:
222     {
223       int blocksize = caps_get_int_field (spec->caps, "block-size");
224
225       g_return_val_if_fail (src_n != 0, FALSE);
226
227       if (blocksize == 0)
228         return FALSE;
229
230       /* Pc: bit 13-15 - stream number (0)
231        *     bit 11-12 - reserved (0)
232        *     bit  8-10 - for DTS type I-III (0) */
233       dst[four] = 0;
234       /* Pc: bit    7  - error bit (0)
235        *     bit  5-6  - reserved (0)
236        *     bit  0-4  - data type (11 = type I, 12 = type II,
237        *                            13 = type III) */
238       dst[five] = 11 + (blocksize / 1024);
239       /* Pd: bit 15-0  - frame size in bytes */
240       dst[six] = ((guint16) src_n) >> 8;
241       dst[seven] = ((guint16) src_n) & 0xff;
242       break;
243     }
244
245     case GST_BUFTYPE_MPEG:
246     {
247       int version, layer;
248
249       version = caps_get_int_field (spec->caps, "mpegaudioversion");
250       layer = caps_get_int_field (spec->caps, "layer");
251
252       g_return_val_if_fail (version > 0 && layer > 0, FALSE);
253
254       /* NOTE: multichannel audio (MPEG-2) is not supported */
255
256       /* Pc: bit 13-15 - stream number (0)
257        *     bit 11-12 - reserved (0)
258        *     bit  9-10 - 0 - no dynamic range control
259        *               - 2 - dynamic range control exists
260        *               - 1,3 - reserved
261        *     bit    8  - Normal (0) or Karaoke (1) mode */
262       dst[four] = 0;
263       /* Pc: bit    7  - error bit (0)
264        *     bit  5-6  - reserved (0)
265        *     bit  0-4  - data type (04 = MPEG 1, Layer 1
266        *                            05 = MPEG 1, Layer 2, 3 / MPEG 2, w/o ext.
267        *                            06 = MPEG 2, with extension
268        *                            08 - MPEG 2 LSF, Layer 1
269        *                            09 - MPEG 2 LSF, Layer 2
270        *                            10 - MPEG 2 LSF, Layer 3 */
271       if (version == 1 && layer == 1)
272         dst[five] = 0x04;
273       else if ((version == 1 && (layer == 2 || layer == 3)) ||
274           (version == 2 && spec->rate >= 32000))
275         dst[five] = 0x05;
276       else if (version == 2 && layer == 1 && spec->rate < 32000)
277         dst[five] = 0x08;
278       else if (version == 2 && layer == 2 && spec->rate < 32000)
279         dst[five] = 0x09;
280       else if (version == 2 && layer == 3 && spec->rate < 32000)
281         dst[five] = 0x0A;
282       else
283         g_return_val_if_reached (FALSE);
284       /* Pd: bit 15-0  - frame size in bits */
285       dst[six] = ((guint16) src_n * 8) >> 8;
286       dst[seven] = ((guint16) src_n * 8) & 0xff;
287
288       break;
289     }
290
291     default:
292       return FALSE;
293   }
294
295   /* Copy the payload */
296   i = 8;
297
298 #if G_BYTE_ORDER == G_BIG_ENDIAN
299   memcpy (dst + i, src, src_n);
300 #else
301   /* Byte-swapped again */
302   /* FIXME: orc-ify this */
303   for (tmp = 1; tmp < src_n; tmp += 2) {
304     dst[i + tmp - 1] = src[tmp];
305     dst[i + tmp] = src[tmp - 1];
306   }
307   /* Do we have 1 byte remaining? */
308   if (src_n % 2) {
309     dst[i + src_n - 1] = 0;
310     dst[i + src_n] = src[src_n - 1];
311     i++;
312   }
313 #endif
314
315   i += src_n;
316
317   /* Zero the rest */
318   memset (dst + i, 0, dst_n - i);
319
320   return TRUE;
321 }