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>
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.
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.
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.
23 * SECTION:gstaudioiec61937
24 * @short_description: Utility functions for IEC 61937 payloading
27 * This module contains some helper functions for encapsulating various
28 * audio formats in IEC 61937 headers and padding.
37 #include "gstaudioiec61937.h"
39 #define IEC61937_HEADER_SIZE 8
40 #define IEC61937_PAYLOAD_SIZE_AC3 (1536 * 4)
41 #define IEC61937_PAYLOAD_SIZE_EAC3 (6144 * 4)
44 caps_get_int_field (const GstCaps * caps, const gchar * field)
46 const GstStructure *st;
49 st = gst_caps_get_structure (caps, 0);
50 gst_structure_get_int (st, field, &ret);
56 caps_get_string_field (const GstCaps * caps, const gchar * field)
58 const GstStructure *st = gst_caps_get_structure (caps, 0);
59 return gst_structure_get_string (st, field);
63 * gst_audio_iec61937_frame_size:
64 * @spec: the ringbufer spec
66 * Calculated the size of the buffer expected by gst_audio_iec61937_payload() for
67 * payloading type from @spec.
69 * Returns: the size or 0 if the given @type is not supported or cannot be
75 gst_audio_iec61937_frame_size (const GstRingBufferSpec * spec)
79 return IEC61937_PAYLOAD_SIZE_AC3;
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;
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;
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;
102 case GST_BUFTYPE_MPEG:
104 int version, layer, channels, frames;
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");
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)
115 if (version == 1 && layer == 1)
117 else if (version == 2 && layer == 1 && spec->rate < 32000)
119 else if (version == 2 && layer == 1 && spec->rate < 32000)
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
138 * @dst_n: size of @dst in bytes
139 * @spec: the ringbufer spec for @src
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.
145 * Returns: transfer-full: %TRUE if the payloading was successful, %FALSE
151 gst_audio_iec61937_payload (const guint8 * src, guint src_n, guint8 * dst,
152 guint dst_n, const GstRingBufferSpec * spec)
155 #if G_BYTE_ORDER == G_BIG_ENDIAN
156 guint8 zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, six = 6,
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,
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);
169 if (dst_n < src_n + IEC61937_HEADER_SIZE)
178 switch (spec->type) {
179 case GST_BUFTYPE_AC3:
181 g_return_val_if_fail (src_n >= 6, FALSE);
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) */
191 /* Pd: bit 15-0 - frame size in bits */
193 dst[six] = (guint8) (tmp >> 8);
194 dst[seven] = (guint8) (tmp & 0xff);
199 case GST_BUFTYPE_EAC3:
201 if (g_str_equal (caps_get_string_field (spec->caps, "alignment"),
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 */
210 /* Pc: bit 7 - error bit (0)
211 * bit 5-6 - subdata type (0)
212 * bit 0-4 - data type (21) */
214 /* Pd: bit 15-0 - frame size in bytes */
215 dst[six] = ((guint16) src_n) >> 8;
216 dst[seven] = ((guint16) src_n) & 0xff;
221 case GST_BUFTYPE_DTS:
223 int blocksize = caps_get_int_field (spec->caps, "block-size");
225 g_return_val_if_fail (src_n != 0, FALSE);
230 /* Pc: bit 13-15 - stream number (0)
231 * bit 11-12 - reserved (0)
232 * bit 8-10 - for DTS type I-III (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,
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;
245 case GST_BUFTYPE_MPEG:
249 version = caps_get_int_field (spec->caps, "mpegaudioversion");
250 layer = caps_get_int_field (spec->caps, "layer");
252 g_return_val_if_fail (version > 0 && layer > 0, FALSE);
254 /* NOTE: multichannel audio (MPEG-2) is not supported */
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
261 * bit 8 - Normal (0) or Karaoke (1) mode */
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)
273 else if ((version == 1 && (layer == 2 || layer == 3)) ||
274 (version == 2 && spec->rate >= 32000))
276 else if (version == 2 && layer == 1 && spec->rate < 32000)
278 else if (version == 2 && layer == 2 && spec->rate < 32000)
280 else if (version == 2 && layer == 3 && spec->rate < 32000)
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;
295 /* Copy the payload */
298 #if G_BYTE_ORDER == G_BIG_ENDIAN
299 memcpy (dst + i, src, src_n);
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];
307 /* Do we have 1 byte remaining? */
309 dst[i + src_n - 1] = 0;
310 dst[i + src_n] = src[src_n - 1];
318 memset (dst + i, 0, dst_n - i);