1 /******************************************************************************
2 Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18 #pragma once
19
20 #include "media-io-defs.h"
21 #include "../util/c99defs.h"
22 #include "../util/util_uint64.h"
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 #define MAX_AUDIO_MIXES 6
29 #define MAX_AUDIO_CHANNELS 8
30 #define AUDIO_OUTPUT_FRAMES 1024
31
32 #define TOTAL_AUDIO_SIZE \
33 (MAX_AUDIO_MIXES * MAX_AUDIO_CHANNELS * AUDIO_OUTPUT_FRAMES * \
34 sizeof(float))
35
36 /*
37 * Base audio output component. Use this to create an audio output track
38 * for the media.
39 */
40
41 struct audio_output;
42 typedef struct audio_output audio_t;
43
44 enum audio_format {
45 AUDIO_FORMAT_UNKNOWN,
46
47 AUDIO_FORMAT_U8BIT,
48 AUDIO_FORMAT_16BIT,
49 AUDIO_FORMAT_32BIT,
50 AUDIO_FORMAT_FLOAT,
51
52 AUDIO_FORMAT_U8BIT_PLANAR,
53 AUDIO_FORMAT_16BIT_PLANAR,
54 AUDIO_FORMAT_32BIT_PLANAR,
55 AUDIO_FORMAT_FLOAT_PLANAR,
56 };
57
58 /**
59 * The speaker layout describes where the speakers are located in the room.
60 * For OBS it dictates:
61 * * how many channels are available and
62 * * which channels are used for which speakers.
63 *
64 * Standard channel layouts where retrieved from ffmpeg documentation at:
65 * https://trac.ffmpeg.org/wiki/AudioChannelManipulation
66 */
67 enum speaker_layout {
68 SPEAKERS_UNKNOWN, /**< Unknown setting, fallback is stereo. */
69 SPEAKERS_MONO, /**< Channels: MONO */
70 SPEAKERS_STEREO, /**< Channels: FL, FR */
71 SPEAKERS_2POINT1, /**< Channels: FL, FR, LFE */
72 SPEAKERS_4POINT0, /**< Channels: FL, FR, FC, RC */
73 SPEAKERS_4POINT1, /**< Channels: FL, FR, FC, LFE, RC */
74 SPEAKERS_5POINT1, /**< Channels: FL, FR, FC, LFE, RL, RR */
75 SPEAKERS_7POINT1 = 8, /**< Channels: FL, FR, FC, LFE, RL, RR, SL, SR */
76 };
77
78 struct audio_data {
79 uint8_t *data[MAX_AV_PLANES];
80 uint32_t frames;
81 uint64_t timestamp;
82 };
83
84 struct audio_output_data {
85 float *data[MAX_AUDIO_CHANNELS];
86 };
87
88 typedef bool (*audio_input_callback_t)(void *param, uint64_t start_ts,
89 uint64_t end_ts, uint64_t *new_ts,
90 uint32_t active_mixers,
91 struct audio_output_data *mixes);
92
93 struct audio_output_info {
94 const char *name;
95
96 uint32_t samples_per_sec;
97 enum audio_format format;
98 enum speaker_layout speakers;
99
100 audio_input_callback_t input_callback;
101 void *input_param;
102 };
103
104 struct audio_convert_info {
105 uint32_t samples_per_sec;
106 enum audio_format format;
107 enum speaker_layout speakers;
108 };
109
get_audio_channels(enum speaker_layout speakers)110 static inline uint32_t get_audio_channels(enum speaker_layout speakers)
111 {
112 switch (speakers) {
113 case SPEAKERS_MONO:
114 return 1;
115 case SPEAKERS_STEREO:
116 return 2;
117 case SPEAKERS_2POINT1:
118 return 3;
119 case SPEAKERS_4POINT0:
120 return 4;
121 case SPEAKERS_4POINT1:
122 return 5;
123 case SPEAKERS_5POINT1:
124 return 6;
125 case SPEAKERS_7POINT1:
126 return 8;
127 case SPEAKERS_UNKNOWN:
128 return 0;
129 }
130
131 return 0;
132 }
133
get_audio_bytes_per_channel(enum audio_format format)134 static inline size_t get_audio_bytes_per_channel(enum audio_format format)
135 {
136 switch (format) {
137 case AUDIO_FORMAT_U8BIT:
138 case AUDIO_FORMAT_U8BIT_PLANAR:
139 return 1;
140
141 case AUDIO_FORMAT_16BIT:
142 case AUDIO_FORMAT_16BIT_PLANAR:
143 return 2;
144
145 case AUDIO_FORMAT_FLOAT:
146 case AUDIO_FORMAT_FLOAT_PLANAR:
147 case AUDIO_FORMAT_32BIT:
148 case AUDIO_FORMAT_32BIT_PLANAR:
149 return 4;
150
151 case AUDIO_FORMAT_UNKNOWN:
152 return 0;
153 }
154
155 return 0;
156 }
157
is_audio_planar(enum audio_format format)158 static inline bool is_audio_planar(enum audio_format format)
159 {
160 switch (format) {
161 case AUDIO_FORMAT_U8BIT:
162 case AUDIO_FORMAT_16BIT:
163 case AUDIO_FORMAT_32BIT:
164 case AUDIO_FORMAT_FLOAT:
165 return false;
166
167 case AUDIO_FORMAT_U8BIT_PLANAR:
168 case AUDIO_FORMAT_FLOAT_PLANAR:
169 case AUDIO_FORMAT_16BIT_PLANAR:
170 case AUDIO_FORMAT_32BIT_PLANAR:
171 return true;
172
173 case AUDIO_FORMAT_UNKNOWN:
174 return false;
175 }
176
177 return false;
178 }
179
get_audio_planes(enum audio_format format,enum speaker_layout speakers)180 static inline size_t get_audio_planes(enum audio_format format,
181 enum speaker_layout speakers)
182 {
183 return (is_audio_planar(format) ? get_audio_channels(speakers) : 1);
184 }
185
get_audio_size(enum audio_format format,enum speaker_layout speakers,uint32_t frames)186 static inline size_t get_audio_size(enum audio_format format,
187 enum speaker_layout speakers,
188 uint32_t frames)
189 {
190 bool planar = is_audio_planar(format);
191
192 return (planar ? 1 : get_audio_channels(speakers)) *
193 get_audio_bytes_per_channel(format) * frames;
194 }
195
audio_frames_to_ns(size_t sample_rate,uint64_t frames)196 static inline uint64_t audio_frames_to_ns(size_t sample_rate, uint64_t frames)
197 {
198 return util_mul_div64(frames, 1000000000ULL, sample_rate);
199 }
200
ns_to_audio_frames(size_t sample_rate,uint64_t frames)201 static inline uint64_t ns_to_audio_frames(size_t sample_rate, uint64_t frames)
202 {
203 return util_mul_div64(frames, sample_rate, 1000000000ULL);
204 }
205
206 #define AUDIO_OUTPUT_SUCCESS 0
207 #define AUDIO_OUTPUT_INVALIDPARAM -1
208 #define AUDIO_OUTPUT_FAIL -2
209
210 EXPORT int audio_output_open(audio_t **audio, struct audio_output_info *info);
211 EXPORT void audio_output_close(audio_t *audio);
212
213 typedef void (*audio_output_callback_t)(void *param, size_t mix_idx,
214 struct audio_data *data);
215
216 EXPORT bool audio_output_connect(audio_t *video, size_t mix_idx,
217 const struct audio_convert_info *conversion,
218 audio_output_callback_t callback, void *param);
219 EXPORT void audio_output_disconnect(audio_t *video, size_t mix_idx,
220 audio_output_callback_t callback,
221 void *param);
222
223 EXPORT bool audio_output_active(const audio_t *audio);
224
225 EXPORT size_t audio_output_get_block_size(const audio_t *audio);
226 EXPORT size_t audio_output_get_planes(const audio_t *audio);
227 EXPORT size_t audio_output_get_channels(const audio_t *audio);
228 EXPORT uint32_t audio_output_get_sample_rate(const audio_t *audio);
229 EXPORT const struct audio_output_info *
230 audio_output_get_info(const audio_t *audio);
231
232 #ifdef __cplusplus
233 }
234 #endif
235