blob: d07a5b4bc83dc94781a99a27c85125f748583125 [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
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000040int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
Peter Kasting69558702016-01-12 16:26:35 -080041 size_t channels,
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000042 int32_t application) {
minyue3cea2562015-11-10 03:49:26 -080043 int opus_app;
44 if (!inst)
45 return -1;
tina.legrand@webrtc.orgd0d41492012-12-20 09:23:10 +000046
minyue3cea2562015-11-10 03:49:26 -080047 switch (application) {
48 case 0:
49 opus_app = OPUS_APPLICATION_VOIP;
50 break;
51 case 1:
52 opus_app = OPUS_APPLICATION_AUDIO;
53 break;
54 default:
55 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000056 }
minyue3cea2562015-11-10 03:49:26 -080057
Alex Loiko7a3e43a2019-01-29 12:27:08 +010058 OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
kwiberg2e486462016-08-23 05:54:25 -070059 RTC_DCHECK(state);
minyue3cea2562015-11-10 03:49:26 -080060
minyue3cea2562015-11-10 03:49:26 -080061 int error;
Alex Loiko50b8c392019-04-03 15:12:01 +020062 state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
63 &error);
Alex Loiko7a3e43a2019-01-29 12:27:08 +010064
Alex Loiko50b8c392019-04-03 15:12:01 +020065 if (error != OPUS_OK || (!state->encoder &&
66 !state->multistream_encoder)) {
67 WebRtcOpus_EncoderFree(state);
68 return -1;
Alex Loiko7a3e43a2019-01-29 12:27:08 +010069 }
70
Alex Loiko50b8c392019-04-03 15:12:01 +020071 state->in_dtx_mode = 0;
72 state->channels = channels;
73
74 *inst = state;
75 return 0;
76}
77
78int16_t WebRtcOpus_MultistreamEncoderCreate(
79 OpusEncInst** inst,
80 size_t channels,
81 int32_t application,
Alex Loikoe5b94162019-04-08 17:19:41 +020082 size_t streams,
Alex Loiko50b8c392019-04-03 15:12:01 +020083 size_t coupled_streams,
84 const unsigned char *channel_mapping) {
85 int opus_app;
86 if (!inst)
87 return -1;
88
89 switch (application) {
90 case 0:
91 opus_app = OPUS_APPLICATION_VOIP;
92 break;
93 case 1:
94 opus_app = OPUS_APPLICATION_AUDIO;
95 break;
96 default:
97 return -1;
98 }
99
100 OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
101 RTC_DCHECK(state);
102
Alex Loiko50b8c392019-04-03 15:12:01 +0200103 int error;
104 state->multistream_encoder =
105 opus_multistream_encoder_create(
106 48000,
107 channels,
108 streams,
109 coupled_streams,
110 channel_mapping,
111 opus_app,
112 &error);
113
114 if (error != OPUS_OK || (!state->encoder &&
115 !state->multistream_encoder)) {
minyue3cea2562015-11-10 03:49:26 -0800116 WebRtcOpus_EncoderFree(state);
117 return -1;
118 }
119
120 state->in_dtx_mode = 0;
121 state->channels = channels;
122
123 *inst = state;
124 return 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000125}
126
127int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000128 if (inst) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200129 if (inst->encoder) {
130 opus_encoder_destroy(inst->encoder);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100131 } else {
Alex Loiko50b8c392019-04-03 15:12:01 +0200132 opus_multistream_encoder_destroy(inst->multistream_encoder);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100133 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000134 free(inst);
135 return 0;
136 } else {
137 return -1;
138 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000139}
140
Peter Kastingbba78072015-06-11 19:02:46 -0700141int WebRtcOpus_Encode(OpusEncInst* inst,
142 const int16_t* audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700143 size_t samples,
144 size_t length_encoded_buffer,
Peter Kastingbba78072015-06-11 19:02:46 -0700145 uint8_t* encoded) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000146 int res;
147
148 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
149 return -1;
150 }
151
Alex Loiko50b8c392019-04-03 15:12:01 +0200152 if (inst->encoder) {
153 res = opus_encode(inst->encoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100154 (const opus_int16*)audio_in,
155 (int)samples,
156 encoded,
157 (opus_int32)length_encoded_buffer);
158 } else {
Alex Loiko50b8c392019-04-03 15:12:01 +0200159 res = opus_multistream_encode(inst->multistream_encoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100160 (const opus_int16*)audio_in,
161 (int)samples,
162 encoded,
163 (opus_int32)length_encoded_buffer);
164 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000165
flim64a7eab2016-08-12 04:36:05 -0700166 if (res <= 0) {
167 return -1;
168 }
169
170 if (res <= 2) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000171 // Indicates DTX since the packet has nothing but a header. In principle,
172 // there is no need to send this packet. However, we do transmit the first
173 // occurrence to let the decoder know that the encoder enters DTX mode.
174 if (inst->in_dtx_mode) {
175 return 0;
176 } else {
177 inst->in_dtx_mode = 1;
flim92382452017-02-10 13:50:38 -0800178 return res;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000179 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000180 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000181
flim64a7eab2016-08-12 04:36:05 -0700182 inst->in_dtx_mode = 0;
183 return res;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000184}
185
Alex Loiko50b8c392019-04-03 15:12:01 +0200186#define ENCODER_CTL(inst, vargs) ( \
187 inst->encoder ? \
188 opus_encoder_ctl(inst->encoder, vargs) \
189 : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs))
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100190
191
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000192int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000193 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100194 return ENCODER_CTL(inst, OPUS_SET_BITRATE(rate));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000195 } else {
196 return -1;
197 }
198}
199
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000200int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
201 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100202 return ENCODER_CTL(inst, OPUS_SET_PACKET_LOSS_PERC(loss_rate));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000203 } else {
204 return -1;
205 }
206}
207
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000208int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000209 opus_int32 set_bandwidth;
210
211 if (!inst)
212 return -1;
213
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000214 if (frequency_hz <= 8000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000215 set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000216 } else if (frequency_hz <= 12000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000217 set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000218 } else if (frequency_hz <= 16000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000219 set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000220 } else if (frequency_hz <= 24000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000221 set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
222 } else {
223 set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
224 }
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100225 return ENCODER_CTL(inst, OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
226}
227
228int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
229 int32_t* result_hz) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200230 if (inst->encoder) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100231 if (opus_encoder_ctl(
Alex Loiko50b8c392019-04-03 15:12:01 +0200232 inst->encoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100233 OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
234 return 0;
235 }
236 return -1;
237 }
238
239 opus_int32 max_bandwidth;
240 int s;
241 int ret;
242
243 max_bandwidth = 0;
244 ret = OPUS_OK;
245 s = 0;
246 while (ret == OPUS_OK) {
247 OpusEncoder *enc;
248 opus_int32 bandwidth;
249
250 ret = ENCODER_CTL(inst, OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
251 if (ret == OPUS_BAD_ARG)
252 break;
253 if (ret != OPUS_OK)
254 return -1;
255 if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
256 return -1;
257
258 if (max_bandwidth != 0 && max_bandwidth != bandwidth)
259 return -1;
260
261 max_bandwidth = bandwidth;
262 s++;
263 }
264 *result_hz = max_bandwidth;
265 return 0;
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000266}
267
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000268int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
269 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100270 return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(1));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000271 } else {
272 return -1;
273 }
274}
275
276int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
277 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100278 return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(0));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000279 } else {
280 return -1;
281 }
282}
283
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000284int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200285 if (!inst) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000286 return -1;
287 }
Minyue Li092041c2015-05-11 12:19:35 +0200288
289 // To prevent Opus from entering CELT-only mode by forcing signal type to
290 // voice to make sure that DTX behaves correctly. Currently, DTX does not
291 // last long during a pure silence, if the signal type is not forced.
292 // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
293 // without it.
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100294 int ret = ENCODER_CTL(inst,
295 OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
Minyue Li092041c2015-05-11 12:19:35 +0200296 if (ret != OPUS_OK)
297 return ret;
298
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100299 return ENCODER_CTL(inst, OPUS_SET_DTX(1));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000300}
301
302int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
303 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100304 int ret = ENCODER_CTL(inst,
305 OPUS_SET_SIGNAL(OPUS_AUTO));
Minyue Li092041c2015-05-11 12:19:35 +0200306 if (ret != OPUS_OK)
307 return ret;
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100308 return ENCODER_CTL(inst, OPUS_SET_DTX(0));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000309 } else {
310 return -1;
311 }
312}
313
soren28dc2852017-04-06 05:48:36 -0700314int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
315 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100316 return ENCODER_CTL(inst, OPUS_SET_VBR(0));
soren28dc2852017-04-06 05:48:36 -0700317 } else {
318 return -1;
319 }
320}
321
322int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
323 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100324 return ENCODER_CTL(inst, OPUS_SET_VBR(1));
soren28dc2852017-04-06 05:48:36 -0700325 } else {
326 return -1;
327 }
328}
329
minyue@webrtc.org04546882014-03-07 08:55:48 +0000330int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
331 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100332 return ENCODER_CTL(inst,
333 OPUS_SET_COMPLEXITY(complexity));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000334 } else {
335 return -1;
336 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000337}
338
Alex Luebseeb27652017-11-20 11:13:56 -0800339int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst) {
340 if (!inst) {
341 return -1;
342 }
343 int32_t bandwidth;
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100344 if (ENCODER_CTL(inst,
345 OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
Alex Luebseeb27652017-11-20 11:13:56 -0800346 return bandwidth;
347 } else {
348 return -1;
349 }
350
351}
352
353int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
354 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100355 return ENCODER_CTL(inst,
356 OPUS_SET_BANDWIDTH(bandwidth));
Alex Luebseeb27652017-11-20 11:13:56 -0800357 } else {
358 return -1;
359 }
360}
361
minyue41b9c802016-10-06 07:13:54 -0700362int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
minyuec8299f92016-09-27 02:08:47 -0700363 if (!inst)
364 return -1;
365 if (num_channels == 0) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100366 return ENCODER_CTL(inst,
minyuec8299f92016-09-27 02:08:47 -0700367 OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
368 } else if (num_channels == 1 || num_channels == 2) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100369 return ENCODER_CTL(inst,
370 OPUS_SET_FORCE_CHANNELS(num_channels));
minyuec8299f92016-09-27 02:08:47 -0700371 } else {
372 return -1;
373 }
374}
375
Peter Kasting69558702016-01-12 16:26:35 -0800376int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000377 int error;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000378 OpusDecInst* state;
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000379
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000380 if (inst != NULL) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100381 // Create Opus decoder state.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000382 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
383 if (state == NULL) {
384 return -1;
385 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000386
Alex Loiko50b8c392019-04-03 15:12:01 +0200387 // Create new memory, always at 48000 Hz.
388 state->decoder = opus_decoder_create(48000,
389 (int)channels, &error);
390 if (error == OPUS_OK && state->decoder) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100391 // Creation of memory all ok.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000392 state->channels = channels;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000393 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000394 state->in_dtx_mode = 0;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000395 *inst = state;
396 return 0;
397 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000398
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100399 // If memory allocation was unsuccessful, free the entire state.
Alex Loiko50b8c392019-04-03 15:12:01 +0200400 if (state->decoder) {
401 opus_decoder_destroy(state->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000402 }
403 free(state);
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000404 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000405 return -1;
406}
407
Alex Loiko50b8c392019-04-03 15:12:01 +0200408int16_t WebRtcOpus_MultistreamDecoderCreate(
409 OpusDecInst** inst, size_t channels,
Alex Loikoe5b94162019-04-08 17:19:41 +0200410 size_t streams,
Alex Loiko50b8c392019-04-03 15:12:01 +0200411 size_t coupled_streams,
412 const unsigned char* channel_mapping) {
413 int error;
414 OpusDecInst* state;
415
416 if (inst != NULL) {
417 // Create Opus decoder state.
418 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
419 if (state == NULL) {
420 return -1;
421 }
422
Alex Loiko50b8c392019-04-03 15:12:01 +0200423 // Create new memory, always at 48000 Hz.
424 state->multistream_decoder = opus_multistream_decoder_create(
Alex Loikoe5b94162019-04-08 17:19:41 +0200425 48000, channels,
Alex Loiko50b8c392019-04-03 15:12:01 +0200426 streams,
427 coupled_streams,
428 channel_mapping,
429 &error);
430
431 if (error == OPUS_OK && state->multistream_decoder) {
432 // Creation of memory all ok.
433 state->channels = channels;
434 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
435 state->in_dtx_mode = 0;
436 *inst = state;
437 return 0;
438 }
439
440 // If memory allocation was unsuccessful, free the entire state.
441 opus_multistream_decoder_destroy(state->multistream_decoder);
442 free(state);
443 }
444 return -1;
445}
446
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000447int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000448 if (inst) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200449 if (inst->decoder) {
450 opus_decoder_destroy(inst->decoder);
451 } else if (inst->multistream_decoder) {
452 opus_multistream_decoder_destroy(inst->multistream_decoder);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100453 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000454 free(inst);
455 return 0;
456 } else {
457 return -1;
458 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000459}
460
Peter Kasting69558702016-01-12 16:26:35 -0800461size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000462 return inst->channels;
463}
464
Karl Wiberg43766482015-08-27 15:22:11 +0200465void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200466 if (inst->decoder) {
467 opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100468 } else {
Alex Loiko50b8c392019-04-03 15:12:01 +0200469 opus_multistream_decoder_ctl(inst->multistream_decoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100470 OPUS_RESET_STATE);
471 }
Karl Wiberg43766482015-08-27 15:22:11 +0200472 inst->in_dtx_mode = 0;
tina.legrand@webrtc.org0ad3c1a2012-11-07 08:07:29 +0000473}
474
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000475/* For decoder to determine if it is to output speech or comfort noise. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700476static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000477 // Audio type becomes comfort noise if |encoded_byte| is 1 and keeps
478 // to be so if the following |encoded_byte| are 0 or 1.
479 if (encoded_bytes == 0 && inst->in_dtx_mode) {
480 return 2; // Comfort noise.
henrik.lundindeaf6fb2017-03-01 00:49:18 -0800481 } else if (encoded_bytes == 1 || encoded_bytes == 2) {
482 // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
483 // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
484 // interpreted as comfort noise output, but such a payload is probably
485 // faulty anyway.
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100486
487 // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
488 // single-stream packets glued together with some packet size bytes in
489 // between. See https://tools.ietf.org/html/rfc6716#appendix-B
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000490 inst->in_dtx_mode = 1;
491 return 2; // Comfort noise.
492 } else {
493 inst->in_dtx_mode = 0;
494 return 0; // Speech.
495 }
496}
497
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000498/* |frame_size| is set to maximum Opus frame size in the normal case, and
499 * is set to the number of samples needed for PLC in case of losses.
500 * It is up to the caller to make sure the value is correct. */
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000501static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700502 size_t encoded_bytes, int frame_size,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000503 int16_t* decoded, int16_t* audio_type, int decode_fec) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100504 int res = -1;
Alex Loiko50b8c392019-04-03 15:12:01 +0200505 if (inst->decoder) {
506 res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100507 (opus_int16*)decoded, frame_size, decode_fec);
508 } else {
509 res = opus_multistream_decode(
Alex Loiko50b8c392019-04-03 15:12:01 +0200510 inst->multistream_decoder, encoded, (opus_int32)encoded_bytes,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100511 (opus_int16*)decoded, frame_size, decode_fec);
512 }
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000513
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000514 if (res <= 0)
515 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000516
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000517 *audio_type = DetermineAudioType(inst, encoded_bytes);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000518
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000519 return res;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000520}
521
Peter Kastingbba78072015-06-11 19:02:46 -0700522int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700523 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700524 int16_t* audio_type) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000525 int decoded_samples;
526
527 if (encoded_bytes == 0) {
528 *audio_type = DetermineAudioType(inst, encoded_bytes);
529 decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
530 } else {
531 decoded_samples = DecodeNative(inst,
532 encoded,
533 encoded_bytes,
534 kWebRtcOpusMaxFrameSizePerChannel,
535 decoded,
536 audio_type,
537 0);
538 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000539 if (decoded_samples < 0) {
540 return -1;
541 }
542
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000543 /* Update decoded sample memory, to be used by the PLC in case of losses. */
544 inst->prev_decoded_samples = decoded_samples;
545
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000546 return decoded_samples;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000547}
548
Peter Kastingbba78072015-06-11 19:02:46 -0700549int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
550 int number_of_lost_frames) {
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000551 int16_t audio_type = 0;
552 int decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000553 int plc_samples;
554
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000555 /* The number of samples we ask for is |number_of_lost_frames| times
556 * |prev_decoded_samples_|. Limit the number of samples to maximum
557 * |kWebRtcOpusMaxFrameSizePerChannel|. */
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000558 plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
559 plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
560 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000561 decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
562 decoded, &audio_type, 0);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000563 if (decoded_samples < 0) {
564 return -1;
565 }
566
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000567 return decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000568}
569
Peter Kastingbba78072015-06-11 19:02:46 -0700570int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700571 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700572 int16_t* audio_type) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000573 int decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000574 int fec_samples;
575
576 if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
577 return 0;
578 }
579
580 fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
581
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000582 decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
583 fec_samples, decoded, audio_type, 1);
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000584 if (decoded_samples < 0) {
585 return -1;
586 }
587
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000588 return decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000589}
590
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000591int WebRtcOpus_DurationEst(OpusDecInst* inst,
592 const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700593 size_t payload_length_bytes) {
minyuel6d92bf52015-09-23 15:20:39 +0200594 if (payload_length_bytes == 0) {
595 // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
596 // PLC duration correspondingly.
597 return WebRtcOpus_PlcDuration(inst);
598 }
599
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000600 int frames, samples;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700601 frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000602 if (frames < 0) {
603 /* Invalid payload data. */
604 return 0;
605 }
606 samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
607 if (samples < 120 || samples > 5760) {
608 /* Invalid payload duration. */
609 return 0;
610 }
611 return samples;
612}
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000613
minyuel6d92bf52015-09-23 15:20:39 +0200614int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
615 /* The number of samples we ask for is |number_of_lost_frames| times
616 * |prev_decoded_samples_|. Limit the number of samples to maximum
617 * |kWebRtcOpusMaxFrameSizePerChannel|. */
618 const int plc_samples = inst->prev_decoded_samples;
619 return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
620 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
621}
622
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000623int WebRtcOpus_FecDurationEst(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700624 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000625 int samples;
626 if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
627 return 0;
628 }
629
630 samples = opus_packet_get_samples_per_frame(payload, 48000);
631 if (samples < 480 || samples > 5760) {
632 /* Invalid payload duration. */
633 return 0;
634 }
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000635 return samples;
636}
637
638int WebRtcOpus_PacketHasFec(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700639 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000640 int frames, channels, payload_length_ms;
641 int n;
642 opus_int16 frame_sizes[48];
643 const unsigned char *frame_data[48];
644
Peter Kastingdce40cf2015-08-24 14:52:23 -0700645 if (payload == NULL || payload_length_bytes == 0)
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000646 return 0;
647
648 /* In CELT_ONLY mode, packets should not have FEC. */
649 if (payload[0] & 0x80)
650 return 0;
651
652 payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
653 if (10 > payload_length_ms)
654 payload_length_ms = 10;
655
656 channels = opus_packet_get_nb_channels(payload);
657
658 switch (payload_length_ms) {
659 case 10:
660 case 20: {
661 frames = 1;
662 break;
663 }
664 case 40: {
665 frames = 2;
666 break;
667 }
668 case 60: {
669 frames = 3;
670 break;
671 }
672 default: {
673 return 0; // It is actually even an invalid packet.
674 }
675 }
676
677 /* The following is to parse the LBRR flags. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700678 if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
679 frame_data, frame_sizes, NULL) < 0) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000680 return 0;
681 }
682
683 if (frame_sizes[0] <= 1) {
684 return 0;
685 }
686
687 for (n = 0; n < channels; n++) {
688 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
689 return 1;
690 }
691
692 return 0;
693}