blob: 3369f8e9cd359362890d5ad2878d3b442a0dee33 [file] [log] [blame]
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/codecs/opus/opus_interface.h"
kwiberg2e486462016-08-23 05:54:25 -070012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/checks.h"
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000014
15#include <stdlib.h>
16#include <string.h>
17
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000018enum {
minyue2e03c662017-02-01 17:31:11 -080019#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
20 /* Maximum supported frame size in WebRTC is 120 ms. */
21 kWebRtcOpusMaxEncodeFrameSizeMs = 120,
22#else
tina.legrand@webrtc.org46d90dc2013-02-01 14:20:06 +000023 /* Maximum supported frame size in WebRTC is 60 ms. */
24 kWebRtcOpusMaxEncodeFrameSizeMs = 60,
minyue2e03c662017-02-01 17:31:11 -080025#endif
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000026
tina.legrand@webrtc.org45426ea2013-07-03 13:32:04 +000027 /* The format allows up to 120 ms frames. Since we don't control the other
28 * side, we must allow for packets of that size. NetEq is currently limited
29 * to 60 ms on the receive side. */
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000030 kWebRtcOpusMaxDecodeFrameSizeMs = 120,
31
tina.legrand@webrtc.org45426ea2013-07-03 13:32:04 +000032 /* Maximum sample count per channel is 48 kHz * maximum frame size in
33 * milliseconds. */
34 kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs,
35
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +000036 /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */
37 kWebRtcOpusDefaultFrameSize = 960,
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000038};
39
Alex Loiko7a3e43a2019-01-29 12:27:08 +010040int16_t GetSurroundParameters(int channels,
41 int *streams,
42 int *coupled_streams,
43 unsigned char *mapping) {
44 int opus_error;
45 int ret = 0;
46 // Use 'surround encoder create' to get values for 'coupled_streams',
47 // 'streams' and 'mapping'.
48 OpusMSEncoder* ms_encoder_ptr = opus_multistream_surround_encoder_create(
49 48000,
50 channels,
51 /* mapping family */ channels <= 2 ? 0 : 1,
52 streams,
53 coupled_streams,
54 mapping,
55 OPUS_APPLICATION_VOIP, // Application type shouldn't affect
56 // streams/mapping values.
57 &opus_error);
58
59 // This shouldn't fail; if it fails,
60 // signal an error and return invalid values.
61 if (opus_error != OPUS_OK || ms_encoder_ptr == NULL) {
62 ret = -1;
63 *streams = -1;
64 *coupled_streams = -1;
65 }
66
67 // We don't need the encoder.
68 if (ms_encoder_ptr != NULL) {
69 opus_multistream_encoder_destroy(ms_encoder_ptr);
70 }
71 return ret;
72}
73
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000074int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
Peter Kasting69558702016-01-12 16:26:35 -080075 size_t channels,
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000076 int32_t application) {
minyue3cea2562015-11-10 03:49:26 -080077 int opus_app;
78 if (!inst)
79 return -1;
tina.legrand@webrtc.orgd0d41492012-12-20 09:23:10 +000080
minyue3cea2562015-11-10 03:49:26 -080081 switch (application) {
82 case 0:
83 opus_app = OPUS_APPLICATION_VOIP;
84 break;
85 case 1:
86 opus_app = OPUS_APPLICATION_AUDIO;
87 break;
88 default:
89 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000090 }
minyue3cea2562015-11-10 03:49:26 -080091
Alex Loiko7a3e43a2019-01-29 12:27:08 +010092 OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
kwiberg2e486462016-08-23 05:54:25 -070093 RTC_DCHECK(state);
minyue3cea2562015-11-10 03:49:26 -080094
minyue3cea2562015-11-10 03:49:26 -080095 int error;
Alex Loiko7a3e43a2019-01-29 12:27:08 +010096 if (channels <= 2) {
97 state->encoder.encoder = opus_encoder_create(48000, (int)channels, opus_app,
98 &error);
99
100 } else {
101 unsigned char mapping[255];
102 memset(mapping, 0, 255);
103 int streams = -1;
104 int coupled_streams = -1;
105
106 state->encoder.multistream_encoder =
107 opus_multistream_surround_encoder_create(
108 48000,
109 channels,
110 /* mapping family */ 1,
111 &streams,
112 &coupled_streams,
113 mapping,
114 opus_app,
115 &error);
116 }
117
118 if (error != OPUS_OK || (!state->encoder.encoder &&
119 !state->encoder.multistream_encoder)) {
minyue3cea2562015-11-10 03:49:26 -0800120 WebRtcOpus_EncoderFree(state);
121 return -1;
122 }
123
124 state->in_dtx_mode = 0;
125 state->channels = channels;
126
127 *inst = state;
128 return 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000129}
130
131int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000132 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100133 if (inst->channels <= 2) {
134 opus_encoder_destroy(inst->encoder.encoder);
135 } else {
136 opus_multistream_encoder_destroy(inst->encoder.multistream_encoder);
137 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000138 free(inst);
139 return 0;
140 } else {
141 return -1;
142 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000143}
144
Peter Kastingbba78072015-06-11 19:02:46 -0700145int WebRtcOpus_Encode(OpusEncInst* inst,
146 const int16_t* audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700147 size_t samples,
148 size_t length_encoded_buffer,
Peter Kastingbba78072015-06-11 19:02:46 -0700149 uint8_t* encoded) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000150 int res;
151
152 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
153 return -1;
154 }
155
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100156 if (inst->channels <= 2) {
157 res = opus_encode(inst->encoder.encoder,
158 (const opus_int16*)audio_in,
159 (int)samples,
160 encoded,
161 (opus_int32)length_encoded_buffer);
162 } else {
163 res = opus_multistream_encode(inst->encoder.multistream_encoder,
164 (const opus_int16*)audio_in,
165 (int)samples,
166 encoded,
167 (opus_int32)length_encoded_buffer);
168 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000169
flim64a7eab2016-08-12 04:36:05 -0700170 if (res <= 0) {
171 return -1;
172 }
173
174 if (res <= 2) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000175 // Indicates DTX since the packet has nothing but a header. In principle,
176 // there is no need to send this packet. However, we do transmit the first
177 // occurrence to let the decoder know that the encoder enters DTX mode.
178 if (inst->in_dtx_mode) {
179 return 0;
180 } else {
181 inst->in_dtx_mode = 1;
flim92382452017-02-10 13:50:38 -0800182 return res;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000183 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000184 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000185
flim64a7eab2016-08-12 04:36:05 -0700186 inst->in_dtx_mode = 0;
187 return res;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000188}
189
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100190#define ENCODER_CTL(inst, vargs) ( \
191 inst->channels <= 2 ? \
192 opus_encoder_ctl(inst->encoder.encoder, vargs) \
193 : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs))
194
195
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000196int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000197 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100198 return ENCODER_CTL(inst, OPUS_SET_BITRATE(rate));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000199 } else {
200 return -1;
201 }
202}
203
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000204int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
205 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100206 return ENCODER_CTL(inst, OPUS_SET_PACKET_LOSS_PERC(loss_rate));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000207 } else {
208 return -1;
209 }
210}
211
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000212int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000213 opus_int32 set_bandwidth;
214
215 if (!inst)
216 return -1;
217
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000218 if (frequency_hz <= 8000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000219 set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000220 } else if (frequency_hz <= 12000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000221 set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000222 } else if (frequency_hz <= 16000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000223 set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000224 } else if (frequency_hz <= 24000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000225 set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
226 } else {
227 set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
228 }
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100229 return ENCODER_CTL(inst, OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
230}
231
232int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
233 int32_t* result_hz) {
234 if (inst->channels <= 2) {
235 if (opus_encoder_ctl(
236 inst->encoder.encoder,
237 OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
238 return 0;
239 }
240 return -1;
241 }
242
243 opus_int32 max_bandwidth;
244 int s;
245 int ret;
246
247 max_bandwidth = 0;
248 ret = OPUS_OK;
249 s = 0;
250 while (ret == OPUS_OK) {
251 OpusEncoder *enc;
252 opus_int32 bandwidth;
253
254 ret = ENCODER_CTL(inst, OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
255 if (ret == OPUS_BAD_ARG)
256 break;
257 if (ret != OPUS_OK)
258 return -1;
259 if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
260 return -1;
261
262 if (max_bandwidth != 0 && max_bandwidth != bandwidth)
263 return -1;
264
265 max_bandwidth = bandwidth;
266 s++;
267 }
268 *result_hz = max_bandwidth;
269 return 0;
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000270}
271
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000272int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
273 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100274 return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(1));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000275 } else {
276 return -1;
277 }
278}
279
280int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
281 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100282 return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(0));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000283 } else {
284 return -1;
285 }
286}
287
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000288int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200289 if (!inst) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000290 return -1;
291 }
Minyue Li092041c2015-05-11 12:19:35 +0200292
293 // To prevent Opus from entering CELT-only mode by forcing signal type to
294 // voice to make sure that DTX behaves correctly. Currently, DTX does not
295 // last long during a pure silence, if the signal type is not forced.
296 // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
297 // without it.
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100298 int ret = ENCODER_CTL(inst,
299 OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
Minyue Li092041c2015-05-11 12:19:35 +0200300 if (ret != OPUS_OK)
301 return ret;
302
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100303 return ENCODER_CTL(inst, OPUS_SET_DTX(1));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000304}
305
306int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
307 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100308 int ret = ENCODER_CTL(inst,
309 OPUS_SET_SIGNAL(OPUS_AUTO));
Minyue Li092041c2015-05-11 12:19:35 +0200310 if (ret != OPUS_OK)
311 return ret;
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100312 return ENCODER_CTL(inst, OPUS_SET_DTX(0));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000313 } else {
314 return -1;
315 }
316}
317
soren28dc2852017-04-06 05:48:36 -0700318int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
319 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100320 return ENCODER_CTL(inst, OPUS_SET_VBR(0));
soren28dc2852017-04-06 05:48:36 -0700321 } else {
322 return -1;
323 }
324}
325
326int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
327 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100328 return ENCODER_CTL(inst, OPUS_SET_VBR(1));
soren28dc2852017-04-06 05:48:36 -0700329 } else {
330 return -1;
331 }
332}
333
minyue@webrtc.org04546882014-03-07 08:55:48 +0000334int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
335 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100336 return ENCODER_CTL(inst,
337 OPUS_SET_COMPLEXITY(complexity));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000338 } else {
339 return -1;
340 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000341}
342
Alex Luebseeb27652017-11-20 11:13:56 -0800343int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst) {
344 if (!inst) {
345 return -1;
346 }
347 int32_t bandwidth;
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100348 if (ENCODER_CTL(inst,
349 OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
Alex Luebseeb27652017-11-20 11:13:56 -0800350 return bandwidth;
351 } else {
352 return -1;
353 }
354
355}
356
357int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
358 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100359 return ENCODER_CTL(inst,
360 OPUS_SET_BANDWIDTH(bandwidth));
Alex Luebseeb27652017-11-20 11:13:56 -0800361 } else {
362 return -1;
363 }
364}
365
minyue41b9c802016-10-06 07:13:54 -0700366int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
minyuec8299f92016-09-27 02:08:47 -0700367 if (!inst)
368 return -1;
369 if (num_channels == 0) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100370 return ENCODER_CTL(inst,
minyuec8299f92016-09-27 02:08:47 -0700371 OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
372 } else if (num_channels == 1 || num_channels == 2) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100373 return ENCODER_CTL(inst,
374 OPUS_SET_FORCE_CHANNELS(num_channels));
minyuec8299f92016-09-27 02:08:47 -0700375 } else {
376 return -1;
377 }
378}
379
Peter Kasting69558702016-01-12 16:26:35 -0800380int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000381 int error;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000382 OpusDecInst* state;
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000383
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000384 if (inst != NULL) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100385 // Create Opus decoder state.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000386 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
387 if (state == NULL) {
388 return -1;
389 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000390
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100391 if (channels <= 2) {
392 state->decoder.decoder = opus_decoder_create(48000,
393 (int)channels, &error);
394 } else {
395 unsigned char mapping[255];
396 memset(mapping, 0, 255);
397 int streams = -1;
398 int coupled_streams = -1;
399 if (GetSurroundParameters(channels, &streams,
400 &coupled_streams, mapping) != 0) {
401 free(state);
402 return -1;
403 }
404
405 // Create new memory, always at 48000 Hz.
406 state->decoder.multistream_decoder = opus_multistream_decoder_create(
407 48000, (int)channels,
408 /* streams = */ streams,
409 /* coupled streams = */ coupled_streams,
410 mapping,
411 &error);
412 }
413 if (error == OPUS_OK && (state->decoder.decoder ||
414 state->decoder.multistream_decoder)) {
415 // Creation of memory all ok.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000416 state->channels = channels;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000417 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000418 state->in_dtx_mode = 0;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000419 *inst = state;
420 return 0;
421 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000422
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100423 // If memory allocation was unsuccessful, free the entire state.
424 if (state->decoder.decoder) {
425 opus_decoder_destroy(state->decoder.decoder);
426
427 } else if (state->decoder.multistream_decoder) {
428 opus_multistream_decoder_destroy(state->decoder.multistream_decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000429 }
430 free(state);
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000431 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000432 return -1;
433}
434
435int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000436 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100437 if (inst->channels <= 2) {
438 opus_decoder_destroy(inst->decoder.decoder);
439 } else if (inst->channels > 2) {
440 opus_multistream_decoder_destroy(inst->decoder.multistream_decoder);
441 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000442 free(inst);
443 return 0;
444 } else {
445 return -1;
446 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000447}
448
Peter Kasting69558702016-01-12 16:26:35 -0800449size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000450 return inst->channels;
451}
452
Karl Wiberg43766482015-08-27 15:22:11 +0200453void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100454 if (inst->channels <= 2) {
455 opus_decoder_ctl(inst->decoder.decoder, OPUS_RESET_STATE);
456 } else {
457 opus_multistream_decoder_ctl(inst->decoder.multistream_decoder,
458 OPUS_RESET_STATE);
459 }
Karl Wiberg43766482015-08-27 15:22:11 +0200460 inst->in_dtx_mode = 0;
tina.legrand@webrtc.org0ad3c1a2012-11-07 08:07:29 +0000461}
462
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000463/* For decoder to determine if it is to output speech or comfort noise. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700464static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000465 // Audio type becomes comfort noise if |encoded_byte| is 1 and keeps
466 // to be so if the following |encoded_byte| are 0 or 1.
467 if (encoded_bytes == 0 && inst->in_dtx_mode) {
468 return 2; // Comfort noise.
henrik.lundindeaf6fb2017-03-01 00:49:18 -0800469 } else if (encoded_bytes == 1 || encoded_bytes == 2) {
470 // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
471 // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
472 // interpreted as comfort noise output, but such a payload is probably
473 // faulty anyway.
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100474
475 // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
476 // single-stream packets glued together with some packet size bytes in
477 // between. See https://tools.ietf.org/html/rfc6716#appendix-B
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000478 inst->in_dtx_mode = 1;
479 return 2; // Comfort noise.
480 } else {
481 inst->in_dtx_mode = 0;
482 return 0; // Speech.
483 }
484}
485
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000486/* |frame_size| is set to maximum Opus frame size in the normal case, and
487 * is set to the number of samples needed for PLC in case of losses.
488 * It is up to the caller to make sure the value is correct. */
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000489static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700490 size_t encoded_bytes, int frame_size,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000491 int16_t* decoded, int16_t* audio_type, int decode_fec) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100492 int res = -1;
493 if (inst->channels <= 2) {
494 res = opus_decode(inst->decoder.decoder, encoded, (opus_int32)encoded_bytes,
495 (opus_int16*)decoded, frame_size, decode_fec);
496 } else {
497 res = opus_multistream_decode(
498 inst->decoder.multistream_decoder, encoded, (opus_int32)encoded_bytes,
499 (opus_int16*)decoded, frame_size, decode_fec);
500 }
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000501
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000502 if (res <= 0)
503 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000504
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000505 *audio_type = DetermineAudioType(inst, encoded_bytes);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000506
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000507 return res;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000508}
509
Peter Kastingbba78072015-06-11 19:02:46 -0700510int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700511 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700512 int16_t* audio_type) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000513 int decoded_samples;
514
515 if (encoded_bytes == 0) {
516 *audio_type = DetermineAudioType(inst, encoded_bytes);
517 decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
518 } else {
519 decoded_samples = DecodeNative(inst,
520 encoded,
521 encoded_bytes,
522 kWebRtcOpusMaxFrameSizePerChannel,
523 decoded,
524 audio_type,
525 0);
526 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000527 if (decoded_samples < 0) {
528 return -1;
529 }
530
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000531 /* Update decoded sample memory, to be used by the PLC in case of losses. */
532 inst->prev_decoded_samples = decoded_samples;
533
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000534 return decoded_samples;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000535}
536
Peter Kastingbba78072015-06-11 19:02:46 -0700537int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
538 int number_of_lost_frames) {
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000539 int16_t audio_type = 0;
540 int decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000541 int plc_samples;
542
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000543 /* The number of samples we ask for is |number_of_lost_frames| times
544 * |prev_decoded_samples_|. Limit the number of samples to maximum
545 * |kWebRtcOpusMaxFrameSizePerChannel|. */
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000546 plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
547 plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
548 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000549 decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
550 decoded, &audio_type, 0);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000551 if (decoded_samples < 0) {
552 return -1;
553 }
554
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000555 return decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000556}
557
Peter Kastingbba78072015-06-11 19:02:46 -0700558int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700559 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700560 int16_t* audio_type) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000561 int decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000562 int fec_samples;
563
564 if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
565 return 0;
566 }
567
568 fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
569
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000570 decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
571 fec_samples, decoded, audio_type, 1);
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000572 if (decoded_samples < 0) {
573 return -1;
574 }
575
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000576 return decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000577}
578
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000579int WebRtcOpus_DurationEst(OpusDecInst* inst,
580 const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700581 size_t payload_length_bytes) {
minyuel6d92bf52015-09-23 15:20:39 +0200582 if (payload_length_bytes == 0) {
583 // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
584 // PLC duration correspondingly.
585 return WebRtcOpus_PlcDuration(inst);
586 }
587
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000588 int frames, samples;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700589 frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000590 if (frames < 0) {
591 /* Invalid payload data. */
592 return 0;
593 }
594 samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
595 if (samples < 120 || samples > 5760) {
596 /* Invalid payload duration. */
597 return 0;
598 }
599 return samples;
600}
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000601
minyuel6d92bf52015-09-23 15:20:39 +0200602int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
603 /* The number of samples we ask for is |number_of_lost_frames| times
604 * |prev_decoded_samples_|. Limit the number of samples to maximum
605 * |kWebRtcOpusMaxFrameSizePerChannel|. */
606 const int plc_samples = inst->prev_decoded_samples;
607 return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
608 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
609}
610
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000611int WebRtcOpus_FecDurationEst(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700612 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000613 int samples;
614 if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
615 return 0;
616 }
617
618 samples = opus_packet_get_samples_per_frame(payload, 48000);
619 if (samples < 480 || samples > 5760) {
620 /* Invalid payload duration. */
621 return 0;
622 }
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000623 return samples;
624}
625
626int WebRtcOpus_PacketHasFec(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700627 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000628 int frames, channels, payload_length_ms;
629 int n;
630 opus_int16 frame_sizes[48];
631 const unsigned char *frame_data[48];
632
Peter Kastingdce40cf2015-08-24 14:52:23 -0700633 if (payload == NULL || payload_length_bytes == 0)
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000634 return 0;
635
636 /* In CELT_ONLY mode, packets should not have FEC. */
637 if (payload[0] & 0x80)
638 return 0;
639
640 payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
641 if (10 > payload_length_ms)
642 payload_length_ms = 10;
643
644 channels = opus_packet_get_nb_channels(payload);
645
646 switch (payload_length_ms) {
647 case 10:
648 case 20: {
649 frames = 1;
650 break;
651 }
652 case 40: {
653 frames = 2;
654 break;
655 }
656 case 60: {
657 frames = 3;
658 break;
659 }
660 default: {
661 return 0; // It is actually even an invalid packet.
662 }
663 }
664
665 /* The following is to parse the LBRR flags. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700666 if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
667 frame_data, frame_sizes, NULL) < 0) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000668 return 0;
669 }
670
671 if (frame_sizes[0] <= 1) {
672 return 0;
673 }
674
675 for (n = 0; n < channels; n++) {
676 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
677 return 1;
678 }
679
680 return 0;
681}