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., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:gstaudioiec61937
24 * @title: GstAudio IEC61937
25 * @short_description: Utility functions for IEC 61937 payloading
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
38 #include <gst/audio/audio.h>
39 #include "gstaudioiec61937.h"
40
41 #define IEC61937_HEADER_SIZE 8
42 #define IEC61937_PAYLOAD_SIZE_AC3 (1536 * 4)
43 #define IEC61937_PAYLOAD_SIZE_EAC3 (6144 * 4)
44 #define IEC61937_PAYLOAD_SIZE_AAC (1024 * 4)
45
46 static gint
caps_get_int_field(const GstCaps * caps,const gchar * field)47 caps_get_int_field (const GstCaps * caps, const gchar * field)
48 {
49 const GstStructure *st;
50 gint ret = 0;
51
52 st = gst_caps_get_structure (caps, 0);
53 gst_structure_get_int (st, field, &ret);
54
55 return ret;
56 }
57
58 static const gchar *
caps_get_string_field(const GstCaps * caps,const gchar * field)59 caps_get_string_field (const GstCaps * caps, const gchar * field)
60 {
61 const GstStructure *st = gst_caps_get_structure (caps, 0);
62 return gst_structure_get_string (st, field);
63 }
64
65 /**
66 * gst_audio_iec61937_frame_size:
67 * @spec: the ringbufer spec
68 *
69 * Calculated the size of the buffer expected by gst_audio_iec61937_payload() for
70 * payloading type from @spec.
71 *
72 * Returns: the size or 0 if the given @type is not supported or cannot be
73 * payloaded.
74 */
75 guint
gst_audio_iec61937_frame_size(const GstAudioRingBufferSpec * spec)76 gst_audio_iec61937_frame_size (const GstAudioRingBufferSpec * spec)
77 {
78 switch (spec->type) {
79 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
80 return IEC61937_PAYLOAD_SIZE_AC3;
81
82 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
83 /* Check that the parser supports /some/ alignment. Need to be less
84 * strict about this at checking time since the alignment is dynamically
85 * set at the moment. */
86 if (caps_get_string_field (spec->caps, "alignment"))
87 return IEC61937_PAYLOAD_SIZE_EAC3;
88 else
89 return 0;
90
91 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
92 {
93 gint dts_frame_size = caps_get_int_field (spec->caps, "frame-size");
94 gint iec_frame_size = caps_get_int_field (spec->caps, "block-size") * 4;
95
96 /* Note: this will also (correctly) fail if either field is missing */
97 if (iec_frame_size >= (dts_frame_size + IEC61937_HEADER_SIZE))
98 return iec_frame_size;
99 else
100 return 0;
101 }
102
103 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
104 {
105 int version, layer, channels, frames;
106
107 version = caps_get_int_field (spec->caps, "mpegaudioversion");
108 layer = caps_get_int_field (spec->caps, "layer");
109 channels = caps_get_int_field (spec->caps, "channels");
110
111 /* Bail out if we can't figure out either, if it's MPEG 2.5, or if it's
112 * MP3 with multichannel audio */
113 if (!version || !layer || version == 3 || channels > 2)
114 return 0;
115
116 if (version == 1 && layer == 1)
117 frames = 384;
118 else if (version == 2 && layer == 1 && spec->info.rate <= 12000)
119 frames = 768;
120 else if (version == 2 && layer == 2 && spec->info.rate <= 12000)
121 frames = 2304;
122 else {
123 /* MPEG-1 layer 2,3, MPEG-2 with or without extension,
124 * MPEG-2 layer 3 low sample freq. */
125 frames = 1152;
126 }
127
128 return frames * 4;
129 }
130
131 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG2_AAC:
132 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG4_AAC:
133 {
134 return IEC61937_PAYLOAD_SIZE_AAC;
135 }
136
137 default:
138 return 0;
139 }
140 }
141
142 /**
143 * gst_audio_iec61937_payload:
144 * @src: (array length=src_n): a buffer containing the data to payload
145 * @src_n: size of @src in bytes
146 * @dst: (array length=dst_n): the destination buffer to store the
147 * payloaded contents in. Should not overlap with @src
148 * @dst_n: size of @dst in bytes
149 * @spec: the ringbufer spec for @src
150 * @endianness: the expected byte order of the payloaded data
151 *
152 * Payloads @src in the form specified by IEC 61937 for the type from @spec and
153 * stores the result in @dst. @src must contain exactly one frame of data and
154 * the frame is not checked for errors.
155 *
156 * Returns: transfer-full: %TRUE if the payloading was successful, %FALSE
157 * otherwise.
158 */
159 gboolean
gst_audio_iec61937_payload(const guint8 * src,guint src_n,guint8 * dst,guint dst_n,const GstAudioRingBufferSpec * spec,gint endianness)160 gst_audio_iec61937_payload (const guint8 * src, guint src_n, guint8 * dst,
161 guint dst_n, const GstAudioRingBufferSpec * spec, gint endianness)
162 {
163 guint i, tmp;
164 #if G_BYTE_ORDER == G_BIG_ENDIAN
165 guint8 zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, six = 6,
166 seven = 7;
167 #else
168 /* We need to send the data byte-swapped */
169 guint8 zero = 1, one = 0, two = 3, three = 2, four = 5, five = 4, six = 7,
170 seven = 6;
171 #endif
172
173 g_return_val_if_fail (src != NULL, FALSE);
174 g_return_val_if_fail (dst != NULL, FALSE);
175 g_return_val_if_fail (src != dst, FALSE);
176 g_return_val_if_fail (dst_n >= gst_audio_iec61937_frame_size (spec), FALSE);
177
178 if (dst_n < src_n + IEC61937_HEADER_SIZE)
179 return FALSE;
180
181 /* Pa, Pb */
182 dst[zero] = 0xF8;
183 dst[one] = 0x72;
184 dst[two] = 0x4E;
185 dst[three] = 0x1F;
186
187 switch (spec->type) {
188 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
189 {
190 g_return_val_if_fail (src_n >= 6, FALSE);
191
192 /* Pc: bit 13-15 - stream number (0)
193 * bit 11-12 - reserved (0)
194 * bit 8-10 - bsmod from AC3 frame */
195 dst[four] = src[5] & 0x7;
196 /* Pc: bit 7 - error bit (0)
197 * bit 5-6 - subdata type (0)
198 * bit 0-4 - data type (1) */
199 dst[five] = 1;
200 /* Pd: bit 15-0 - frame size in bits */
201 tmp = src_n * 8;
202 dst[six] = (guint8) (tmp >> 8);
203 dst[seven] = (guint8) (tmp & 0xff);
204
205 break;
206 }
207
208 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
209 {
210 if (g_str_equal (caps_get_string_field (spec->caps, "alignment"),
211 "iec61937"))
212 return FALSE;
213
214 /* Pc: bit 13-15 - stream number (0)
215 * bit 11-12 - reserved (0)
216 * bit 8-10 - bsmod from E-AC3 frame if present */
217 /* FIXME: this works, but nicer if we can put in the actual bsmod */
218 dst[four] = 0;
219 /* Pc: bit 7 - error bit (0)
220 * bit 5-6 - subdata type (0)
221 * bit 0-4 - data type (21) */
222 dst[five] = 21;
223 /* Pd: bit 15-0 - frame size in bytes */
224 dst[six] = ((guint16) src_n) >> 8;
225 dst[seven] = ((guint16) src_n) & 0xff;
226
227 break;
228 }
229
230 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
231 {
232 int blocksize = caps_get_int_field (spec->caps, "block-size");
233
234 g_return_val_if_fail (src_n != 0, FALSE);
235
236 if (blocksize == 0)
237 return FALSE;
238
239 /* Pc: bit 13-15 - stream number (0)
240 * bit 11-12 - reserved (0)
241 * bit 8-10 - for DTS type I-III (0) */
242 dst[four] = 0;
243 /* Pc: bit 7 - error bit (0)
244 * bit 5-6 - reserved (0)
245 * bit 0-4 - data type (11 = type I, 12 = type II,
246 * 13 = type III) */
247 dst[five] = 11 + (blocksize / 1024);
248 /* Pd: bit 15-0 - frame size, in bits (for type I-III) */
249 tmp = src_n * 8;
250 dst[six] = ((guint16) tmp) >> 8;
251 dst[seven] = ((guint16) tmp) & 0xff;
252 break;
253 }
254
255 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
256 {
257 int version, layer;
258
259 version = caps_get_int_field (spec->caps, "mpegaudioversion");
260 layer = caps_get_int_field (spec->caps, "layer");
261
262 g_return_val_if_fail (version > 0 && layer > 0, FALSE);
263
264 /* NOTE: multichannel audio (MPEG-2) is not supported */
265
266 /* Pc: bit 13-15 - stream number (0)
267 * bit 11-12 - reserved (0)
268 * bit 9-10 - 0 - no dynamic range control
269 * - 2 - dynamic range control exists
270 * - 1,3 - reserved
271 * bit 8 - Normal (0) or Karaoke (1) mode */
272 dst[four] = 0;
273 /* Pc: bit 7 - error bit (0)
274 * bit 5-6 - reserved (0)
275 * bit 0-4 - data type (04 = MPEG 1, Layer 1
276 * 05 = MPEG 1, Layer 2, 3 / MPEG 2, w/o ext.
277 * 06 = MPEG 2, with extension
278 * 08 - MPEG 2 LSF, Layer 1
279 * 09 - MPEG 2 LSF, Layer 2
280 * 10 - MPEG 2 LSF, Layer 3
281 * FIXME: we don't handle type 06 at the moment */
282 if (version == 1 && layer == 1)
283 dst[five] = 0x04;
284 else if ((version == 1 && (layer == 2 || layer == 3)) ||
285 (version == 2 && spec->info.rate >= 12000))
286 dst[five] = 0x05;
287 else if (version == 2 && layer == 1 && spec->info.rate < 12000)
288 dst[five] = 0x08;
289 else if (version == 2 && layer == 2 && spec->info.rate < 12000)
290 dst[five] = 0x09;
291 else if (version == 2 && layer == 3 && spec->info.rate < 12000)
292 dst[five] = 0x0A;
293 else
294 g_return_val_if_reached (FALSE);
295 /* Pd: bit 15-0 - frame size in bits */
296 dst[six] = ((guint16) src_n * 8) >> 8;
297 dst[seven] = ((guint16) src_n * 8) & 0xff;
298
299 break;
300 }
301
302 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG2_AAC:
303 /* HACK. disguising MPEG4 AAC as MPEG2 AAC seems to work. */
304 /* TODO: set the right Pc,Pd for MPEG4 in accordance with IEC61937-6 */
305 case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG4_AAC:
306 {
307 int num_rd_blks;
308
309 g_return_val_if_fail (src_n >= 7, FALSE);
310 num_rd_blks = (src[6] & 0x03) + 1;
311
312 /* Pc: bit 13-15 - stream number (0)
313 * bit 11-12 - reserved (0)
314 * bit 8-10 - reserved? (0) */
315 dst[four] = 0;
316 /* Pc: bit 7 - error bit (0)
317 * bit 5-6 - reserved (0)
318 * bit 0-4 - data type (07 = MPEG2 AAC ADTS
319 * 19 = MPEG2 AAC ADTS half-rate LSF
320 * 51 = MPEG2 AAC ADTS quater-rate LSF */
321 if (num_rd_blks == 1)
322 dst[five] = 0x07;
323 else if (num_rd_blks == 2)
324 dst[five] = 0x13;
325 else if (num_rd_blks == 4)
326 dst[five] = 0x33;
327 else
328 g_return_val_if_reached (FALSE);
329
330 /* Pd: bit 15-0 - frame size in bits */
331 tmp = GST_ROUND_UP_2 (src_n) * 8;
332 dst[six] = (guint8) (tmp >> 8);
333 dst[seven] = (guint8) (tmp & 0xff);
334 break;
335 }
336
337 default:
338 return FALSE;
339 }
340
341 /* Copy the payload */
342 i = 8;
343
344 if (G_BYTE_ORDER == endianness) {
345 memcpy (dst + i, src, src_n);
346 } else {
347 /* Byte-swapped again */
348 /* FIXME: orc-ify this */
349 for (tmp = 1; tmp < src_n; tmp += 2) {
350 dst[i + tmp - 1] = src[tmp];
351 dst[i + tmp] = src[tmp - 1];
352 }
353 /* Do we have 1 byte remaining? */
354 if (src_n % 2) {
355 dst[i + src_n - 1] = 0;
356 dst[i + src_n] = src[src_n - 1];
357 i++;
358 }
359 }
360
361 i += src_n;
362
363 /* Zero the rest */
364 memset (dst + i, 0, dst_n - i);
365
366 return TRUE;
367 }
368