1 /* GStreamer
2 * Copyright (C) <2012> 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 "audio-format.h"
27
28 #include "gstaudiopack.h"
29
30 #ifdef HAVE_ORC
31 #include <orc/orcfunctions.h>
32 #else
33 #define orc_memset memset
34 #endif
35
36 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
37 # define audio_orc_unpack_s16le audio_orc_unpack_s16
38 # define audio_orc_unpack_s16le_trunc audio_orc_unpack_s16_trunc
39 # define audio_orc_unpack_s16be audio_orc_unpack_s16_swap
40 # define audio_orc_unpack_s16be_trunc audio_orc_unpack_s16_swap_trunc
41 # define audio_orc_unpack_u16le audio_orc_unpack_u16
42 # define audio_orc_unpack_u16le_trunc audio_orc_unpack_u16_trunc
43 # define audio_orc_unpack_u16be audio_orc_unpack_u16_swap
44 # define audio_orc_unpack_u16be_trunc audio_orc_unpack_u16_swap_trunc
45 # define audio_orc_unpack_s24_32le audio_orc_unpack_s24_32
46 # define audio_orc_unpack_s24_32be audio_orc_unpack_s24_32_swap
47 # define audio_orc_unpack_u24_32le audio_orc_unpack_u24_32
48 # define audio_orc_unpack_u24_32be audio_orc_unpack_u24_32_swap
49 # define audio_orc_unpack_s32le audio_orc_unpack_s32
50 # define audio_orc_unpack_s32be audio_orc_unpack_s32_swap
51 # define audio_orc_unpack_u32le audio_orc_unpack_u32
52 # define audio_orc_unpack_u32be audio_orc_unpack_u32_swap
53 # define audio_orc_unpack_f32le audio_orc_unpack_f32
54 # define audio_orc_unpack_f32be audio_orc_unpack_f32_swap
55 # define audio_orc_unpack_f64le audio_orc_unpack_f64
56 # define audio_orc_unpack_f64be audio_orc_unpack_f64_swap
57 # define audio_orc_pack_s16le audio_orc_pack_s16
58 # define audio_orc_pack_s16be audio_orc_pack_s16_swap
59 # define audio_orc_pack_u16le audio_orc_pack_u16
60 # define audio_orc_pack_u16be audio_orc_pack_u16_swap
61 # define audio_orc_pack_s24_32le audio_orc_pack_s24_32
62 # define audio_orc_pack_s24_32be audio_orc_pack_s24_32_swap
63 # define audio_orc_pack_u24_32le audio_orc_pack_u24_32
64 # define audio_orc_pack_u24_32be audio_orc_pack_u24_32_swap
65 # define audio_orc_pack_s32le audio_orc_pack_s32
66 # define audio_orc_pack_s32be audio_orc_pack_s32_swap
67 # define audio_orc_pack_u32le audio_orc_pack_u32
68 # define audio_orc_pack_u32be audio_orc_pack_u32_swap
69 # define audio_orc_pack_f32le audio_orc_pack_f32
70 # define audio_orc_pack_f32be audio_orc_pack_f32_swap
71 # define audio_orc_pack_f64le audio_orc_pack_f64
72 # define audio_orc_pack_f64be audio_orc_pack_f64_swap
73 #else
74 # define audio_orc_unpack_s16le audio_orc_unpack_s16_swap
75 # define audio_orc_unpack_s16le_trunc audio_orc_unpack_s16_swap_trunc
76 # define audio_orc_unpack_s16be audio_orc_unpack_s16
77 # define audio_orc_unpack_s16be_trunc audio_orc_unpack_s16_trunc
78 # define audio_orc_unpack_u16le audio_orc_unpack_u16_swap
79 # define audio_orc_unpack_u16le_trunc audio_orc_unpack_u16_swap_trunc
80 # define audio_orc_unpack_u16be audio_orc_unpack_u16
81 # define audio_orc_unpack_u16be_trunc audio_orc_unpack_u16_trunc
82 # define audio_orc_unpack_s24_32le audio_orc_unpack_s24_32_swap
83 # define audio_orc_unpack_s24_32be audio_orc_unpack_s24_32
84 # define audio_orc_unpack_u24_32le audio_orc_unpack_u24_32_swap
85 # define audio_orc_unpack_u24_32be audio_orc_unpack_u24_32
86 # define audio_orc_unpack_s32le audio_orc_unpack_s32_swap
87 # define audio_orc_unpack_s32be audio_orc_unpack_s32
88 # define audio_orc_unpack_u32le audio_orc_unpack_u32_swap
89 # define audio_orc_unpack_u32be audio_orc_unpack_u32
90 # define audio_orc_unpack_f32le audio_orc_unpack_f32_swap
91 # define audio_orc_unpack_f32be audio_orc_unpack_f32
92 # define audio_orc_unpack_f64le audio_orc_unpack_f64_swap
93 # define audio_orc_unpack_f64be audio_orc_unpack_f64
94 # define audio_orc_pack_s16le audio_orc_pack_s16_swap
95 # define audio_orc_pack_s16be audio_orc_pack_s16
96 # define audio_orc_pack_u16le audio_orc_pack_u16_swap
97 # define audio_orc_pack_u16be audio_orc_pack_u16
98 # define audio_orc_pack_s24_32le audio_orc_pack_s24_32_swap
99 # define audio_orc_pack_s24_32be audio_orc_pack_s24_32
100 # define audio_orc_pack_u24_32le audio_orc_pack_u24_32_swap
101 # define audio_orc_pack_u24_32be audio_orc_pack_u24_32
102 # define audio_orc_pack_s32le audio_orc_pack_s32_swap
103 # define audio_orc_pack_s32be audio_orc_pack_s32
104 # define audio_orc_pack_u32le audio_orc_pack_u32_swap
105 # define audio_orc_pack_u32be audio_orc_pack_u32
106 # define audio_orc_pack_f32le audio_orc_pack_f32_swap
107 # define audio_orc_pack_f32be audio_orc_pack_f32
108 # define audio_orc_pack_f64le audio_orc_pack_f64_swap
109 # define audio_orc_pack_f64be audio_orc_pack_f64
110 #endif
111
112 #define MAKE_ORC_PACK_UNPACK(fmt,fmt_t) \
113 static void unpack_ ##fmt (const GstAudioFormatInfo *info, \
114 GstAudioPackFlags flags, gpointer dest, \
115 gconstpointer data, gint length) { \
116 if (flags & GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE) \
117 audio_orc_unpack_ ##fmt_t (dest, data, length); \
118 else \
119 audio_orc_unpack_ ##fmt (dest, data, length); \
120 } \
121 static void pack_ ##fmt (const GstAudioFormatInfo *info, \
122 GstAudioPackFlags flags, gconstpointer src, \
123 gpointer data, gint length) { \
124 audio_orc_pack_ ##fmt (data, src, length); \
125 }
126
127 #define PACK_S8 GST_AUDIO_FORMAT_S32, unpack_s8, pack_s8
128 MAKE_ORC_PACK_UNPACK (s8, s8_trunc)
129 #define PACK_U8 GST_AUDIO_FORMAT_S32, unpack_u8, pack_u8
130 MAKE_ORC_PACK_UNPACK (u8, u8_trunc)
131 #define PACK_S16LE GST_AUDIO_FORMAT_S32, unpack_s16le, pack_s16le
132 MAKE_ORC_PACK_UNPACK (s16le, s16le_trunc)
133 #define PACK_S16BE GST_AUDIO_FORMAT_S32, unpack_s16be, pack_s16be
134 MAKE_ORC_PACK_UNPACK (s16be, s16be_trunc)
135 #define PACK_U16LE GST_AUDIO_FORMAT_S32, unpack_u16le, pack_u16le
136 MAKE_ORC_PACK_UNPACK (u16le, u16le_trunc)
137 #define PACK_U16BE GST_AUDIO_FORMAT_S32, unpack_u16be, pack_u16be
138 MAKE_ORC_PACK_UNPACK (u16be, u16be_trunc)
139 #define PACK_S24_32LE GST_AUDIO_FORMAT_S32, unpack_s24_32le, pack_s24_32le
140 MAKE_ORC_PACK_UNPACK (s24_32le, s24_32le)
141 #define PACK_S24_32BE GST_AUDIO_FORMAT_S32, unpack_s24_32be, pack_s24_32be
142 MAKE_ORC_PACK_UNPACK (s24_32be, s24_32be)
143 #define PACK_U24_32LE GST_AUDIO_FORMAT_S32, unpack_u24_32le, pack_u24_32le
144 MAKE_ORC_PACK_UNPACK (u24_32le, u24_32le)
145 #define PACK_U24_32BE GST_AUDIO_FORMAT_S32, unpack_u24_32be, pack_u24_32be
146 MAKE_ORC_PACK_UNPACK (u24_32be, u24_32be)
147 #define PACK_S32LE GST_AUDIO_FORMAT_S32, unpack_s32le, pack_s32le
148 MAKE_ORC_PACK_UNPACK (s32le, s32le)
149 #define PACK_S32BE GST_AUDIO_FORMAT_S32, unpack_s32be, pack_s32be
150 MAKE_ORC_PACK_UNPACK (s32be, s32be)
151 #define PACK_U32LE GST_AUDIO_FORMAT_S32, unpack_u32le, pack_u32le
152 MAKE_ORC_PACK_UNPACK (u32le, u32le)
153 #define PACK_U32BE GST_AUDIO_FORMAT_S32, unpack_u32be, pack_u32be
154 MAKE_ORC_PACK_UNPACK (u32be, u32be)
155 #define SIGNED (1U<<31)
156 /* pack from signed integer 32 to integer */
157 #define WRITE24_TO_LE(p,v) p[0] = v & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff
158 #define WRITE24_TO_BE(p,v) p[2] = v & 0xff; p[1] = (v >> 8) & 0xff; p[0] = (v >> 16) & 0xff
159 #define READ24_FROM_LE(p) (p[0] | (p[1] << 8) | (p[2] << 16))
160 #define READ24_FROM_BE(p) (p[2] | (p[1] << 8) | (p[0] << 16))
161 #define MAKE_PACK_UNPACK(name, stride, sign, scale, READ_FUNC, WRITE_FUNC) \
162 static void unpack_ ##name (const GstAudioFormatInfo *info, \
163 GstAudioPackFlags flags, gpointer dest, \
164 gconstpointer data, gint length) \
165 { \
166 guint32 *d = dest; \
167 const guint8 *s = data; \
168 for (;length; length--) { \
169 *d++ = (((gint32) READ_FUNC (s)) << scale) ^ (sign); \
170 s += stride; \
171 } \
172 } \
173 static void pack_ ##name (const GstAudioFormatInfo *info, \
174 GstAudioPackFlags flags, gconstpointer src, \
175 gpointer data, gint length) \
176 { \
177 gint32 tmp; \
178 const guint32 *s = src; \
179 guint8 *d = data; \
180 for (;length; length--) { \
181 tmp = (*s++ ^ (sign)) >> scale; \
182 WRITE_FUNC (d, tmp); \
183 d += stride; \
184 } \
185 }
186 #define PACK_S24LE GST_AUDIO_FORMAT_S32, unpack_s24le, pack_s24le
187 MAKE_PACK_UNPACK (s24le, 3, 0, 8, READ24_FROM_LE, WRITE24_TO_LE)
188 #define PACK_U24LE GST_AUDIO_FORMAT_S32, unpack_u24le, pack_u24le
189 MAKE_PACK_UNPACK (u24le, 3, SIGNED, 8, READ24_FROM_LE, WRITE24_TO_LE)
190 #define PACK_S24BE GST_AUDIO_FORMAT_S32, unpack_s24be, pack_s24be
191 MAKE_PACK_UNPACK (s24be, 3, 0, 8, READ24_FROM_BE, WRITE24_TO_BE)
192 #define PACK_U24BE GST_AUDIO_FORMAT_S32, unpack_u24be, pack_u24be
193 MAKE_PACK_UNPACK (u24be, 3, SIGNED, 8, READ24_FROM_BE, WRITE24_TO_BE)
194 #define PACK_S20LE GST_AUDIO_FORMAT_S32, unpack_s20le, pack_s20le
195 MAKE_PACK_UNPACK (s20le, 3, 0, 12, READ24_FROM_LE, WRITE24_TO_LE)
196 #define PACK_U20LE GST_AUDIO_FORMAT_S32, unpack_u20le, pack_u20le
197 MAKE_PACK_UNPACK (u20le, 3, SIGNED, 12, READ24_FROM_LE, WRITE24_TO_LE)
198 #define PACK_S20BE GST_AUDIO_FORMAT_S32, unpack_s20be, pack_s20be
199 MAKE_PACK_UNPACK (s20be, 3, 0, 12, READ24_FROM_BE, WRITE24_TO_BE)
200 #define PACK_U20BE GST_AUDIO_FORMAT_S32, unpack_u20be, pack_u20be
201 MAKE_PACK_UNPACK (u20be, 3, SIGNED, 12, READ24_FROM_BE, WRITE24_TO_BE)
202 #define PACK_S18LE GST_AUDIO_FORMAT_S32, unpack_s18le, pack_s18le
203 MAKE_PACK_UNPACK (s18le, 3, 0, 14, READ24_FROM_LE, WRITE24_TO_LE)
204 #define PACK_U18LE GST_AUDIO_FORMAT_S32, unpack_u18le, pack_u18le
205 MAKE_PACK_UNPACK (u18le, 3, SIGNED, 14, READ24_FROM_LE, WRITE24_TO_LE)
206 #define PACK_S18BE GST_AUDIO_FORMAT_S32, unpack_s18be, pack_s18be
207 MAKE_PACK_UNPACK (s18be, 3, 0, 14, READ24_FROM_BE, WRITE24_TO_BE)
208 #define PACK_U18BE GST_AUDIO_FORMAT_S32, unpack_u18be, pack_u18be
209 MAKE_PACK_UNPACK (u18be, 3, SIGNED, 14, READ24_FROM_BE, WRITE24_TO_BE)
210 #define PACK_F32LE GST_AUDIO_FORMAT_F64, unpack_f32le, pack_f32le
211 MAKE_ORC_PACK_UNPACK (f32le, f32le)
212 #define PACK_F32BE GST_AUDIO_FORMAT_F64, unpack_f32be, pack_f32be
213 MAKE_ORC_PACK_UNPACK (f32be, f32be)
214 #define PACK_F64LE GST_AUDIO_FORMAT_F64, unpack_f64le, pack_f64le
215 MAKE_ORC_PACK_UNPACK (f64le, f64le)
216 #define PACK_F64BE GST_AUDIO_FORMAT_F64, unpack_f64be, pack_f64be
217 MAKE_ORC_PACK_UNPACK (f64be, f64be)
218 #define SINT (GST_AUDIO_FORMAT_FLAG_INTEGER | GST_AUDIO_FORMAT_FLAG_SIGNED)
219 #define SINT_PACK (SINT | GST_AUDIO_FORMAT_FLAG_UNPACK)
220 #define UINT (GST_AUDIO_FORMAT_FLAG_INTEGER)
221 #define FLOAT (GST_AUDIO_FORMAT_FLAG_FLOAT)
222 #define FLOAT_PACK (FLOAT | GST_AUDIO_FORMAT_FLAG_UNPACK)
223 #define MAKE_FORMAT(str,desc,flags,end,width,depth,silent, pack) \
224 { GST_AUDIO_FORMAT_ ##str, G_STRINGIFY(str), desc, flags, end, width, depth, silent, pack }
225 #define SILENT_0 { 0, 0, 0, 0, 0, 0, 0, 0 }
226 #define SILENT_U8 { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
227 #define SILENT_U16LE { 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80 }
228 #define SILENT_U16BE { 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }
229 #define SILENT_U24_32LE { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00 }
230 #define SILENT_U24_32BE { 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 }
231 #define SILENT_U32LE { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80 }
232 #define SILENT_U32BE { 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }
233 #define SILENT_U24LE { 0x00, 0x00, 0x80, 0x00, 0x00, 0x80 }
234 #define SILENT_U24BE { 0x80, 0x00, 0x00, 0x80, 0x00, 0x00 }
235 #define SILENT_U20LE { 0x00, 0x00, 0x08, 0x00, 0x00, 0x08 }
236 #define SILENT_U20BE { 0x08, 0x00, 0x00, 0x08, 0x00, 0x00 }
237 #define SILENT_U18LE { 0x00, 0x00, 0x02, 0x00, 0x00, 0x02 }
238 #define SILENT_U18BE { 0x02, 0x00, 0x00, 0x02, 0x00, 0x00 }
239 static const GstAudioFormatInfo formats[] = {
240 {GST_AUDIO_FORMAT_UNKNOWN, "UNKNOWN", "Unknown audio", 0, 0, 0, 0},
241 {GST_AUDIO_FORMAT_ENCODED, "ENCODED", "Encoded audio",
242 GST_AUDIO_FORMAT_FLAG_COMPLEX, 0, 0, 0},
243 /* 8 bit */
244 MAKE_FORMAT (S8, "8-bit signed PCM audio", SINT, 0, 8, 8, SILENT_0,
245 PACK_S8),
246 MAKE_FORMAT (U8, "8-bit unsigned PCM audio", UINT, 0, 8, 8, SILENT_U8,
247 PACK_U8),
248 /* 16 bit */
249 MAKE_FORMAT (S16LE, "16-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 16,
250 16,
251 SILENT_0, PACK_S16LE),
252 MAKE_FORMAT (S16BE, "16-bit signed PCM audio", SINT, G_BIG_ENDIAN, 16,
253 16,
254 SILENT_0, PACK_S16BE),
255 MAKE_FORMAT (U16LE, "16-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN,
256 16,
257 16, SILENT_U16LE, PACK_U16LE),
258 MAKE_FORMAT (U16BE, "16-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 16,
259 16,
260 SILENT_U16BE, PACK_U16BE),
261 /* 24 bit in low 3 bytes of 32 bits */
262 MAKE_FORMAT (S24_32LE, "24-bit signed PCM audio", SINT, G_LITTLE_ENDIAN,
263 32,
264 24, SILENT_0, PACK_S24_32LE),
265 MAKE_FORMAT (S24_32BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32,
266 24,
267 SILENT_0, PACK_S24_32BE),
268 MAKE_FORMAT (U24_32LE, "24-bit unsigned PCM audio", UINT,
269 G_LITTLE_ENDIAN, 32,
270 24, SILENT_U24_32LE, PACK_U24_32LE),
271 MAKE_FORMAT (U24_32BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN,
272 32,
273 24, SILENT_U24_32BE, PACK_U24_32BE),
274 /* 32 bit */
275 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
276 MAKE_FORMAT (S32LE, "32-bit signed PCM audio", SINT_PACK,
277 G_LITTLE_ENDIAN, 32,
278 32, SILENT_0, PACK_S32LE),
279 MAKE_FORMAT (S32BE, "32-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32,
280 32,
281 SILENT_0, PACK_S32BE),
282 #else
283 MAKE_FORMAT (S32LE, "32-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 32,
284 32,
285 SILENT_0, PACK_S32LE),
286 MAKE_FORMAT (S32BE, "32-bit signed PCM audio", SINT_PACK, G_BIG_ENDIAN,
287 32,
288 32,
289 SILENT_0, PACK_S32BE),
290 #endif
291 MAKE_FORMAT (U32LE, "32-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN,
292 32,
293 32, SILENT_U32LE, PACK_U32LE),
294 MAKE_FORMAT (U32BE, "32-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32,
295 32,
296 SILENT_U32BE, PACK_U32BE),
297 /* 24 bit in 3 bytes */
298 MAKE_FORMAT (S24LE, "24-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24,
299 24,
300 SILENT_0, PACK_S24LE),
301 MAKE_FORMAT (S24BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24,
302 24,
303 SILENT_0, PACK_S24BE),
304 MAKE_FORMAT (U24LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN,
305 24,
306 24, SILENT_U24LE, PACK_U24LE),
307 MAKE_FORMAT (U24BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24,
308 24,
309 SILENT_U24BE, PACK_U24BE),
310 /* 20 bit in 3 bytes */
311 MAKE_FORMAT (S20LE, "20-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24,
312 20,
313 SILENT_0, PACK_S20LE),
314 MAKE_FORMAT (S20BE, "20-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24,
315 20,
316 SILENT_0, PACK_S20BE),
317 MAKE_FORMAT (U20LE, "20-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN,
318 24,
319 20, SILENT_U20LE, PACK_U20LE),
320 MAKE_FORMAT (U20BE, "20-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24,
321 20,
322 SILENT_U20BE, PACK_U20BE),
323 /* 18 bit in 3 bytes */
324 MAKE_FORMAT (S18LE, "18-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24,
325 18,
326 SILENT_0, PACK_S18LE),
327 MAKE_FORMAT (S18BE, "18-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24,
328 18,
329 SILENT_0, PACK_S18BE),
330 MAKE_FORMAT (U18LE, "18-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN,
331 24,
332 18, SILENT_U18LE, PACK_U18LE),
333 MAKE_FORMAT (U18BE, "18-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24,
334 18,
335 SILENT_U18BE, PACK_U18BE),
336 /* float */
337 MAKE_FORMAT (F32LE, "32-bit floating-point audio",
338 GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 32, 32, SILENT_0,
339 PACK_F32LE),
340 MAKE_FORMAT (F32BE, "32-bit floating-point audio",
341 GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 32, 32, SILENT_0,
342 PACK_F32BE),
343 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
344 MAKE_FORMAT (F64LE, "64-bit floating-point audio",
345 FLOAT_PACK, G_LITTLE_ENDIAN, 64, 64, SILENT_0, PACK_F64LE),
346 MAKE_FORMAT (F64BE, "64-bit floating-point audio",
347 FLOAT, G_BIG_ENDIAN, 64, 64, SILENT_0, PACK_F64BE)
348 #else
349 MAKE_FORMAT (F64LE, "64-bit floating-point audio",
350 FLOAT, G_LITTLE_ENDIAN, 64, 64, SILENT_0, PACK_F64LE),
351 MAKE_FORMAT (F64BE, "64-bit floating-point audio",
352 FLOAT_PACK, G_BIG_ENDIAN, 64, 64, SILENT_0, PACK_F64BE)
353 #endif
354 };
355
356 G_DEFINE_POINTER_TYPE (GstAudioFormatInfo, gst_audio_format_info);
357
358 /**
359 * gst_audio_format_build_integer:
360 * @sign: signed or unsigned format
361 * @endianness: G_LITTLE_ENDIAN or G_BIG_ENDIAN
362 * @width: amount of bits used per sample
363 * @depth: amount of used bits in @width
364 *
365 * Construct a #GstAudioFormat with given parameters.
366 *
367 * Returns: a #GstAudioFormat or GST_AUDIO_FORMAT_UNKNOWN when no audio format
368 * exists with the given parameters.
369 */
370 GstAudioFormat
gst_audio_format_build_integer(gboolean sign,gint endianness,gint width,gint depth)371 gst_audio_format_build_integer (gboolean sign, gint endianness,
372 gint width, gint depth)
373 {
374 gint i, e;
375
376 for (i = 0; i < G_N_ELEMENTS (formats); i++) {
377 const GstAudioFormatInfo *finfo = &formats[i];
378
379 /* must be int */
380 if (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (finfo))
381 continue;
382
383 /* width and depth must match */
384 if (width != GST_AUDIO_FORMAT_INFO_WIDTH (finfo))
385 continue;
386 if (depth != GST_AUDIO_FORMAT_INFO_DEPTH (finfo))
387 continue;
388
389 /* if there is endianness, it must match */
390 e = GST_AUDIO_FORMAT_INFO_ENDIANNESS (finfo);
391 if (e && e != endianness)
392 continue;
393
394 /* check sign */
395 if ((sign && !GST_AUDIO_FORMAT_INFO_IS_SIGNED (finfo)) ||
396 (!sign && GST_AUDIO_FORMAT_INFO_IS_SIGNED (finfo)))
397 continue;
398
399 return GST_AUDIO_FORMAT_INFO_FORMAT (finfo);
400 }
401 return GST_AUDIO_FORMAT_UNKNOWN;
402 }
403
404 /**
405 * gst_audio_format_from_string:
406 * @format: a format string
407 *
408 * Convert the @format string to its #GstAudioFormat.
409 *
410 * Returns: the #GstAudioFormat for @format or GST_AUDIO_FORMAT_UNKNOWN when the
411 * string is not a known format.
412 */
413 GstAudioFormat
gst_audio_format_from_string(const gchar * format)414 gst_audio_format_from_string (const gchar * format)
415 {
416 guint i;
417
418 g_return_val_if_fail (format != NULL, GST_AUDIO_FORMAT_UNKNOWN);
419
420 for (i = 0; i < G_N_ELEMENTS (formats); i++) {
421 if (strcmp (GST_AUDIO_FORMAT_INFO_NAME (&formats[i]), format) == 0)
422 return GST_AUDIO_FORMAT_INFO_FORMAT (&formats[i]);
423 }
424 return GST_AUDIO_FORMAT_UNKNOWN;
425 }
426
427 const gchar *
gst_audio_format_to_string(GstAudioFormat format)428 gst_audio_format_to_string (GstAudioFormat format)
429 {
430 g_return_val_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN, NULL);
431
432 if ((gint) format >= G_N_ELEMENTS (formats))
433 return NULL;
434
435 return GST_AUDIO_FORMAT_INFO_NAME (&formats[format]);
436 }
437
438 /**
439 * gst_audio_format_get_info:
440 * @format: a #GstAudioFormat
441 *
442 * Get the #GstAudioFormatInfo for @format
443 *
444 * Returns: The #GstAudioFormatInfo for @format.
445 */
446 const GstAudioFormatInfo *
gst_audio_format_get_info(GstAudioFormat format)447 gst_audio_format_get_info (GstAudioFormat format)
448 {
449 g_return_val_if_fail ((gint) format < G_N_ELEMENTS (formats), NULL);
450
451 return &formats[format];
452 }
453
454 /**
455 * gst_audio_format_fill_silence:
456 * @info: a #GstAudioFormatInfo
457 * @dest: (array length=length) (element-type guint8): a destination
458 * to fill
459 * @length: the length to fill
460 *
461 * Fill @length bytes in @dest with silence samples for @info.
462 *
463 * Deprecated: 1.20: Use gst_audio_format_info_fill_silence() instead.
464 */
465 void
gst_audio_format_fill_silence(const GstAudioFormatInfo * info,gpointer dest,gsize length)466 gst_audio_format_fill_silence (const GstAudioFormatInfo * info,
467 gpointer dest, gsize length)
468 {
469 gst_audio_format_info_fill_silence (info, dest, length);
470 }
471
472 /**
473 * gst_audio_format_info_fill_silence:
474 * @info: a #GstAudioFormatInfo
475 * @dest: (array length=length) (element-type guint8): a destination
476 * to fill
477 * @length: the length to fill
478 *
479 * Fill @length bytes in @dest with silence samples for @info.
480 *
481 * Since: 1.20
482 */
483 void
gst_audio_format_info_fill_silence(const GstAudioFormatInfo * info,gpointer dest,gsize length)484 gst_audio_format_info_fill_silence (const GstAudioFormatInfo * info,
485 gpointer dest, gsize length)
486 {
487 guint8 *dptr = dest;
488
489 g_return_if_fail (info != NULL);
490 g_return_if_fail (dest != NULL);
491
492 if (info->flags & GST_AUDIO_FORMAT_FLAG_FLOAT ||
493 info->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) {
494 /* float or signed always 0 */
495 orc_memset (dest, 0, length);
496 } else {
497 gint i, j, bps = info->width >> 3;
498
499 switch (bps) {
500 case 1:
501 orc_memset (dest, info->silence[0], length);
502 break;
503 case 2:{
504 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
505 guint16 silence = GST_READ_UINT16_LE (info->silence);
506 #else
507 guint16 silence = GST_READ_UINT16_BE (info->silence);
508 #endif
509 audio_orc_splat_u16 (dest, silence, length / bps);
510 break;
511 }
512 case 4:{
513 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
514 guint32 silence = GST_READ_UINT32_LE (info->silence);
515 #else
516 guint32 silence = GST_READ_UINT32_BE (info->silence);
517 #endif
518 audio_orc_splat_u32 (dest, silence, length / bps);
519 break;
520 }
521 case 8:{
522 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
523 guint64 silence = GST_READ_UINT64_LE (info->silence);
524 #else
525 guint64 silence = GST_READ_UINT64_BE (info->silence);
526 #endif
527 audio_orc_splat_u64 (dest, silence, length / bps);
528 break;
529 }
530 default:
531 for (i = 0; i < length; i += bps) {
532 for (j = 0; j < bps; j++)
533 *dptr++ = info->silence[j];
534 }
535 break;
536 }
537 }
538 }
539
540 struct RawAudioFormats
541 {
542 GstAudioFormat *formats;
543 guint n;
544 };
545
546 static gpointer
generate_raw_audio_formats(gpointer data)547 generate_raw_audio_formats (gpointer data)
548 {
549 GValue list = G_VALUE_INIT;
550 struct RawAudioFormats *all = g_new (struct RawAudioFormats, 1);
551 gchar *tmp;
552 guint i;
553 gboolean res G_GNUC_UNUSED;
554
555 g_value_init (&list, GST_TYPE_LIST);
556 /* Workaround a bug in our parser that would lead to segfaults
557 * when deserializing container types using static strings,
558 * see https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/446 */
559 tmp = g_strdup (GST_AUDIO_FORMATS_ALL);
560 res = gst_value_deserialize (&list, tmp);
561 g_assert (res);
562 g_free (tmp);
563
564 all->n = gst_value_list_get_size (&list);
565 all->formats = g_new (GstAudioFormat, all->n);
566
567 for (i = 0; i < all->n; i++) {
568 const GValue *v = gst_value_list_get_value (&list, i);
569
570 all->formats[i] = gst_audio_format_from_string (g_value_get_string (v));
571 g_assert (all->formats[i] != GST_AUDIO_FORMAT_UNKNOWN
572 && all->formats[i] != GST_AUDIO_FORMAT_ENCODED);
573 }
574
575 g_value_unset (&list);
576
577 return all;
578 }
579
580 /**
581 * gst_audio_formats_raw:
582 * @len: (out): the number of elements in the returned array
583 *
584 * Return all the raw audio formats supported by GStreamer.
585 *
586 * Returns: (transfer none) (array length=len): an array of #GstAudioFormat
587 * Since: 1.18
588 */
589 const GstAudioFormat *
gst_audio_formats_raw(guint * len)590 gst_audio_formats_raw (guint * len)
591 {
592 static GOnce raw_audio_formats_once = G_ONCE_INIT;
593 struct RawAudioFormats *all;
594
595 g_return_val_if_fail (len, NULL);
596
597 g_once (&raw_audio_formats_once, generate_raw_audio_formats, NULL);
598
599 all = raw_audio_formats_once.retval;
600 *len = all->n;
601 return all->formats;
602 }
603
604 /**
605 * gst_audio_make_raw_caps:
606 * @formats: (array length=len) (nullable): an array of raw #GstAudioFormat, or %NULL
607 * @len: the size of @formats
608 * @layout: the layout of audio samples
609 *
610 * Return a generic raw audio caps for formats defined in @formats.
611 * If @formats is %NULL returns a caps for all the supported raw audio formats,
612 * see gst_audio_formats_raw().
613 *
614 * Returns: (transfer full): an audio @GstCaps
615 * Since: 1.18
616 */
617 GstCaps *
gst_audio_make_raw_caps(const GstAudioFormat formats[],guint len,GstAudioLayout layout)618 gst_audio_make_raw_caps (const GstAudioFormat formats[], guint len,
619 GstAudioLayout layout)
620 {
621 GstStructure *s;
622 GValue format = G_VALUE_INIT;
623 GstCaps *caps;
624 const gchar *layout_str;
625
626 g_return_val_if_fail ((formats && len > 0) || (!formats && len == 0), NULL);
627
628 if (!formats) {
629 formats = gst_audio_formats_raw (&len);
630 }
631
632 if (len > 1) {
633 guint i;
634
635 g_value_init (&format, GST_TYPE_LIST);
636
637 for (i = 0; i < len; i++) {
638 GValue v = G_VALUE_INIT;
639
640 g_return_val_if_fail (formats[i] != GST_AUDIO_FORMAT_UNKNOWN
641 && formats[i] != GST_AUDIO_FORMAT_ENCODED, NULL);
642
643 g_value_init (&v, G_TYPE_STRING);
644 g_value_set_static_string (&v, gst_audio_format_to_string (formats[i]));
645 gst_value_list_append_and_take_value (&format, &v);
646 }
647 } else {
648 g_value_init (&format, G_TYPE_STRING);
649
650 g_value_set_static_string (&format,
651 gst_audio_format_to_string (formats[0]));
652 }
653
654 if (layout == GST_AUDIO_LAYOUT_INTERLEAVED)
655 layout_str = "interleaved";
656 else
657 layout_str = "non-interleaved";
658
659 s = gst_structure_new ("audio/x-raw",
660 "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
661 "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT,
662 "layout", G_TYPE_STRING, layout_str, NULL);
663
664 gst_structure_take_value (s, "format", &format);
665
666 caps = gst_caps_new_full (s, NULL);
667
668 return caps;
669 }
670