Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2016-2026 The TokTok team. |
3 | | * Copyright © 2013-2015 Tox project. |
4 | | */ |
5 | | #include "audio.h" |
6 | | |
7 | | #include <assert.h> |
8 | | #include <opus.h> |
9 | | #include <pthread.h> |
10 | | #include <stdlib.h> |
11 | | #include <string.h> |
12 | | |
13 | | #include "rtp.h" |
14 | | |
15 | | #include "../toxcore/attributes.h" |
16 | | #include "../toxcore/ccompat.h" |
17 | | #include "../toxcore/logger.h" |
18 | | #include "../toxcore/mono_time.h" |
19 | | #include "../toxcore/network.h" |
20 | | #include "../toxcore/util.h" |
21 | | |
22 | | |
23 | | struct ACSession { |
24 | | Mono_Time *_Nonnull mono_time; |
25 | | const Logger *_Nonnull log; |
26 | | |
27 | | /* encoding */ |
28 | | OpusEncoder *_Nullable encoder; |
29 | | uint32_t le_sample_rate; /* Last encoder sample rate */ |
30 | | uint8_t le_channel_count; /* Last encoder channel count */ |
31 | | uint32_t le_bit_rate; /* Last encoder bit rate */ |
32 | | |
33 | | /* decoding */ |
34 | | OpusDecoder *_Nullable decoder; |
35 | | uint8_t lp_channel_count; /* Last packet channel count */ |
36 | | uint32_t lp_sampling_rate; /* Last packet sample rate */ |
37 | | uint32_t lp_frame_duration; /* Last packet frame duration */ |
38 | | uint32_t ld_sample_rate; /* Last decoder sample rate */ |
39 | | uint8_t ld_channel_count; /* Last decoder channel count */ |
40 | | uint64_t ldrts; /* Last decoder reconfiguration time stamp */ |
41 | | void *_Nullable j_buf; |
42 | | |
43 | | pthread_mutex_t queue_mutex[1]; |
44 | | |
45 | | int16_t *_Nullable decode_buffer; |
46 | | |
47 | | uint32_t friend_number; |
48 | | /* Audio frame receive callback */ |
49 | | ac_audio_receive_frame_cb *_Nullable acb; |
50 | | void *_Nullable user_data; |
51 | | }; |
52 | | |
53 | | |
54 | | static struct JitterBuffer *_Nullable jbuf_new(uint32_t capacity); |
55 | | static void jbuf_clear(struct JitterBuffer *_Nonnull q); |
56 | | static void jbuf_free(struct JitterBuffer *_Nullable q); |
57 | | static int jbuf_write(const Logger *_Nonnull log, struct JitterBuffer *_Nonnull q, struct RTPMessage *_Nonnull m); |
58 | | static struct RTPMessage *_Nullable jbuf_read(struct JitterBuffer *_Nonnull q, int32_t *_Nonnull success); |
59 | | static OpusEncoder *_Nullable create_audio_encoder(const Logger *_Nonnull log, uint32_t bit_rate, uint32_t sampling_rate, |
60 | | uint8_t channel_count); |
61 | | static bool reconfigure_audio_encoder(const Logger *_Nonnull log, OpusEncoder *_Nonnull *_Nonnull e, uint32_t new_br, uint32_t new_sr, |
62 | | uint8_t new_ch, uint32_t *_Nonnull old_br, uint32_t *_Nonnull old_sr, uint8_t *_Nonnull old_ch); |
63 | | static bool reconfigure_audio_decoder(ACSession *_Nonnull ac, uint32_t sampling_rate, uint8_t channels); |
64 | | |
65 | | |
66 | | |
67 | | ACSession *ac_new(Mono_Time *mono_time, const Logger *log, uint32_t friend_number, |
68 | | ac_audio_receive_frame_cb *cb, void *user_data) |
69 | 25 | { |
70 | 25 | ACSession *ac = (ACSession *)calloc(1, sizeof(ACSession)); |
71 | | |
72 | 25 | if (ac == nullptr) { |
73 | 0 | LOGGER_WARNING(log, "Allocation failed! Application might misbehave!"); |
74 | 0 | return nullptr; |
75 | 0 | } |
76 | | |
77 | 25 | if (create_recursive_mutex(ac->queue_mutex) != 0) { |
78 | 0 | LOGGER_WARNING(log, "Failed to create recursive mutex!"); |
79 | 0 | free(ac); |
80 | 0 | return nullptr; |
81 | 0 | } |
82 | | |
83 | 25 | int status; |
84 | 25 | ac->decoder = opus_decoder_create(AUDIO_DECODER_START_SAMPLE_RATE, AUDIO_DECODER_START_CHANNEL_COUNT, &status); |
85 | | |
86 | 25 | if (status != OPUS_OK) { |
87 | 0 | LOGGER_ERROR(log, "Error while starting audio decoder: %s", opus_strerror(status)); |
88 | 0 | goto BASE_CLEANUP; |
89 | 0 | } |
90 | | |
91 | 25 | ac->j_buf = jbuf_new(AUDIO_JITTERBUFFER_COUNT); |
92 | | |
93 | 25 | if (ac->j_buf == nullptr) { |
94 | 0 | LOGGER_WARNING(log, "Jitter buffer creaton failed!"); |
95 | 0 | opus_decoder_destroy(ac->decoder); |
96 | 0 | goto BASE_CLEANUP; |
97 | 0 | } |
98 | | |
99 | 25 | ac->mono_time = mono_time; |
100 | 25 | ac->log = log; |
101 | | |
102 | 25 | ac->decode_buffer = (int16_t *)malloc(AUDIO_MAX_BUFFER_SIZE_PCM16 * AUDIO_MAX_CHANNEL_COUNT * sizeof(int16_t)); |
103 | | |
104 | 25 | if (ac->decode_buffer == nullptr) { |
105 | 0 | LOGGER_ERROR(log, "Failed to allocate memory for audio buffer"); |
106 | 0 | goto DECODER_CLEANUP; |
107 | 0 | } |
108 | | |
109 | | /* Initialize encoders with default values */ |
110 | 25 | ac->encoder = create_audio_encoder(log, AUDIO_START_BITRATE, AUDIO_START_SAMPLE_RATE, AUDIO_START_CHANNEL_COUNT); |
111 | | |
112 | 25 | if (ac->encoder == nullptr) { |
113 | 0 | goto DECODER_CLEANUP; |
114 | 0 | } |
115 | | |
116 | 25 | ac->le_bit_rate = AUDIO_START_BITRATE; |
117 | 25 | ac->le_sample_rate = AUDIO_START_SAMPLE_RATE; |
118 | 25 | ac->le_channel_count = AUDIO_START_CHANNEL_COUNT; |
119 | | |
120 | 25 | ac->ld_channel_count = AUDIO_DECODER_START_CHANNEL_COUNT; |
121 | 25 | ac->ld_sample_rate = AUDIO_DECODER_START_SAMPLE_RATE; |
122 | 25 | ac->ldrts = 0; /* Make it possible to reconfigure straight away */ |
123 | | |
124 | | /* These need to be set in order to properly |
125 | | * do error correction with opus */ |
126 | 25 | ac->lp_frame_duration = AUDIO_MAX_FRAME_DURATION_MS; |
127 | 25 | ac->lp_sampling_rate = AUDIO_DECODER_START_SAMPLE_RATE; |
128 | 25 | ac->lp_channel_count = AUDIO_DECODER_START_CHANNEL_COUNT; |
129 | | |
130 | 25 | ac->friend_number = friend_number; |
131 | 25 | ac->acb = cb; |
132 | 25 | ac->user_data = user_data; |
133 | | |
134 | 25 | return ac; |
135 | | |
136 | 0 | DECODER_CLEANUP: |
137 | 0 | free(ac->decode_buffer); |
138 | 0 | opus_decoder_destroy(ac->decoder); |
139 | 0 | jbuf_free((struct JitterBuffer *)ac->j_buf); |
140 | 0 | BASE_CLEANUP: |
141 | 0 | pthread_mutex_destroy(ac->queue_mutex); |
142 | 0 | free(ac); |
143 | 0 | return nullptr; |
144 | 0 | } |
145 | | |
146 | | void ac_kill(ACSession *ac) |
147 | 25 | { |
148 | 25 | if (ac == nullptr) { |
149 | 0 | return; |
150 | 0 | } |
151 | | |
152 | 25 | opus_encoder_destroy(ac->encoder); |
153 | 25 | opus_decoder_destroy(ac->decoder); |
154 | 25 | jbuf_free((struct JitterBuffer *)ac->j_buf); |
155 | 25 | free(ac->decode_buffer); |
156 | | |
157 | 25 | pthread_mutex_destroy(ac->queue_mutex); |
158 | | |
159 | 25 | LOGGER_DEBUG(ac->log, "Terminated audio handler: %p", (void *)ac); |
160 | 25 | free(ac); |
161 | 25 | } |
162 | | |
163 | | void ac_iterate(ACSession *ac) |
164 | 65.7k | { |
165 | 65.7k | if (ac == nullptr) { |
166 | 0 | return; |
167 | 0 | } |
168 | | |
169 | | /* TODO: fix this and jitter buffering */ |
170 | | |
171 | 65.7k | int rc = 0; |
172 | | |
173 | 65.7k | pthread_mutex_lock(ac->queue_mutex); |
174 | | |
175 | 131k | while (true) { |
176 | 131k | struct JitterBuffer *const j_buf = (struct JitterBuffer *)ac->j_buf; |
177 | 131k | struct RTPMessage *msg = jbuf_read(j_buf, &rc); |
178 | | |
179 | 131k | if (msg == nullptr && rc != 2) { |
180 | 65.7k | break; |
181 | 65.7k | } |
182 | | |
183 | 65.7k | pthread_mutex_unlock(ac->queue_mutex); |
184 | | |
185 | 65.7k | if (rc == 2) { |
186 | | /* Packet Loss Concealment (PLC) */ |
187 | 7 | LOGGER_DEBUG(ac->log, "OPUS correction"); |
188 | | |
189 | | /* Use safe defaults or last known good values */ |
190 | 7 | const uint32_t sampling_rate = ac->lp_sampling_rate; |
191 | 7 | const uint32_t frame_duration = ac->lp_frame_duration; |
192 | | |
193 | 7 | if (sampling_rate == 0 || sampling_rate > AUDIO_MAX_SAMPLE_RATE || frame_duration > AUDIO_MAX_FRAME_DURATION_MS) { |
194 | 0 | LOGGER_WARNING(ac->log, "Invalid PLC parameters: sr %u, dur %u", sampling_rate, frame_duration); |
195 | 7 | } else { |
196 | 7 | const int fs = (sampling_rate * frame_duration) / 1000; |
197 | 7 | rc = opus_decode(ac->decoder, nullptr, 0, ac->decode_buffer, fs, 1); |
198 | 7 | } |
199 | 65.6k | } else { |
200 | 65.6k | const uint8_t *msg_data = rtp_message_data(msg); |
201 | 65.6k | const uint32_t msg_length = rtp_message_len(msg); |
202 | | |
203 | 65.6k | if (msg_length <= 4) { |
204 | 1 | LOGGER_WARNING(ac->log, "Packet too short: %u", msg_length); |
205 | 1 | free(msg); |
206 | 1 | pthread_mutex_lock(ac->queue_mutex); |
207 | 1 | continue; |
208 | 1 | } |
209 | | |
210 | | /* Pick up sampling rate from packet */ |
211 | 65.6k | uint32_t sampling_rate; |
212 | 65.6k | memcpy(&sampling_rate, msg_data, 4); |
213 | 65.6k | sampling_rate = net_ntohl(sampling_rate); |
214 | | |
215 | 65.6k | const int channels = opus_packet_get_nb_channels(msg_data + 4); |
216 | | |
217 | 65.6k | if (channels < 1 || channels > AUDIO_MAX_CHANNEL_COUNT || |
218 | 65.6k | sampling_rate == 0 || sampling_rate > AUDIO_MAX_SAMPLE_RATE) { |
219 | 1 | LOGGER_WARNING(ac->log, "Invalid packet parameters: sr %u, cc %d", sampling_rate, channels); |
220 | 1 | free(msg); |
221 | 1 | pthread_mutex_lock(ac->queue_mutex); |
222 | 1 | continue; |
223 | 1 | } |
224 | | |
225 | | /** NOTE: even though OPUS supports decoding mono frames with stereo decoder and vice versa, |
226 | | * it didn't work quite well. |
227 | | */ |
228 | 65.6k | if (!reconfigure_audio_decoder(ac, sampling_rate, (uint8_t)channels)) { |
229 | 1 | LOGGER_WARNING(ac->log, "Failed to reconfigure decoder!"); |
230 | 1 | free(msg); |
231 | 1 | pthread_mutex_lock(ac->queue_mutex); |
232 | 1 | continue; |
233 | 1 | } |
234 | | |
235 | 65.6k | ac->lp_sampling_rate = sampling_rate; |
236 | 65.6k | ac->lp_channel_count = (uint8_t)channels; |
237 | | |
238 | | /* |
239 | | * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0); |
240 | | * where |
241 | | * packet is the byte array containing the compressed data |
242 | | * len is the exact number of bytes contained in the packet |
243 | | * decoded is the decoded audio data in opus_int16 (or float for opus_decode_float()) |
244 | | * max_size is the max duration of the frame in samples (per channel) that can fit |
245 | | * into the decoded_frame array |
246 | | */ |
247 | 65.6k | rc = opus_decode(ac->decoder, msg_data + 4, msg_length - 4, ac->decode_buffer, AUDIO_MAX_BUFFER_SIZE_PCM16, 0); |
248 | 65.6k | free(msg); |
249 | 65.6k | } |
250 | | |
251 | 65.6k | if (rc < 0) { |
252 | 0 | LOGGER_WARNING(ac->log, "Decoding error: %s", opus_strerror(rc)); |
253 | 65.6k | } else if (ac->acb != nullptr && ac->lp_sampling_rate != 0) { |
254 | 65.6k | ac->lp_frame_duration = (rc * 1000) / ac->lp_sampling_rate; |
255 | | |
256 | 65.6k | ac->acb(ac->friend_number, ac->decode_buffer, (size_t)rc, ac->lp_channel_count, |
257 | 65.6k | ac->lp_sampling_rate, ac->user_data); |
258 | 65.6k | } |
259 | | |
260 | 65.6k | pthread_mutex_lock(ac->queue_mutex); |
261 | 65.6k | } |
262 | | |
263 | 65.7k | pthread_mutex_unlock(ac->queue_mutex); |
264 | 65.7k | } |
265 | | |
266 | | int ac_queue_message(const Mono_Time *mono_time, void *cs, struct RTPMessage *msg) |
267 | 65.7k | { |
268 | 65.7k | ACSession *ac = (ACSession *)cs; |
269 | | |
270 | 65.7k | if (ac == nullptr || msg == nullptr) { |
271 | 0 | free(msg); |
272 | 0 | return -1; |
273 | 0 | } |
274 | | |
275 | 65.7k | if ((rtp_message_pt(msg) & 0x7f) == (RTP_TYPE_AUDIO + 2) % 128) { |
276 | 0 | LOGGER_WARNING(ac->log, "Got dummy!"); |
277 | 0 | free(msg); |
278 | 0 | return 0; |
279 | 0 | } |
280 | | |
281 | 65.7k | if ((rtp_message_pt(msg) & 0x7f) != RTP_TYPE_AUDIO % 128) { |
282 | 0 | LOGGER_WARNING(ac->log, "Invalid payload type!"); |
283 | 0 | free(msg); |
284 | 0 | return -1; |
285 | 0 | } |
286 | | |
287 | 65.7k | pthread_mutex_lock(ac->queue_mutex); |
288 | 65.7k | const int rc = jbuf_write(ac->log, (struct JitterBuffer *)ac->j_buf, msg); |
289 | 65.7k | pthread_mutex_unlock(ac->queue_mutex); |
290 | | |
291 | 65.7k | if (rc == -1) { |
292 | 2 | LOGGER_WARNING(ac->log, "Could not queue the message!"); |
293 | 2 | free(msg); |
294 | 2 | return -1; |
295 | 2 | } |
296 | | |
297 | 65.6k | return 0; |
298 | 65.7k | } |
299 | | |
300 | | int ac_reconfigure_encoder(ACSession *ac, uint32_t bit_rate, uint32_t sampling_rate, uint8_t channels) |
301 | 52 | { |
302 | 52 | if (ac == nullptr || !reconfigure_audio_encoder( |
303 | 52 | ac->log, &ac->encoder, bit_rate, |
304 | 52 | sampling_rate, channels, |
305 | 52 | &ac->le_bit_rate, |
306 | 52 | &ac->le_sample_rate, |
307 | 52 | &ac->le_channel_count)) { |
308 | 0 | return -1; |
309 | 0 | } |
310 | | |
311 | 52 | return 0; |
312 | 52 | } |
313 | | |
314 | | uint32_t ac_get_lp_frame_duration(const ACSession *ac) |
315 | 129 | { |
316 | 129 | return ac->lp_frame_duration; |
317 | 129 | } |
318 | | |
319 | | int ac_encode(ACSession *ac, const int16_t *pcm, size_t sample_count, uint8_t *dest, size_t dest_max) |
320 | 150 | { |
321 | 150 | const int vrc = opus_encode(ac->encoder, pcm, (int)sample_count, dest, (int)dest_max); |
322 | | |
323 | 150 | if (vrc < 0) { |
324 | 0 | LOGGER_WARNING(ac->log, "Failed to encode frame %s", opus_strerror(vrc)); |
325 | 0 | } |
326 | | |
327 | 150 | return vrc; |
328 | 150 | } |
329 | | |
330 | | struct JitterBuffer { |
331 | | struct RTPMessage *_Nullable *_Nonnull queue; |
332 | | uint32_t size; |
333 | | uint32_t capacity; |
334 | | uint16_t bottom; |
335 | | uint16_t top; |
336 | | }; |
337 | | |
338 | | static struct JitterBuffer *jbuf_new(uint32_t capacity) |
339 | 25 | { |
340 | 25 | unsigned int size = 1; |
341 | | |
342 | 125 | while (size <= (capacity * 4)) { |
343 | 100 | size *= 2; |
344 | 100 | } |
345 | | |
346 | 25 | struct JitterBuffer *q = (struct JitterBuffer *)calloc(1, sizeof(struct JitterBuffer)); |
347 | | |
348 | 25 | if (q == nullptr) { |
349 | 0 | return nullptr; |
350 | 0 | } |
351 | | |
352 | 25 | q->queue = (struct RTPMessage **)calloc(size, sizeof(struct RTPMessage *)); |
353 | | |
354 | 25 | if (q->queue == nullptr) { |
355 | 0 | free(q); |
356 | 0 | return nullptr; |
357 | 0 | } |
358 | | |
359 | 25 | q->size = size; |
360 | 25 | q->capacity = capacity; |
361 | 25 | return q; |
362 | 25 | } |
363 | | |
364 | | static void jbuf_clear(struct JitterBuffer *q) |
365 | 26 | { |
366 | 38 | while (q->bottom != q->top) { |
367 | 12 | free(q->queue[q->bottom % q->size]); |
368 | 12 | q->queue[q->bottom % q->size] = nullptr; |
369 | 12 | ++q->bottom; |
370 | 12 | } |
371 | 26 | } |
372 | | |
373 | | static void jbuf_free(struct JitterBuffer *q) |
374 | 25 | { |
375 | 25 | if (q == nullptr) { |
376 | 0 | return; |
377 | 0 | } |
378 | | |
379 | 25 | jbuf_clear(q); |
380 | 25 | free(q->queue); |
381 | 25 | free(q); |
382 | 25 | } |
383 | | |
384 | | /* |
385 | | * if -1 is returned the RTPMessage m needs to be free'd by the caller |
386 | | * if 0 is returned the RTPMessage m is stored in the ringbuffer and must NOT be freed by the caller |
387 | | */ |
388 | | static int jbuf_write(const Logger *log, struct JitterBuffer *q, struct RTPMessage *m) |
389 | 65.7k | { |
390 | 65.7k | const uint16_t sequnum = rtp_message_sequnum(m); |
391 | | |
392 | 65.7k | const unsigned int num = sequnum % q->size; |
393 | | |
394 | 65.7k | const int16_t diff = (int16_t)(sequnum - q->bottom); |
395 | | |
396 | 65.7k | if (diff < 0) { |
397 | 1 | return -1; |
398 | 1 | } |
399 | | |
400 | 65.7k | if (diff > (int32_t)q->size) { |
401 | 1 | LOGGER_DEBUG(log, "Clearing filled jitter buffer: %p", (void *)q); |
402 | | |
403 | 1 | jbuf_clear(q); |
404 | 1 | q->bottom = sequnum - q->capacity; |
405 | 1 | q->queue[num] = m; |
406 | 1 | q->top = sequnum + 1; |
407 | 1 | return 0; |
408 | 1 | } |
409 | | |
410 | 65.6k | if (q->queue[num] != nullptr) { |
411 | 1 | return -1; |
412 | 1 | } |
413 | | |
414 | 65.6k | q->queue[num] = m; |
415 | | |
416 | 65.6k | if ((sequnum - q->bottom) >= (q->top - q->bottom)) { |
417 | 65.6k | q->top = sequnum + 1; |
418 | 65.6k | } |
419 | | |
420 | 65.6k | return 0; |
421 | 65.6k | } |
422 | | |
423 | | static struct RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success) |
424 | 131k | { |
425 | 131k | if (q->top == q->bottom) { |
426 | 65.7k | *success = 0; |
427 | 65.7k | return nullptr; |
428 | 65.7k | } |
429 | | |
430 | 65.7k | const unsigned int num = q->bottom % q->size; |
431 | | |
432 | 65.7k | if (q->queue[num] != nullptr) { |
433 | 65.6k | struct RTPMessage *ret = q->queue[num]; |
434 | 65.6k | q->queue[num] = nullptr; |
435 | 65.6k | ++q->bottom; |
436 | 65.6k | *success = 1; |
437 | 65.6k | return ret; |
438 | 65.6k | } |
439 | | |
440 | 11 | if ((uint16_t)(q->top - q->bottom) > q->capacity) { |
441 | 7 | ++q->bottom; |
442 | 7 | *success = 2; |
443 | 7 | return nullptr; |
444 | 7 | } |
445 | | |
446 | 4 | *success = 0; |
447 | 4 | return nullptr; |
448 | 11 | } |
449 | | static OpusEncoder *create_audio_encoder(const Logger *log, uint32_t bit_rate, uint32_t sampling_rate, |
450 | | uint8_t channel_count) |
451 | 32 | { |
452 | 32 | int status = OPUS_OK; |
453 | | /* |
454 | | * OPUS_APPLICATION_VOIP Process signal for improved speech intelligibility |
455 | | * OPUS_APPLICATION_AUDIO Favor faithfulness to the original input |
456 | | * OPUS_APPLICATION_RESTRICTED_LOWDELAY Configure the minimum possible coding delay |
457 | | */ |
458 | 32 | OpusEncoder *rc = opus_encoder_create(sampling_rate, channel_count, OPUS_APPLICATION_VOIP, &status); |
459 | | |
460 | 32 | if (status != OPUS_OK) { |
461 | 0 | LOGGER_ERROR(log, "Error while starting audio encoder: %s", opus_strerror(status)); |
462 | 0 | return nullptr; |
463 | 0 | } |
464 | | |
465 | | /* |
466 | | * Rates from 500 to 512000 bits per second are meaningful as well as the special |
467 | | * values OPUS_BITRATE_AUTO and OPUS_BITRATE_MAX. The value OPUS_BITRATE_MAX can |
468 | | * be used to cause the codec to use as much rate as it can, which is useful for |
469 | | * controlling the rate by adjusting the output buffer size. |
470 | | * |
471 | | * Parameters: |
472 | | * `[in]` `x` `opus_int32`: bitrate in bits per second. |
473 | | */ |
474 | 32 | status = opus_encoder_ctl(rc, OPUS_SET_BITRATE(bit_rate)); |
475 | | |
476 | 32 | if (status != OPUS_OK) { |
477 | 0 | LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); |
478 | 0 | goto FAILURE; |
479 | 0 | } |
480 | | |
481 | | /* |
482 | | * The libopus library defaults to VBR, which is unsafe in any VoIP environment |
483 | | * (see for example doi:10.1109/SP.2011.34). Switching to CBR very slightly |
484 | | * decreases audio quality at lower bitrates. |
485 | | * |
486 | | * Parameters: |
487 | | * `[in]` `x` `opus_int32`: Whether to use VBR mode, 1 (VBR) is default |
488 | | */ |
489 | 32 | status = opus_encoder_ctl(rc, OPUS_SET_VBR(0)); |
490 | | |
491 | 32 | if (status != OPUS_OK) { |
492 | 0 | LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); |
493 | 0 | goto FAILURE; |
494 | 0 | } |
495 | | |
496 | | /* |
497 | | * Configures the encoder's use of inband forward error correction. |
498 | | * Note: |
499 | | * This is only applicable to the LPC layer |
500 | | * Parameters: |
501 | | * `[in]` `x` `int`: FEC flag, 0 (disabled) is default |
502 | | */ |
503 | | /* Enable in-band forward error correction in codec */ |
504 | 32 | status = opus_encoder_ctl(rc, OPUS_SET_INBAND_FEC(1)); |
505 | | |
506 | 32 | if (status != OPUS_OK) { |
507 | 0 | LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); |
508 | 0 | goto FAILURE; |
509 | 0 | } |
510 | | |
511 | | /* |
512 | | * Configures the encoder's expected packet loss percentage. |
513 | | * Higher values with trigger progressively more loss resistant behavior in |
514 | | * the encoder at the expense of quality at a given bitrate in the lossless case, |
515 | | * but greater quality under loss. |
516 | | * Parameters: |
517 | | * `[in]` `x` `int`: Loss percentage in the range 0-100, inclusive. |
518 | | */ |
519 | | /* Make codec resistant to up to 10% packet loss |
520 | | * NOTE This could also be adjusted on the fly, rather than hard-coded, |
521 | | * with feedback from the receiving client. |
522 | | */ |
523 | 32 | status = opus_encoder_ctl(rc, OPUS_SET_PACKET_LOSS_PERC(AUDIO_OPUS_PACKET_LOSS_PERC)); |
524 | | |
525 | 32 | if (status != OPUS_OK) { |
526 | 0 | LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); |
527 | 0 | goto FAILURE; |
528 | 0 | } |
529 | | |
530 | | /* |
531 | | * Configures the encoder's computational complexity. |
532 | | * |
533 | | * The supported range is 0-10 inclusive with 10 representing the highest complexity. |
534 | | * The default value is 10. |
535 | | * |
536 | | * Parameters: |
537 | | * `[in]` `x` `int`: 0-10, inclusive |
538 | | */ |
539 | | /* Set algorithm to the highest complexity, maximizing compression */ |
540 | 32 | status = opus_encoder_ctl(rc, OPUS_SET_COMPLEXITY(AUDIO_OPUS_COMPLEXITY)); |
541 | | |
542 | 32 | if (status != OPUS_OK) { |
543 | 0 | LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); |
544 | 0 | goto FAILURE; |
545 | 0 | } |
546 | | |
547 | 32 | return rc; |
548 | | |
549 | 0 | FAILURE: |
550 | 0 | opus_encoder_destroy(rc); |
551 | 0 | return nullptr; |
552 | 32 | } |
553 | | |
554 | | static bool reconfigure_audio_encoder(const Logger *log, OpusEncoder **e, uint32_t new_br, uint32_t new_sr, |
555 | | uint8_t new_ch, uint32_t *old_br, uint32_t *old_sr, uint8_t *old_ch) |
556 | 52 | { |
557 | | /* Values are checked in toxav.c */ |
558 | 52 | if (*old_sr != new_sr || *old_ch != new_ch) { |
559 | 7 | OpusEncoder *new_encoder = create_audio_encoder(log, new_br, new_sr, new_ch); |
560 | | |
561 | 7 | if (new_encoder == nullptr) { |
562 | 0 | return false; |
563 | 0 | } |
564 | | |
565 | 7 | opus_encoder_destroy(*e); |
566 | 7 | *e = new_encoder; |
567 | 45 | } else if (*old_br == new_br) { |
568 | 45 | return true; /* Nothing changed */ |
569 | 45 | } |
570 | | |
571 | 7 | const int status = opus_encoder_ctl(*e, OPUS_SET_BITRATE(new_br)); |
572 | | |
573 | 7 | if (status != OPUS_OK) { |
574 | 0 | LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); |
575 | 0 | return false; |
576 | 0 | } |
577 | | |
578 | 7 | *old_br = new_br; |
579 | 7 | *old_sr = new_sr; |
580 | 7 | *old_ch = new_ch; |
581 | | |
582 | 7 | LOGGER_DEBUG(log, "Reconfigured audio encoder br: %u sr: %u cc:%d", new_br, new_sr, new_ch); |
583 | 7 | return true; |
584 | 7 | } |
585 | | |
586 | | static bool reconfigure_audio_decoder(ACSession *ac, uint32_t sampling_rate, uint8_t channels) |
587 | 65.6k | { |
588 | 65.6k | if (sampling_rate != ac->ld_sample_rate || channels != ac->ld_channel_count) { |
589 | 4 | if (current_time_monotonic(ac->mono_time) - ac->ldrts < 500) { |
590 | 1 | return false; |
591 | 1 | } |
592 | | |
593 | 3 | int status; |
594 | 3 | OpusDecoder *new_dec = opus_decoder_create(sampling_rate, channels, &status); |
595 | | |
596 | 3 | if (status != OPUS_OK) { |
597 | 0 | LOGGER_ERROR(ac->log, "Error while starting audio decoder(%u %u): %s", sampling_rate, channels, opus_strerror(status)); |
598 | 0 | return false; |
599 | 0 | } |
600 | | |
601 | 3 | ac->ld_sample_rate = sampling_rate; |
602 | 3 | ac->ld_channel_count = channels; |
603 | 3 | ac->ldrts = current_time_monotonic(ac->mono_time); |
604 | | |
605 | 3 | opus_decoder_destroy(ac->decoder); |
606 | 3 | ac->decoder = new_dec; |
607 | | |
608 | 3 | LOGGER_DEBUG(ac->log, "Reconfigured audio decoder sr: %u cc: %u", sampling_rate, channels); |
609 | 3 | } |
610 | | |
611 | 65.6k | return true; |
612 | 65.6k | } |