blob: c657a14a6eb31d70605c2489d8abc9378a5a908b [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 Loiko83ed89a2019-01-17 12:32:11 +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 Loiko83ed89a2019-01-17 12:32:11 +010092 unsigned char mapping[255];
93 memset(mapping, 0, 255);
94 int streams = -1;
95 int coupled_streams = -1;
96
97
minyue3cea2562015-11-10 03:49:26 -080098 OpusEncInst* state = calloc(1, sizeof(OpusEncInst));
kwiberg2e486462016-08-23 05:54:25 -070099 RTC_DCHECK(state);
minyue3cea2562015-11-10 03:49:26 -0800100
minyue3cea2562015-11-10 03:49:26 -0800101 int error;
Alex Loiko83ed89a2019-01-17 12:32:11 +0100102 state->encoder = opus_multistream_surround_encoder_create(
103 48000,
104 channels,
105 /* mapping family */ channels <= 2 ? 0 : 1,
106 &streams,
107 &coupled_streams,
108 mapping,
109 opus_app,
110 &error);
111
minyue3cea2562015-11-10 03:49:26 -0800112 if (error != OPUS_OK || !state->encoder) {
113 WebRtcOpus_EncoderFree(state);
114 return -1;
115 }
116
117 state->in_dtx_mode = 0;
118 state->channels = channels;
119
120 *inst = state;
121 return 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000122}
123
124int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000125 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100126 opus_multistream_encoder_destroy(inst->encoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000127 free(inst);
128 return 0;
129 } else {
130 return -1;
131 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000132}
133
Peter Kastingbba78072015-06-11 19:02:46 -0700134int WebRtcOpus_Encode(OpusEncInst* inst,
135 const int16_t* audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700136 size_t samples,
137 size_t length_encoded_buffer,
Peter Kastingbba78072015-06-11 19:02:46 -0700138 uint8_t* encoded) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000139 int res;
140
141 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
142 return -1;
143 }
144
Alex Loiko83ed89a2019-01-17 12:32:11 +0100145 res = opus_multistream_encode(inst->encoder,
146 (const opus_int16*)audio_in,
147 (int)samples,
148 encoded,
149 (opus_int32)length_encoded_buffer);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000150
flim64a7eab2016-08-12 04:36:05 -0700151 if (res <= 0) {
152 return -1;
153 }
154
155 if (res <= 2) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000156 // Indicates DTX since the packet has nothing but a header. In principle,
157 // there is no need to send this packet. However, we do transmit the first
158 // occurrence to let the decoder know that the encoder enters DTX mode.
159 if (inst->in_dtx_mode) {
160 return 0;
161 } else {
162 inst->in_dtx_mode = 1;
flim92382452017-02-10 13:50:38 -0800163 return res;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000164 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000165 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000166
flim64a7eab2016-08-12 04:36:05 -0700167 inst->in_dtx_mode = 0;
168 return res;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000169}
170
171int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000172 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100173 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000174 } else {
175 return -1;
176 }
177}
178
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000179int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
180 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100181 return opus_multistream_encoder_ctl(inst->encoder,
182 OPUS_SET_PACKET_LOSS_PERC(loss_rate));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000183 } else {
184 return -1;
185 }
186}
187
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000188int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000189 opus_int32 set_bandwidth;
190
191 if (!inst)
192 return -1;
193
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000194 if (frequency_hz <= 8000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000195 set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000196 } else if (frequency_hz <= 12000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000197 set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000198 } else if (frequency_hz <= 16000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000199 set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000200 } else if (frequency_hz <= 24000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000201 set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
202 } else {
203 set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
204 }
Alex Loiko83ed89a2019-01-17 12:32:11 +0100205 return opus_multistream_encoder_ctl(inst->encoder,
206 OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
207}
208
209int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
210 int32_t* result_hz) {
211 opus_int32 max_bandwidth;
212 int s;
213 int ret;
214
215 max_bandwidth = 0;
216 ret = OPUS_OK;
217 s = 0;
218 while (ret == OPUS_OK) {
219 OpusEncoder *enc;
220 opus_int32 bandwidth;
221
222 ret = opus_multistream_encoder_ctl(
223 inst->encoder,
224 OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
225 if (ret == OPUS_BAD_ARG)
226 break;
227 if (ret != OPUS_OK)
228 return -1;
229 if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
230 return -1;
231
232 if (max_bandwidth != 0 && max_bandwidth != bandwidth)
233 return -1;
234
235 max_bandwidth = bandwidth;
236 s++;
237 }
238 *result_hz = max_bandwidth;
239 return 0;
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000240}
241
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000242int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
243 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100244 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(1));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000245 } else {
246 return -1;
247 }
248}
249
250int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
251 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100252 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(0));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000253 } else {
254 return -1;
255 }
256}
257
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000258int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200259 if (!inst) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000260 return -1;
261 }
Minyue Li092041c2015-05-11 12:19:35 +0200262
263 // To prevent Opus from entering CELT-only mode by forcing signal type to
264 // voice to make sure that DTX behaves correctly. Currently, DTX does not
265 // last long during a pure silence, if the signal type is not forced.
266 // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
267 // without it.
Alex Loiko83ed89a2019-01-17 12:32:11 +0100268 int ret = opus_multistream_encoder_ctl(inst->encoder,
269 OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
Minyue Li092041c2015-05-11 12:19:35 +0200270 if (ret != OPUS_OK)
271 return ret;
272
Alex Loiko83ed89a2019-01-17 12:32:11 +0100273 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_DTX(1));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000274}
275
276int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
277 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100278 int ret = opus_multistream_encoder_ctl(inst->encoder,
279 OPUS_SET_SIGNAL(OPUS_AUTO));
Minyue Li092041c2015-05-11 12:19:35 +0200280 if (ret != OPUS_OK)
281 return ret;
Alex Loiko83ed89a2019-01-17 12:32:11 +0100282 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_DTX(0));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000283 } else {
284 return -1;
285 }
286}
287
soren28dc2852017-04-06 05:48:36 -0700288int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
289 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100290 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_VBR(0));
soren28dc2852017-04-06 05:48:36 -0700291 } else {
292 return -1;
293 }
294}
295
296int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
297 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100298 return opus_multistream_encoder_ctl(inst->encoder, OPUS_SET_VBR(1));
soren28dc2852017-04-06 05:48:36 -0700299 } else {
300 return -1;
301 }
302}
303
minyue@webrtc.org04546882014-03-07 08:55:48 +0000304int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
305 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100306 return opus_multistream_encoder_ctl(inst->encoder,
307 OPUS_SET_COMPLEXITY(complexity));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000308 } else {
309 return -1;
310 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000311}
312
Alex Luebseeb27652017-11-20 11:13:56 -0800313int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst) {
314 if (!inst) {
315 return -1;
316 }
317 int32_t bandwidth;
Alex Loiko83ed89a2019-01-17 12:32:11 +0100318 if (opus_multistream_encoder_ctl(inst->encoder,
319 OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
Alex Luebseeb27652017-11-20 11:13:56 -0800320 return bandwidth;
321 } else {
322 return -1;
323 }
324
325}
326
327int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
328 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100329 return opus_multistream_encoder_ctl(inst->encoder,
330 OPUS_SET_BANDWIDTH(bandwidth));
Alex Luebseeb27652017-11-20 11:13:56 -0800331 } else {
332 return -1;
333 }
334}
335
minyue41b9c802016-10-06 07:13:54 -0700336int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
minyuec8299f92016-09-27 02:08:47 -0700337 if (!inst)
338 return -1;
339 if (num_channels == 0) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100340 return opus_multistream_encoder_ctl(inst->encoder,
minyuec8299f92016-09-27 02:08:47 -0700341 OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
342 } else if (num_channels == 1 || num_channels == 2) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100343 return opus_multistream_encoder_ctl(inst->encoder,
minyuec8299f92016-09-27 02:08:47 -0700344 OPUS_SET_FORCE_CHANNELS(num_channels));
345 } else {
346 return -1;
347 }
348}
349
Peter Kasting69558702016-01-12 16:26:35 -0800350int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000351 int error;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000352 OpusDecInst* state;
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000353
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000354 if (inst != NULL) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100355 // Create Opus decoder state.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000356 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
357 if (state == NULL) {
358 return -1;
359 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000360
Alex Loiko83ed89a2019-01-17 12:32:11 +0100361 unsigned char mapping[255];
362 memset(mapping, 0, 255);
363 int streams = -1;
364 int coupled_streams = -1;
365 if (GetSurroundParameters(channels, &streams,
366 &coupled_streams, mapping) != 0) {
367 free(state);
368 return -1;
369 }
370
371 // Create new memory, always at 48000 Hz.
372 state->decoder = opus_multistream_decoder_create(
373 48000, (int)channels,
374 /* streams = */ streams,
375 /* coupled streams = */ coupled_streams,
376 mapping,
377 &error);
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000378 if (error == OPUS_OK && state->decoder != NULL) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100379 // Creation of memory all ok.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000380 state->channels = channels;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000381 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000382 state->in_dtx_mode = 0;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000383 *inst = state;
384 return 0;
385 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000386
Alex Loiko83ed89a2019-01-17 12:32:11 +0100387 // If memory allocation was unsuccessful, free the entire state.
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000388 if (state->decoder) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100389 opus_multistream_decoder_destroy(state->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000390 }
391 free(state);
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000392 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000393 return -1;
394}
395
396int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000397 if (inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100398 opus_multistream_decoder_destroy(inst->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000399 free(inst);
400 return 0;
401 } else {
402 return -1;
403 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000404}
405
Peter Kasting69558702016-01-12 16:26:35 -0800406size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000407 return inst->channels;
408}
409
Karl Wiberg43766482015-08-27 15:22:11 +0200410void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100411 opus_multistream_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
Karl Wiberg43766482015-08-27 15:22:11 +0200412 inst->in_dtx_mode = 0;
tina.legrand@webrtc.org0ad3c1a2012-11-07 08:07:29 +0000413}
414
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000415/* For decoder to determine if it is to output speech or comfort noise. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700416static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000417 // Audio type becomes comfort noise if |encoded_byte| is 1 and keeps
418 // to be so if the following |encoded_byte| are 0 or 1.
419 if (encoded_bytes == 0 && inst->in_dtx_mode) {
420 return 2; // Comfort noise.
henrik.lundindeaf6fb2017-03-01 00:49:18 -0800421 } else if (encoded_bytes == 1 || encoded_bytes == 2) {
422 // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
423 // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
424 // interpreted as comfort noise output, but such a payload is probably
425 // faulty anyway.
Alex Loiko83ed89a2019-01-17 12:32:11 +0100426
427 // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
428 // single-stream packets glued together with some packet size bytes in
429 // between. See https://tools.ietf.org/html/rfc6716#appendix-B
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000430 inst->in_dtx_mode = 1;
431 return 2; // Comfort noise.
432 } else {
433 inst->in_dtx_mode = 0;
434 return 0; // Speech.
435 }
436}
437
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000438/* |frame_size| is set to maximum Opus frame size in the normal case, and
439 * is set to the number of samples needed for PLC in case of losses.
440 * It is up to the caller to make sure the value is correct. */
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000441static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700442 size_t encoded_bytes, int frame_size,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000443 int16_t* decoded, int16_t* audio_type, int decode_fec) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100444 int res = opus_multistream_decode(
445 inst->decoder, encoded, (opus_int32)encoded_bytes,
446 (opus_int16*)decoded, frame_size, decode_fec);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000447
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000448 if (res <= 0)
449 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000450
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000451 *audio_type = DetermineAudioType(inst, encoded_bytes);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000452
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000453 return res;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000454}
455
Peter Kastingbba78072015-06-11 19:02:46 -0700456int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700457 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700458 int16_t* audio_type) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000459 int decoded_samples;
460
461 if (encoded_bytes == 0) {
462 *audio_type = DetermineAudioType(inst, encoded_bytes);
463 decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
464 } else {
465 decoded_samples = DecodeNative(inst,
466 encoded,
467 encoded_bytes,
468 kWebRtcOpusMaxFrameSizePerChannel,
469 decoded,
470 audio_type,
471 0);
472 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000473 if (decoded_samples < 0) {
474 return -1;
475 }
476
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000477 /* Update decoded sample memory, to be used by the PLC in case of losses. */
478 inst->prev_decoded_samples = decoded_samples;
479
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000480 return decoded_samples;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000481}
482
Peter Kastingbba78072015-06-11 19:02:46 -0700483int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
484 int number_of_lost_frames) {
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000485 int16_t audio_type = 0;
486 int decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000487 int plc_samples;
488
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000489 /* The number of samples we ask for is |number_of_lost_frames| times
490 * |prev_decoded_samples_|. Limit the number of samples to maximum
491 * |kWebRtcOpusMaxFrameSizePerChannel|. */
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000492 plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
493 plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
494 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000495 decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
496 decoded, &audio_type, 0);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000497 if (decoded_samples < 0) {
498 return -1;
499 }
500
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000501 return decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000502}
503
Peter Kastingbba78072015-06-11 19:02:46 -0700504int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700505 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700506 int16_t* audio_type) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000507 int decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000508 int fec_samples;
509
510 if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
511 return 0;
512 }
513
514 fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
515
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000516 decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
517 fec_samples, decoded, audio_type, 1);
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000518 if (decoded_samples < 0) {
519 return -1;
520 }
521
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000522 return decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000523}
524
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000525int WebRtcOpus_DurationEst(OpusDecInst* inst,
526 const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700527 size_t payload_length_bytes) {
minyuel6d92bf52015-09-23 15:20:39 +0200528 if (payload_length_bytes == 0) {
529 // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
530 // PLC duration correspondingly.
531 return WebRtcOpus_PlcDuration(inst);
532 }
533
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000534 int frames, samples;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700535 frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000536 if (frames < 0) {
537 /* Invalid payload data. */
538 return 0;
539 }
540 samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
541 if (samples < 120 || samples > 5760) {
542 /* Invalid payload duration. */
543 return 0;
544 }
545 return samples;
546}
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000547
minyuel6d92bf52015-09-23 15:20:39 +0200548int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
549 /* The number of samples we ask for is |number_of_lost_frames| times
550 * |prev_decoded_samples_|. Limit the number of samples to maximum
551 * |kWebRtcOpusMaxFrameSizePerChannel|. */
552 const int plc_samples = inst->prev_decoded_samples;
553 return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
554 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
555}
556
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000557int WebRtcOpus_FecDurationEst(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700558 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000559 int samples;
560 if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
561 return 0;
562 }
563
564 samples = opus_packet_get_samples_per_frame(payload, 48000);
565 if (samples < 480 || samples > 5760) {
566 /* Invalid payload duration. */
567 return 0;
568 }
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000569 return samples;
570}
571
572int WebRtcOpus_PacketHasFec(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700573 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000574 int frames, channels, payload_length_ms;
575 int n;
576 opus_int16 frame_sizes[48];
577 const unsigned char *frame_data[48];
578
Peter Kastingdce40cf2015-08-24 14:52:23 -0700579 if (payload == NULL || payload_length_bytes == 0)
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000580 return 0;
581
582 /* In CELT_ONLY mode, packets should not have FEC. */
583 if (payload[0] & 0x80)
584 return 0;
585
586 payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
587 if (10 > payload_length_ms)
588 payload_length_ms = 10;
589
590 channels = opus_packet_get_nb_channels(payload);
591
592 switch (payload_length_ms) {
593 case 10:
594 case 20: {
595 frames = 1;
596 break;
597 }
598 case 40: {
599 frames = 2;
600 break;
601 }
602 case 60: {
603 frames = 3;
604 break;
605 }
606 default: {
607 return 0; // It is actually even an invalid packet.
608 }
609 }
610
611 /* The following is to parse the LBRR flags. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700612 if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
613 frame_data, frame_sizes, NULL) < 0) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000614 return 0;
615 }
616
617 if (frame_sizes[0] <= 1) {
618 return 0;
619 }
620
621 for (n = 0; n < channels; n++) {
622 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
623 return 1;
624 }
625
626 return 0;
627}