blob: d219098b0122433e12863241a5e996f48edb2d31 [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
58 OpusEncInst* state = 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;
Amit Hilbuch1fa51d62019-01-17 22:38:48 +000062 state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
63 &error);
minyue3cea2562015-11-10 03:49:26 -080064 if (error != OPUS_OK || !state->encoder) {
65 WebRtcOpus_EncoderFree(state);
66 return -1;
67 }
68
69 state->in_dtx_mode = 0;
70 state->channels = channels;
71
72 *inst = state;
73 return 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000074}
75
76int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000077 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +000078 opus_encoder_destroy(inst->encoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000079 free(inst);
80 return 0;
81 } else {
82 return -1;
83 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000084}
85
Peter Kastingbba78072015-06-11 19:02:46 -070086int WebRtcOpus_Encode(OpusEncInst* inst,
87 const int16_t* audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -070088 size_t samples,
89 size_t length_encoded_buffer,
Peter Kastingbba78072015-06-11 19:02:46 -070090 uint8_t* encoded) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000091 int res;
92
93 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
94 return -1;
95 }
96
Amit Hilbuch1fa51d62019-01-17 22:38:48 +000097 res = opus_encode(inst->encoder,
98 (const opus_int16*)audio_in,
99 (int)samples,
100 encoded,
101 (opus_int32)length_encoded_buffer);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000102
flim64a7eab2016-08-12 04:36:05 -0700103 if (res <= 0) {
104 return -1;
105 }
106
107 if (res <= 2) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000108 // Indicates DTX since the packet has nothing but a header. In principle,
109 // there is no need to send this packet. However, we do transmit the first
110 // occurrence to let the decoder know that the encoder enters DTX mode.
111 if (inst->in_dtx_mode) {
112 return 0;
113 } else {
114 inst->in_dtx_mode = 1;
flim92382452017-02-10 13:50:38 -0800115 return res;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000116 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000117 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000118
flim64a7eab2016-08-12 04:36:05 -0700119 inst->in_dtx_mode = 0;
120 return res;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000121}
122
123int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000124 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000125 return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000126 } else {
127 return -1;
128 }
129}
130
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000131int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
132 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000133 return opus_encoder_ctl(inst->encoder,
134 OPUS_SET_PACKET_LOSS_PERC(loss_rate));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000135 } else {
136 return -1;
137 }
138}
139
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000140int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000141 opus_int32 set_bandwidth;
142
143 if (!inst)
144 return -1;
145
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000146 if (frequency_hz <= 8000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000147 set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000148 } else if (frequency_hz <= 12000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000149 set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000150 } else if (frequency_hz <= 16000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000151 set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000152 } else if (frequency_hz <= 24000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000153 set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
154 } else {
155 set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
156 }
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000157 return opus_encoder_ctl(inst->encoder,
158 OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000159}
160
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000161int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
162 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000163 return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(1));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000164 } else {
165 return -1;
166 }
167}
168
169int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
170 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000171 return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(0));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000172 } else {
173 return -1;
174 }
175}
176
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000177int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200178 if (!inst) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000179 return -1;
180 }
Minyue Li092041c2015-05-11 12:19:35 +0200181
182 // To prevent Opus from entering CELT-only mode by forcing signal type to
183 // voice to make sure that DTX behaves correctly. Currently, DTX does not
184 // last long during a pure silence, if the signal type is not forced.
185 // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
186 // without it.
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000187 int ret = opus_encoder_ctl(inst->encoder,
188 OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
Minyue Li092041c2015-05-11 12:19:35 +0200189 if (ret != OPUS_OK)
190 return ret;
191
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000192 return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(1));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000193}
194
195int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
196 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000197 int ret = opus_encoder_ctl(inst->encoder,
198 OPUS_SET_SIGNAL(OPUS_AUTO));
Minyue Li092041c2015-05-11 12:19:35 +0200199 if (ret != OPUS_OK)
200 return ret;
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000201 return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(0));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000202 } else {
203 return -1;
204 }
205}
206
soren28dc2852017-04-06 05:48:36 -0700207int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
208 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000209 return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(0));
soren28dc2852017-04-06 05:48:36 -0700210 } else {
211 return -1;
212 }
213}
214
215int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
216 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000217 return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(1));
soren28dc2852017-04-06 05:48:36 -0700218 } else {
219 return -1;
220 }
221}
222
minyue@webrtc.org04546882014-03-07 08:55:48 +0000223int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
224 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000225 return opus_encoder_ctl(inst->encoder, OPUS_SET_COMPLEXITY(complexity));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000226 } else {
227 return -1;
228 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000229}
230
Alex Luebseeb27652017-11-20 11:13:56 -0800231int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst) {
232 if (!inst) {
233 return -1;
234 }
235 int32_t bandwidth;
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000236 if (opus_encoder_ctl(inst->encoder, OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
Alex Luebseeb27652017-11-20 11:13:56 -0800237 return bandwidth;
238 } else {
239 return -1;
240 }
241
242}
243
244int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
245 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000246 return opus_encoder_ctl(inst->encoder, OPUS_SET_BANDWIDTH(bandwidth));
Alex Luebseeb27652017-11-20 11:13:56 -0800247 } else {
248 return -1;
249 }
250}
251
minyue41b9c802016-10-06 07:13:54 -0700252int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
minyuec8299f92016-09-27 02:08:47 -0700253 if (!inst)
254 return -1;
255 if (num_channels == 0) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000256 return opus_encoder_ctl(inst->encoder,
minyuec8299f92016-09-27 02:08:47 -0700257 OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
258 } else if (num_channels == 1 || num_channels == 2) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000259 return opus_encoder_ctl(inst->encoder,
minyuec8299f92016-09-27 02:08:47 -0700260 OPUS_SET_FORCE_CHANNELS(num_channels));
261 } else {
262 return -1;
263 }
264}
265
Peter Kasting69558702016-01-12 16:26:35 -0800266int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000267 int error;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000268 OpusDecInst* state;
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000269
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000270 if (inst != NULL) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000271 /* Create Opus decoder state. */
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000272 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
273 if (state == NULL) {
274 return -1;
275 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000276
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000277 /* Create new memory, always at 48000 Hz. */
278 state->decoder = opus_decoder_create(48000, (int)channels, &error);
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000279 if (error == OPUS_OK && state->decoder != NULL) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000280 /* Creation of memory all ok. */
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000281 state->channels = channels;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000282 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000283 state->in_dtx_mode = 0;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000284 *inst = state;
285 return 0;
286 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000287
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000288 /* If memory allocation was unsuccessful, free the entire state. */
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000289 if (state->decoder) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000290 opus_decoder_destroy(state->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000291 }
292 free(state);
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000293 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000294 return -1;
295}
296
297int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000298 if (inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000299 opus_decoder_destroy(inst->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000300 free(inst);
301 return 0;
302 } else {
303 return -1;
304 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000305}
306
Peter Kasting69558702016-01-12 16:26:35 -0800307size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000308 return inst->channels;
309}
310
Karl Wiberg43766482015-08-27 15:22:11 +0200311void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000312 opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
Karl Wiberg43766482015-08-27 15:22:11 +0200313 inst->in_dtx_mode = 0;
tina.legrand@webrtc.org0ad3c1a2012-11-07 08:07:29 +0000314}
315
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000316/* For decoder to determine if it is to output speech or comfort noise. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700317static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000318 // Audio type becomes comfort noise if |encoded_byte| is 1 and keeps
319 // to be so if the following |encoded_byte| are 0 or 1.
320 if (encoded_bytes == 0 && inst->in_dtx_mode) {
321 return 2; // Comfort noise.
henrik.lundindeaf6fb2017-03-01 00:49:18 -0800322 } else if (encoded_bytes == 1 || encoded_bytes == 2) {
323 // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
324 // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
325 // interpreted as comfort noise output, but such a payload is probably
326 // faulty anyway.
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000327 inst->in_dtx_mode = 1;
328 return 2; // Comfort noise.
329 } else {
330 inst->in_dtx_mode = 0;
331 return 0; // Speech.
332 }
333}
334
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000335/* |frame_size| is set to maximum Opus frame size in the normal case, and
336 * is set to the number of samples needed for PLC in case of losses.
337 * It is up to the caller to make sure the value is correct. */
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000338static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700339 size_t encoded_bytes, int frame_size,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000340 int16_t* decoded, int16_t* audio_type, int decode_fec) {
Amit Hilbuch1fa51d62019-01-17 22:38:48 +0000341 int res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
342 (opus_int16*)decoded, frame_size, decode_fec);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000343
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000344 if (res <= 0)
345 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000346
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000347 *audio_type = DetermineAudioType(inst, encoded_bytes);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000348
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000349 return res;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000350}
351
Peter Kastingbba78072015-06-11 19:02:46 -0700352int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700353 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700354 int16_t* audio_type) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000355 int decoded_samples;
356
357 if (encoded_bytes == 0) {
358 *audio_type = DetermineAudioType(inst, encoded_bytes);
359 decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
360 } else {
361 decoded_samples = DecodeNative(inst,
362 encoded,
363 encoded_bytes,
364 kWebRtcOpusMaxFrameSizePerChannel,
365 decoded,
366 audio_type,
367 0);
368 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000369 if (decoded_samples < 0) {
370 return -1;
371 }
372
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000373 /* Update decoded sample memory, to be used by the PLC in case of losses. */
374 inst->prev_decoded_samples = decoded_samples;
375
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000376 return decoded_samples;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000377}
378
Peter Kastingbba78072015-06-11 19:02:46 -0700379int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
380 int number_of_lost_frames) {
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000381 int16_t audio_type = 0;
382 int decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000383 int plc_samples;
384
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000385 /* The number of samples we ask for is |number_of_lost_frames| times
386 * |prev_decoded_samples_|. Limit the number of samples to maximum
387 * |kWebRtcOpusMaxFrameSizePerChannel|. */
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000388 plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
389 plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
390 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000391 decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
392 decoded, &audio_type, 0);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000393 if (decoded_samples < 0) {
394 return -1;
395 }
396
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000397 return decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000398}
399
Peter Kastingbba78072015-06-11 19:02:46 -0700400int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700401 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700402 int16_t* audio_type) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000403 int decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000404 int fec_samples;
405
406 if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
407 return 0;
408 }
409
410 fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
411
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000412 decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
413 fec_samples, decoded, audio_type, 1);
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000414 if (decoded_samples < 0) {
415 return -1;
416 }
417
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000418 return decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000419}
420
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000421int WebRtcOpus_DurationEst(OpusDecInst* inst,
422 const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700423 size_t payload_length_bytes) {
minyuel6d92bf52015-09-23 15:20:39 +0200424 if (payload_length_bytes == 0) {
425 // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
426 // PLC duration correspondingly.
427 return WebRtcOpus_PlcDuration(inst);
428 }
429
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000430 int frames, samples;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700431 frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000432 if (frames < 0) {
433 /* Invalid payload data. */
434 return 0;
435 }
436 samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
437 if (samples < 120 || samples > 5760) {
438 /* Invalid payload duration. */
439 return 0;
440 }
441 return samples;
442}
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000443
minyuel6d92bf52015-09-23 15:20:39 +0200444int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
445 /* The number of samples we ask for is |number_of_lost_frames| times
446 * |prev_decoded_samples_|. Limit the number of samples to maximum
447 * |kWebRtcOpusMaxFrameSizePerChannel|. */
448 const int plc_samples = inst->prev_decoded_samples;
449 return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
450 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
451}
452
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000453int WebRtcOpus_FecDurationEst(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700454 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000455 int samples;
456 if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
457 return 0;
458 }
459
460 samples = opus_packet_get_samples_per_frame(payload, 48000);
461 if (samples < 480 || samples > 5760) {
462 /* Invalid payload duration. */
463 return 0;
464 }
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000465 return samples;
466}
467
468int WebRtcOpus_PacketHasFec(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700469 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000470 int frames, channels, payload_length_ms;
471 int n;
472 opus_int16 frame_sizes[48];
473 const unsigned char *frame_data[48];
474
Peter Kastingdce40cf2015-08-24 14:52:23 -0700475 if (payload == NULL || payload_length_bytes == 0)
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000476 return 0;
477
478 /* In CELT_ONLY mode, packets should not have FEC. */
479 if (payload[0] & 0x80)
480 return 0;
481
482 payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
483 if (10 > payload_length_ms)
484 payload_length_ms = 10;
485
486 channels = opus_packet_get_nb_channels(payload);
487
488 switch (payload_length_ms) {
489 case 10:
490 case 20: {
491 frames = 1;
492 break;
493 }
494 case 40: {
495 frames = 2;
496 break;
497 }
498 case 60: {
499 frames = 3;
500 break;
501 }
502 default: {
503 return 0; // It is actually even an invalid packet.
504 }
505 }
506
507 /* The following is to parse the LBRR flags. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700508 if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
509 frame_data, frame_sizes, NULL) < 0) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000510 return 0;
511 }
512
513 if (frame_sizes[0] <= 1) {
514 return 0;
515 }
516
517 for (n = 0; n < channels; n++) {
518 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
519 return 1;
520 }
521
522 return 0;
523}