• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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