1/* GStreamer
2 * Copyright (C) 2023 Carlos Rafael Giani <crg7475@mailbox.org>
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#pragma once
21
22#include <gst/gst.h>
23#include <gst/audio/audio.h>
24#include <gst/audio/gstdsdformat.h>
25
26G_BEGIN_DECLS
27
28/**
29 * GST_DSD_MEDIA_TYPE:
30 *
31 * The GStreamer media type for DSD.
32 *
33 * Since: 1.24
34 */
35#define GST_DSD_MEDIA_TYPE "audio/x-dsd"
36
37/**
38 * GST_DSD_CAPS_MAKE:
39 * @format: string format that describes the DSD bits grouping,
40 * as string (e.g. "DSDU32BE", "DSDU8", etc.)
41 *
42 * Generic caps string for DSD audio, for use in pad templates.
43 *
44 * Since: 1.24
45 */
46#define GST_DSD_CAPS_MAKE(format) \
47 GST_DSD_MEDIA_TYPE ", " \
48 "format = (string) " format ", " \
49 "rate = " GST_AUDIO_RATE_RANGE ", " \
50 "layout = (string) { interleaved, non-interleaved }, " \
51 "reversed-bytes = (gboolean) { false, true }, " \
52 "channels = " GST_AUDIO_CHANNELS_RANGE
53
54/**
55 * GST_DSD_MAKE_DSD_RATE_44x:
56 *
57 * Calculates a valid DSD-44x rate (in bytes) from commonly used rate
58 * multiplier specifications like DSD64, DSD128 etc.
59 *
60 * For example, to get the rate for DSD64-44x, use 64 as the multiplier
61 * argument.
62 *
63 * Since: 1.24
64 */
65#define GST_DSD_MAKE_DSD_RATE_44x(multiplier) \
66 ((gint) ((gint64) multiplier) * 44100 / 8)
67
68/**
69 * GST_DSD_MAKE_DSD_RATE_48x:
70 *
71 * Calculates a valid DSD-48x rate (in bytes) from commonly used rate
72 * multiplier specifications like DSD64, DSD128 etc.
73 *
74 * For example, to get the rate for DSD64-48x, use 64 as the multiplier
75 * argument.
76 *
77 * Since: 1.24
78 */
79#define GST_DSD_MAKE_DSD_RATE_48x(multiplier) \
80 ((gint) ((gint64) multiplier) * 48000 / 8)
81/**
82 * GST_DSD_SILENCE_PATTERN_BYTE:
83 *
84 * Silence pattern for DSD data.
85 *
86 * In DSD, a nullbyte does not correspond to silence. To fill memory regions
87 * with "DSD silence", these regions must be filled with byte 0x69 instead
88 * (this is the DSD silence pattern). This constant provides that pattern
89 * in a more readable fashion.
90 *
91 * Since: 1.24
92 */
93#define GST_DSD_SILENCE_PATTERN_BYTE (0x69)
94
95typedef struct _GstDsdInfo GstDsdInfo;
96
97/**
98 * GstDsdInfo:
99 * @format: DSD grouping format
100 * @rate: DSD rate
101 * @channels: number of channels (must be at least 1)
102 * @layout: audio layout
103 * @reversed_bytes: true if the DSD bits in the data bytes are reversed,
104 * that is, the least significant bit comes first
105 * @positions: positions for each channel
106 *
107 * Information describing DSD audio properties.
108 *
109 * In DSD, the "sample format" is the bit. Unlike PCM, there are no further
110 * "sample formats" in DSD. However, in software, DSD bits are grouped into
111 * bytes (since dealing with individual bits is impractical), and these bytes
112 * in turn are grouped into words. This becomes relevant when interleaving
113 * channels and transmitting DSD data through audio APIs. The different
114 * types of grouping DSD bytes are referred to as the "DSD grouping forma"
115 * or just "DSD format". #GstDsdFormat has a list of valid ways of grouping
116 * DSD bytes into words.
117 *
118 * DSD rates are equivalent to PCM sample rates, except that they specify
119 * how many DSD bytes are consumed per second. This refers to the bytes per
120 * second _per channel_; the rate does not change when the number of channel
121 * changes. (Strictly speaking, it would be more correct to measure the
122 * *bits* per second, since the bit is the DSD "sample format", but it is
123 * more practical to use bytes.) In DSD, bit rates are always an integer
124 * multiple of the CD audio rate (44100) or the DAT rate (48000). DSD64-44x
125 * is 44100 * 64 = 2822400 bits per second, or 352800 bytes per second
126 * (the latter would be used in this info structure). DSD64-48x is
127 * 48000 * 64 = 3072000 bits per second, or 384000 bytes per second.
128 * #GST_DSD_MAKE_DSD_RATE_44x can be used for specifying DSD-44x rates,
129 * *and #GST_DSD_MAKE_DSD_RATE_48x can be used for specifying DSD-48x ones.
130 * Also, since DSD-48x is less well known, when the multiplier is given
131 * without the 44x/48x specifier, 44x is typically implied.
132 *
133 * It is important to know that in DSD, different format widths correspond
134 * to different playtimes. That is, a word with 32 DSD bits covers two times
135 * as much playtime as a word with 16 DSD bits. This is in contrast to PCM,
136 * where one word (= one PCM sample) always covers a time period of 1/samplerate,
137 * no matter how many bits a PCM sample is made of. For this reason, DSD
138 * and PCM widths and strides cannot be used the same way.
139 *
140 * Multiple channels are arranged in DSD data either interleaved or non-
141 * interleaved. This is similar to PCM. Interleaved layouts rotate between
142 * channels and words. First, word 0 of channel 0 is present. Then word
143 * 0 of channel 1 follows. Then word 0 of channel 2 etc. until all
144 * channels are through, then comes word 1 of channel 0 etc.
145 *
146 * Non-interleaved data is planar. First, all words of channel 0 are
147 * present, then all words of channel 1 etc. Unlike interleaved data,
148 * non-interleaved data can be sparse, that is, there can be space in
149 * between the planes. the @positions array specifies the plane offsets.
150 *
151 * In uncommon cases, the DSD bits in the data bytes can be stored in reverse
152 * order. For example, normally, in DSDU8, the first byte contains DSD bits
153 * 0 to 7, and the most significant bit of that byte is DSD bit 0. If this
154 * order is reversed, then bit 7 is the first one instead. In that ase,
155 * @reversed_bytes is set to TRUE.
156 *
157 * Use the provided macros to access the info in this structure.
158 *
159 * Since: 1.24
160 */
161struct _GstDsdInfo {
162 GstDsdFormat format;
163 gint rate;
164 gint channels;
165 GstAudioLayout layout;
166 gboolean reversed_bytes;
167 GstAudioChannelPosition positions[64];
168 GstAudioFlags flags;
169
170 /*< private >*/
171 gpointer _gst_reserved[GST_PADDING];
172};
173
174#define GST_TYPE_DSD_INFO (gst_dsd_info_get_type ())
175GST_AUDIO_API
176GType gst_dsd_info_get_type (void);
177
178#define GST_DSD_INFO_IS_VALID(i) ((i)->format < GST_NUM_DSD_FORMATS && (i)->rate > 0 && (i)->channels > 0)
179
180#define GST_DSD_INFO_FORMAT(info) ((info)->format)
181#define GST_DSD_INFO_RATE(info) ((info)->rate)
182#define GST_DSD_INFO_CHANNELS(info) ((info)->channels)
183#define GST_DSD_INFO_LAYOUT(info) ((info)->layout)
184#define GST_DSD_INFO_REVERSED_BYTES(info) ((info)->reversed_bytes)
185#define GST_DSD_INFO_POSITION(info,c) ((info)->position[c])
186
187/**
188 * GST_DSD_INFO_STRIDE:
189 *
190 * Calculates the stride for a given #GstDsdInfo.
191 *
192 * Note that this is only useful if the info's audio layout
193 * is GST_AUDIO_LAYOUT_INTERLEAVED.
194 *
195 * Since: 1.24
196 */
197#define GST_DSD_INFO_STRIDE(info) (gst_dsd_format_get_width((info)->format) * (info)->channels)
198
199/*** GstDsdPlaneOffsetMeta ***/
200
201#define GST_DSD_PLANE_OFFSET_META_API_TYPE (gst_dsd_plane_offset_meta_api_get_type())
202#define GST_DSD_PLANE_OFFSET_META_INFO (gst_dsd_plane_offset_meta_get_info())
203
204/**
205 * GST_META_TAG_DSD_PLANE_OFFSETS_STR:
206 *
207 * This metadata stays relevant as long as the DSD plane offsets are unchanged.
208 *
209 * Since: 1.24
210 */
211#define GST_META_TAG_DSD_PLANE_OFFSETS_STR "dsdplaneoffsets"
212
213typedef struct _GstDsdPlaneOffsetMeta GstDsdPlaneOffsetMeta;
214
215/**
216 * GstDsdPlaneOffsetMeta:
217 * @meta: parent #GstMeta
218 * @num_channels: number of channels in the DSD data
219 * @num_bytes_per_channel: the number of valid bytes per channel in the buffer
220 * @offsets: the offsets (in bytes) where each channel plane starts in the buffer
221 *
222 * Buffer metadata describing planar DSD contents in the buffer. This is not needed
223 * for interleaved DSD data, and is required for non-interleaved (= planar) data.
224 *
225 * The different channels in @offsets are always in the GStreamer channel order.
226 * Zero-copy channel reordering can be implemented by swapping the values in
227 * @offsets.
228 *
229 * It is not allowed for channels to overlap in memory,
230 * i.e. for each i in [0, channels), the range
231 * [@offsets[i], @offsets[i] + @num_bytes_per_channel) must not overlap
232 * with any other such range.
233 *
234 * It is, however, allowed to have parts of the buffer memory unused, by using
235 * @offsets and @num_bytes_per_channel in such a way that leave gaps on it.
236 * This is used to implement zero-copy clipping in non-interleaved buffers.
237 *
238 * Obviously, due to the above, it is not safe to infer the
239 * number of valid bytes from the size of the buffer. You should always
240 * use the @num_bytes_per_channel variable of this metadata.
241 *
242 * Since: 1.24
243 */
244struct _GstDsdPlaneOffsetMeta {
245 GstMeta meta;
246 gint num_channels;
247 gsize num_bytes_per_channel;
248 gsize *offsets;
249
250 /*< private >*/
251 gsize priv_offsets_arr[8];
252 gpointer _gst_reserved[GST_PADDING];
253};
254
255GST_AUDIO_API
256GType gst_dsd_plane_offset_meta_api_get_type (void);
257
258GST_AUDIO_API
259const GstMetaInfo * gst_dsd_plane_offset_meta_get_info (void);
260
261#define gst_buffer_get_dsd_plane_offset_meta(b) \
262 ((GstDsdPlaneOffsetMeta*)gst_buffer_get_meta((b), GST_DSD_PLANE_OFFSET_META_API_TYPE))
263
264GST_AUDIO_API
265GstDsdPlaneOffsetMeta * gst_buffer_add_dsd_plane_offset_meta (GstBuffer *buffer,
266 gint num_channels,
267 gsize num_bytes_per_channel,
268 gsize offsets[]);
269
270GST_AUDIO_API
271GstDsdInfo * gst_dsd_info_new (void);
272
273GST_AUDIO_API
274GstDsdInfo * gst_dsd_info_new_from_caps (const GstCaps * caps);
275
276GST_AUDIO_API
277void gst_dsd_info_init (GstDsdInfo * info);
278
279GST_AUDIO_API
280void gst_dsd_info_set_format (GstDsdInfo * info,
281 GstDsdFormat format,
282 gint rate,
283 gint channels,
284 const GstAudioChannelPosition * positions);
285
286GST_AUDIO_API
287GstDsdInfo * gst_dsd_info_copy (const GstDsdInfo * info);
288
289GST_AUDIO_API
290void gst_dsd_info_free (GstDsdInfo * info);
291
292GST_AUDIO_API
293gboolean gst_dsd_info_from_caps (GstDsdInfo *info,
294 const GstCaps *caps);
295
296GST_AUDIO_API
297GstCaps * gst_dsd_info_to_caps (const GstDsdInfo *info);
298
299GST_AUDIO_API
300gboolean gst_dsd_info_is_equal (const GstDsdInfo *info,
301 const GstDsdInfo *other);
302
303GST_AUDIO_API
304void gst_dsd_convert (const guint8 *input_data,
305 guint8 *output_data,
306 GstDsdFormat input_format,
307 GstDsdFormat output_format,
308 GstAudioLayout input_layout,
309 GstAudioLayout output_layout,
310 const gsize *input_plane_offsets,
311 const gsize *output_plane_offsets,
312 gsize num_dsd_bytes,
313 gint num_channels,
314 gboolean reverse_byte_bits);
315
316/**
317 * gst_dsd_format_is_le:
318 * @format: The format.
319 *
320 * Useful for determining whether a format is a little-endian.
321 * GST_DSD_FORMAT_U8 and GST_DSD_FORMAT_UNKNOWN
322 * are not considered little-endian.
323 *
324 * Returns: TRUE if the format is a little-endian one.
325 */
326static inline gboolean
327gst_dsd_format_is_le (GstDsdFormat format)
328{
329 switch (format) {
330 case GST_DSD_FORMAT_U16LE:
331 case GST_DSD_FORMAT_U32LE:
332 return TRUE;
333 default:
334 return FALSE;
335 }
336}
337
338G_END_DECLS
339

source code of include/gstreamer-1.0/gst/audio/gstdsd.h