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