blob: 817caac11721dc8c4fbd861ff04156254ed0d9d9 [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,
Karl Wiberg7e7c5c32019-05-21 11:50:32 +020042 int32_t application,
43 int sample_rate_hz) {
minyue3cea2562015-11-10 03:49:26 -080044 int opus_app;
45 if (!inst)
46 return -1;
tina.legrand@webrtc.orgd0d41492012-12-20 09:23:10 +000047
minyue3cea2562015-11-10 03:49:26 -080048 switch (application) {
49 case 0:
50 opus_app = OPUS_APPLICATION_VOIP;
51 break;
52 case 1:
53 opus_app = OPUS_APPLICATION_AUDIO;
54 break;
55 default:
56 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000057 }
minyue3cea2562015-11-10 03:49:26 -080058
Alex Loiko7a3e43a2019-01-29 12:27:08 +010059 OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
kwiberg2e486462016-08-23 05:54:25 -070060 RTC_DCHECK(state);
minyue3cea2562015-11-10 03:49:26 -080061
minyue3cea2562015-11-10 03:49:26 -080062 int error;
Karl Wiberg7e7c5c32019-05-21 11:50:32 +020063 state->encoder = opus_encoder_create(sample_rate_hz, (int)channels, opus_app,
Alex Loiko50b8c392019-04-03 15:12:01 +020064 &error);
Alex Loiko7a3e43a2019-01-29 12:27:08 +010065
Alex Loiko50b8c392019-04-03 15:12:01 +020066 if (error != OPUS_OK || (!state->encoder &&
67 !state->multistream_encoder)) {
68 WebRtcOpus_EncoderFree(state);
69 return -1;
Alex Loiko7a3e43a2019-01-29 12:27:08 +010070 }
71
Alex Loiko50b8c392019-04-03 15:12:01 +020072 state->in_dtx_mode = 0;
73 state->channels = channels;
74
75 *inst = state;
76 return 0;
77}
78
79int16_t WebRtcOpus_MultistreamEncoderCreate(
80 OpusEncInst** inst,
81 size_t channels,
82 int32_t application,
Alex Loikoe5b94162019-04-08 17:19:41 +020083 size_t streams,
Alex Loiko50b8c392019-04-03 15:12:01 +020084 size_t coupled_streams,
85 const unsigned char *channel_mapping) {
86 int opus_app;
87 if (!inst)
88 return -1;
89
90 switch (application) {
91 case 0:
92 opus_app = OPUS_APPLICATION_VOIP;
93 break;
94 case 1:
95 opus_app = OPUS_APPLICATION_AUDIO;
96 break;
97 default:
98 return -1;
99 }
100
101 OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
102 RTC_DCHECK(state);
103
Alex Loiko50b8c392019-04-03 15:12:01 +0200104 int error;
105 state->multistream_encoder =
106 opus_multistream_encoder_create(
107 48000,
108 channels,
109 streams,
110 coupled_streams,
111 channel_mapping,
112 opus_app,
113 &error);
114
115 if (error != OPUS_OK || (!state->encoder &&
116 !state->multistream_encoder)) {
minyue3cea2562015-11-10 03:49:26 -0800117 WebRtcOpus_EncoderFree(state);
118 return -1;
119 }
120
121 state->in_dtx_mode = 0;
122 state->channels = channels;
123
124 *inst = state;
125 return 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000126}
127
128int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000129 if (inst) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200130 if (inst->encoder) {
131 opus_encoder_destroy(inst->encoder);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100132 } else {
Alex Loiko50b8c392019-04-03 15:12:01 +0200133 opus_multistream_encoder_destroy(inst->multistream_encoder);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100134 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000135 free(inst);
136 return 0;
137 } else {
138 return -1;
139 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000140}
141
Peter Kastingbba78072015-06-11 19:02:46 -0700142int WebRtcOpus_Encode(OpusEncInst* inst,
143 const int16_t* audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700144 size_t samples,
145 size_t length_encoded_buffer,
Peter Kastingbba78072015-06-11 19:02:46 -0700146 uint8_t* encoded) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000147 int res;
148
149 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
150 return -1;
151 }
152
Alex Loiko50b8c392019-04-03 15:12:01 +0200153 if (inst->encoder) {
154 res = opus_encode(inst->encoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100155 (const opus_int16*)audio_in,
156 (int)samples,
157 encoded,
158 (opus_int32)length_encoded_buffer);
159 } else {
Alex Loiko50b8c392019-04-03 15:12:01 +0200160 res = opus_multistream_encode(inst->multistream_encoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100161 (const opus_int16*)audio_in,
162 (int)samples,
163 encoded,
164 (opus_int32)length_encoded_buffer);
165 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000166
flim64a7eab2016-08-12 04:36:05 -0700167 if (res <= 0) {
168 return -1;
169 }
170
171 if (res <= 2) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000172 // Indicates DTX since the packet has nothing but a header. In principle,
173 // there is no need to send this packet. However, we do transmit the first
174 // occurrence to let the decoder know that the encoder enters DTX mode.
175 if (inst->in_dtx_mode) {
176 return 0;
177 } else {
178 inst->in_dtx_mode = 1;
flim92382452017-02-10 13:50:38 -0800179 return res;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000180 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000181 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000182
flim64a7eab2016-08-12 04:36:05 -0700183 inst->in_dtx_mode = 0;
184 return res;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000185}
186
Alex Loiko50b8c392019-04-03 15:12:01 +0200187#define ENCODER_CTL(inst, vargs) ( \
188 inst->encoder ? \
189 opus_encoder_ctl(inst->encoder, vargs) \
190 : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs))
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100191
192
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000193int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000194 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100195 return ENCODER_CTL(inst, OPUS_SET_BITRATE(rate));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000196 } else {
197 return -1;
198 }
199}
200
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000201int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
202 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100203 return ENCODER_CTL(inst, OPUS_SET_PACKET_LOSS_PERC(loss_rate));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000204 } else {
205 return -1;
206 }
207}
208
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000209int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000210 opus_int32 set_bandwidth;
211
212 if (!inst)
213 return -1;
214
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000215 if (frequency_hz <= 8000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000216 set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000217 } else if (frequency_hz <= 12000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000218 set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000219 } else if (frequency_hz <= 16000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000220 set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000221 } else if (frequency_hz <= 24000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000222 set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
223 } else {
224 set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
225 }
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100226 return ENCODER_CTL(inst, OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
227}
228
229int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
230 int32_t* result_hz) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200231 if (inst->encoder) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100232 if (opus_encoder_ctl(
Alex Loiko50b8c392019-04-03 15:12:01 +0200233 inst->encoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100234 OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
235 return 0;
236 }
237 return -1;
238 }
239
240 opus_int32 max_bandwidth;
241 int s;
242 int ret;
243
244 max_bandwidth = 0;
245 ret = OPUS_OK;
246 s = 0;
247 while (ret == OPUS_OK) {
248 OpusEncoder *enc;
249 opus_int32 bandwidth;
250
251 ret = ENCODER_CTL(inst, OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
252 if (ret == OPUS_BAD_ARG)
253 break;
254 if (ret != OPUS_OK)
255 return -1;
256 if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
257 return -1;
258
259 if (max_bandwidth != 0 && max_bandwidth != bandwidth)
260 return -1;
261
262 max_bandwidth = bandwidth;
263 s++;
264 }
265 *result_hz = max_bandwidth;
266 return 0;
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000267}
268
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000269int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
270 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100271 return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(1));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000272 } else {
273 return -1;
274 }
275}
276
277int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
278 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100279 return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(0));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000280 } else {
281 return -1;
282 }
283}
284
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000285int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200286 if (!inst) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000287 return -1;
288 }
Minyue Li092041c2015-05-11 12:19:35 +0200289
290 // To prevent Opus from entering CELT-only mode by forcing signal type to
291 // voice to make sure that DTX behaves correctly. Currently, DTX does not
292 // last long during a pure silence, if the signal type is not forced.
293 // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
294 // without it.
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100295 int ret = ENCODER_CTL(inst,
296 OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
Minyue Li092041c2015-05-11 12:19:35 +0200297 if (ret != OPUS_OK)
298 return ret;
299
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100300 return ENCODER_CTL(inst, OPUS_SET_DTX(1));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000301}
302
303int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
304 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100305 int ret = ENCODER_CTL(inst,
306 OPUS_SET_SIGNAL(OPUS_AUTO));
Minyue Li092041c2015-05-11 12:19:35 +0200307 if (ret != OPUS_OK)
308 return ret;
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100309 return ENCODER_CTL(inst, OPUS_SET_DTX(0));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000310 } else {
311 return -1;
312 }
313}
314
soren28dc2852017-04-06 05:48:36 -0700315int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
316 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100317 return ENCODER_CTL(inst, OPUS_SET_VBR(0));
soren28dc2852017-04-06 05:48:36 -0700318 } else {
319 return -1;
320 }
321}
322
323int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
324 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100325 return ENCODER_CTL(inst, OPUS_SET_VBR(1));
soren28dc2852017-04-06 05:48:36 -0700326 } else {
327 return -1;
328 }
329}
330
minyue@webrtc.org04546882014-03-07 08:55:48 +0000331int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
332 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100333 return ENCODER_CTL(inst,
334 OPUS_SET_COMPLEXITY(complexity));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000335 } else {
336 return -1;
337 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000338}
339
Alex Luebseeb27652017-11-20 11:13:56 -0800340int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst) {
341 if (!inst) {
342 return -1;
343 }
344 int32_t bandwidth;
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100345 if (ENCODER_CTL(inst,
346 OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
Alex Luebseeb27652017-11-20 11:13:56 -0800347 return bandwidth;
348 } else {
349 return -1;
350 }
351
352}
353
354int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
355 if (inst) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100356 return ENCODER_CTL(inst,
357 OPUS_SET_BANDWIDTH(bandwidth));
Alex Luebseeb27652017-11-20 11:13:56 -0800358 } else {
359 return -1;
360 }
361}
362
minyue41b9c802016-10-06 07:13:54 -0700363int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
minyuec8299f92016-09-27 02:08:47 -0700364 if (!inst)
365 return -1;
366 if (num_channels == 0) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100367 return ENCODER_CTL(inst,
minyuec8299f92016-09-27 02:08:47 -0700368 OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
369 } else if (num_channels == 1 || num_channels == 2) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100370 return ENCODER_CTL(inst,
371 OPUS_SET_FORCE_CHANNELS(num_channels));
minyuec8299f92016-09-27 02:08:47 -0700372 } else {
373 return -1;
374 }
375}
376
Peter Kasting69558702016-01-12 16:26:35 -0800377int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000378 int error;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000379 OpusDecInst* state;
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000380
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000381 if (inst != NULL) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100382 // Create Opus decoder state.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000383 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
384 if (state == NULL) {
385 return -1;
386 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000387
Alex Loiko50b8c392019-04-03 15:12:01 +0200388 // Create new memory, always at 48000 Hz.
389 state->decoder = opus_decoder_create(48000,
390 (int)channels, &error);
391 if (error == OPUS_OK && state->decoder) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100392 // Creation of memory all ok.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000393 state->channels = channels;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000394 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000395 state->in_dtx_mode = 0;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000396 *inst = state;
397 return 0;
398 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000399
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100400 // If memory allocation was unsuccessful, free the entire state.
Alex Loiko50b8c392019-04-03 15:12:01 +0200401 if (state->decoder) {
402 opus_decoder_destroy(state->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000403 }
404 free(state);
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000405 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000406 return -1;
407}
408
Alex Loiko50b8c392019-04-03 15:12:01 +0200409int16_t WebRtcOpus_MultistreamDecoderCreate(
410 OpusDecInst** inst, size_t channels,
Alex Loikoe5b94162019-04-08 17:19:41 +0200411 size_t streams,
Alex Loiko50b8c392019-04-03 15:12:01 +0200412 size_t coupled_streams,
413 const unsigned char* channel_mapping) {
414 int error;
415 OpusDecInst* state;
416
417 if (inst != NULL) {
418 // Create Opus decoder state.
419 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
420 if (state == NULL) {
421 return -1;
422 }
423
Alex Loiko50b8c392019-04-03 15:12:01 +0200424 // Create new memory, always at 48000 Hz.
425 state->multistream_decoder = opus_multistream_decoder_create(
Alex Loikoe5b94162019-04-08 17:19:41 +0200426 48000, channels,
Alex Loiko50b8c392019-04-03 15:12:01 +0200427 streams,
428 coupled_streams,
429 channel_mapping,
430 &error);
431
432 if (error == OPUS_OK && state->multistream_decoder) {
433 // Creation of memory all ok.
434 state->channels = channels;
435 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
436 state->in_dtx_mode = 0;
437 *inst = state;
438 return 0;
439 }
440
441 // If memory allocation was unsuccessful, free the entire state.
442 opus_multistream_decoder_destroy(state->multistream_decoder);
443 free(state);
444 }
445 return -1;
446}
447
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000448int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000449 if (inst) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200450 if (inst->decoder) {
451 opus_decoder_destroy(inst->decoder);
452 } else if (inst->multistream_decoder) {
453 opus_multistream_decoder_destroy(inst->multistream_decoder);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100454 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000455 free(inst);
456 return 0;
457 } else {
458 return -1;
459 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000460}
461
Peter Kasting69558702016-01-12 16:26:35 -0800462size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000463 return inst->channels;
464}
465
Karl Wiberg43766482015-08-27 15:22:11 +0200466void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
Alex Loiko50b8c392019-04-03 15:12:01 +0200467 if (inst->decoder) {
468 opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100469 } else {
Alex Loiko50b8c392019-04-03 15:12:01 +0200470 opus_multistream_decoder_ctl(inst->multistream_decoder,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100471 OPUS_RESET_STATE);
472 }
Karl Wiberg43766482015-08-27 15:22:11 +0200473 inst->in_dtx_mode = 0;
tina.legrand@webrtc.org0ad3c1a2012-11-07 08:07:29 +0000474}
475
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000476/* For decoder to determine if it is to output speech or comfort noise. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700477static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000478 // Audio type becomes comfort noise if |encoded_byte| is 1 and keeps
479 // to be so if the following |encoded_byte| are 0 or 1.
480 if (encoded_bytes == 0 && inst->in_dtx_mode) {
481 return 2; // Comfort noise.
henrik.lundindeaf6fb2017-03-01 00:49:18 -0800482 } else if (encoded_bytes == 1 || encoded_bytes == 2) {
483 // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
484 // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
485 // interpreted as comfort noise output, but such a payload is probably
486 // faulty anyway.
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100487
488 // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
489 // single-stream packets glued together with some packet size bytes in
490 // between. See https://tools.ietf.org/html/rfc6716#appendix-B
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000491 inst->in_dtx_mode = 1;
492 return 2; // Comfort noise.
493 } else {
494 inst->in_dtx_mode = 0;
495 return 0; // Speech.
496 }
497}
498
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000499/* |frame_size| is set to maximum Opus frame size in the normal case, and
500 * is set to the number of samples needed for PLC in case of losses.
501 * It is up to the caller to make sure the value is correct. */
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000502static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700503 size_t encoded_bytes, int frame_size,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000504 int16_t* decoded, int16_t* audio_type, int decode_fec) {
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100505 int res = -1;
Alex Loiko50b8c392019-04-03 15:12:01 +0200506 if (inst->decoder) {
507 res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100508 (opus_int16*)decoded, frame_size, decode_fec);
509 } else {
510 res = opus_multistream_decode(
Alex Loiko50b8c392019-04-03 15:12:01 +0200511 inst->multistream_decoder, encoded, (opus_int32)encoded_bytes,
Alex Loiko7a3e43a2019-01-29 12:27:08 +0100512 (opus_int16*)decoded, frame_size, decode_fec);
513 }
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000514
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000515 if (res <= 0)
516 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000517
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000518 *audio_type = DetermineAudioType(inst, encoded_bytes);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000519
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000520 return res;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000521}
522
Peter Kastingbba78072015-06-11 19:02:46 -0700523int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700524 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700525 int16_t* audio_type) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000526 int decoded_samples;
527
528 if (encoded_bytes == 0) {
529 *audio_type = DetermineAudioType(inst, encoded_bytes);
530 decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
531 } else {
532 decoded_samples = DecodeNative(inst,
533 encoded,
534 encoded_bytes,
535 kWebRtcOpusMaxFrameSizePerChannel,
536 decoded,
537 audio_type,
538 0);
539 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000540 if (decoded_samples < 0) {
541 return -1;
542 }
543
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000544 /* Update decoded sample memory, to be used by the PLC in case of losses. */
545 inst->prev_decoded_samples = decoded_samples;
546
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000547 return decoded_samples;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000548}
549
Peter Kastingbba78072015-06-11 19:02:46 -0700550int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
551 int number_of_lost_frames) {
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000552 int16_t audio_type = 0;
553 int decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000554 int plc_samples;
555
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000556 /* The number of samples we ask for is |number_of_lost_frames| times
557 * |prev_decoded_samples_|. Limit the number of samples to maximum
558 * |kWebRtcOpusMaxFrameSizePerChannel|. */
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000559 plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
560 plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
561 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000562 decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
563 decoded, &audio_type, 0);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000564 if (decoded_samples < 0) {
565 return -1;
566 }
567
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000568 return decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000569}
570
Peter Kastingbba78072015-06-11 19:02:46 -0700571int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700572 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700573 int16_t* audio_type) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000574 int decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000575 int fec_samples;
576
577 if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
578 return 0;
579 }
580
581 fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
582
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000583 decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
584 fec_samples, decoded, audio_type, 1);
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000585 if (decoded_samples < 0) {
586 return -1;
587 }
588
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000589 return decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000590}
591
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000592int WebRtcOpus_DurationEst(OpusDecInst* inst,
593 const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700594 size_t payload_length_bytes) {
minyuel6d92bf52015-09-23 15:20:39 +0200595 if (payload_length_bytes == 0) {
596 // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
597 // PLC duration correspondingly.
598 return WebRtcOpus_PlcDuration(inst);
599 }
600
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000601 int frames, samples;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700602 frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000603 if (frames < 0) {
604 /* Invalid payload data. */
605 return 0;
606 }
607 samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
608 if (samples < 120 || samples > 5760) {
609 /* Invalid payload duration. */
610 return 0;
611 }
612 return samples;
613}
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000614
minyuel6d92bf52015-09-23 15:20:39 +0200615int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
616 /* The number of samples we ask for is |number_of_lost_frames| times
617 * |prev_decoded_samples_|. Limit the number of samples to maximum
618 * |kWebRtcOpusMaxFrameSizePerChannel|. */
619 const int plc_samples = inst->prev_decoded_samples;
620 return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
621 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
622}
623
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000624int WebRtcOpus_FecDurationEst(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700625 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000626 int samples;
627 if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
628 return 0;
629 }
630
631 samples = opus_packet_get_samples_per_frame(payload, 48000);
632 if (samples < 480 || samples > 5760) {
633 /* Invalid payload duration. */
634 return 0;
635 }
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000636 return samples;
637}
638
639int WebRtcOpus_PacketHasFec(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700640 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000641 int frames, channels, payload_length_ms;
642 int n;
643 opus_int16 frame_sizes[48];
644 const unsigned char *frame_data[48];
645
Peter Kastingdce40cf2015-08-24 14:52:23 -0700646 if (payload == NULL || payload_length_bytes == 0)
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000647 return 0;
648
649 /* In CELT_ONLY mode, packets should not have FEC. */
650 if (payload[0] & 0x80)
651 return 0;
652
653 payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
654 if (10 > payload_length_ms)
655 payload_length_ms = 10;
656
657 channels = opus_packet_get_nb_channels(payload);
658
659 switch (payload_length_ms) {
660 case 10:
661 case 20: {
662 frames = 1;
663 break;
664 }
665 case 40: {
666 frames = 2;
667 break;
668 }
669 case 60: {
670 frames = 3;
671 break;
672 }
673 default: {
674 return 0; // It is actually even an invalid packet.
675 }
676 }
677
678 /* The following is to parse the LBRR flags. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700679 if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
680 frame_data, frame_sizes, NULL) < 0) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000681 return 0;
682 }
683
684 if (frame_sizes[0] <= 1) {
685 return 0;
686 }
687
688 for (n = 0; n < channels; n++) {
689 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
690 return 1;
691 }
692
693 return 0;
694}