blob: 5166f4cae5b089b41317a359eec7c92fd2b71ae0 [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"
14#include "modules/audio_coding/codecs/opus/opus_inst.h"
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000015
16#include <stdlib.h>
17#include <string.h>
18
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000019enum {
minyue2e03c662017-02-01 17:31:11 -080020#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
21 /* Maximum supported frame size in WebRTC is 120 ms. */
22 kWebRtcOpusMaxEncodeFrameSizeMs = 120,
23#else
tina.legrand@webrtc.org46d90dc2013-02-01 14:20:06 +000024 /* Maximum supported frame size in WebRTC is 60 ms. */
25 kWebRtcOpusMaxEncodeFrameSizeMs = 60,
minyue2e03c662017-02-01 17:31:11 -080026#endif
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000027
tina.legrand@webrtc.org45426ea2013-07-03 13:32:04 +000028 /* The format allows up to 120 ms frames. Since we don't control the other
29 * side, we must allow for packets of that size. NetEq is currently limited
30 * to 60 ms on the receive side. */
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000031 kWebRtcOpusMaxDecodeFrameSizeMs = 120,
32
tina.legrand@webrtc.org45426ea2013-07-03 13:32:04 +000033 /* Maximum sample count per channel is 48 kHz * maximum frame size in
34 * milliseconds. */
35 kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs,
36
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +000037 /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */
38 kWebRtcOpusDefaultFrameSize = 960,
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000039};
40
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000041int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
Peter Kasting69558702016-01-12 16:26:35 -080042 size_t channels,
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000043 int32_t application) {
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
59 OpusEncInst* state = 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;
Peter Kasting69558702016-01-12 16:26:35 -080063 state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
minyue3cea2562015-11-10 03:49:26 -080064 &error);
65 if (error != OPUS_OK || !state->encoder) {
66 WebRtcOpus_EncoderFree(state);
67 return -1;
68 }
69
70 state->in_dtx_mode = 0;
71 state->channels = channels;
72
73 *inst = state;
74 return 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000075}
76
77int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000078 if (inst) {
79 opus_encoder_destroy(inst->encoder);
80 free(inst);
81 return 0;
82 } else {
83 return -1;
84 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000085}
86
Peter Kastingbba78072015-06-11 19:02:46 -070087int WebRtcOpus_Encode(OpusEncInst* inst,
88 const int16_t* audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -070089 size_t samples,
90 size_t length_encoded_buffer,
Peter Kastingbba78072015-06-11 19:02:46 -070091 uint8_t* encoded) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000092 int res;
93
94 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
95 return -1;
96 }
97
kwiberg@webrtc.org4bd2db92014-10-09 11:21:10 +000098 res = opus_encode(inst->encoder,
minyuel7e937e92016-02-29 10:24:15 +010099 (const opus_int16*)audio_in,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700100 (int)samples,
kwiberg@webrtc.org4bd2db92014-10-09 11:21:10 +0000101 encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700102 (opus_int32)length_encoded_buffer);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000103
flim64a7eab2016-08-12 04:36:05 -0700104 if (res <= 0) {
105 return -1;
106 }
107
108 if (res <= 2) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000109 // Indicates DTX since the packet has nothing but a header. In principle,
110 // there is no need to send this packet. However, we do transmit the first
111 // occurrence to let the decoder know that the encoder enters DTX mode.
112 if (inst->in_dtx_mode) {
113 return 0;
114 } else {
115 inst->in_dtx_mode = 1;
flim92382452017-02-10 13:50:38 -0800116 return res;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000117 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000118 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000119
flim64a7eab2016-08-12 04:36:05 -0700120 inst->in_dtx_mode = 0;
121 return res;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000122}
123
124int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000125 if (inst) {
minyue@webrtc.org04546882014-03-07 08:55:48 +0000126 return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
127 } else {
128 return -1;
129 }
130}
131
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000132int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
133 if (inst) {
134 return opus_encoder_ctl(inst->encoder,
135 OPUS_SET_PACKET_LOSS_PERC(loss_rate));
136 } else {
137 return -1;
138 }
139}
140
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000141int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000142 opus_int32 set_bandwidth;
143
144 if (!inst)
145 return -1;
146
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000147 if (frequency_hz <= 8000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000148 set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000149 } else if (frequency_hz <= 12000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000150 set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000151 } else if (frequency_hz <= 16000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000152 set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000153 } else if (frequency_hz <= 24000) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000154 set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
155 } else {
156 set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
157 }
158 return opus_encoder_ctl(inst->encoder,
159 OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
160}
161
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000162int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
163 if (inst) {
164 return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(1));
165 } else {
166 return -1;
167 }
168}
169
170int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
171 if (inst) {
172 return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(0));
173 } else {
174 return -1;
175 }
176}
177
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000178int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200179 if (!inst) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000180 return -1;
181 }
Minyue Li092041c2015-05-11 12:19:35 +0200182
183 // To prevent Opus from entering CELT-only mode by forcing signal type to
184 // voice to make sure that DTX behaves correctly. Currently, DTX does not
185 // last long during a pure silence, if the signal type is not forced.
186 // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
187 // without it.
188 int ret = opus_encoder_ctl(inst->encoder,
189 OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
190 if (ret != OPUS_OK)
191 return ret;
192
193 return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(1));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000194}
195
196int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
197 if (inst) {
Minyue Li092041c2015-05-11 12:19:35 +0200198 int ret = opus_encoder_ctl(inst->encoder,
199 OPUS_SET_SIGNAL(OPUS_AUTO));
200 if (ret != OPUS_OK)
201 return ret;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000202 return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(0));
203 } else {
204 return -1;
205 }
206}
207
soren28dc2852017-04-06 05:48:36 -0700208int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
209 if (inst) {
210 return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(0));
211 } else {
212 return -1;
213 }
214}
215
216int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
217 if (inst) {
218 return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(1));
219 } else {
220 return -1;
221 }
222}
223
minyue@webrtc.org04546882014-03-07 08:55:48 +0000224int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
225 if (inst) {
226 return opus_encoder_ctl(inst->encoder, OPUS_SET_COMPLEXITY(complexity));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000227 } else {
228 return -1;
229 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000230}
231
minyue41b9c802016-10-06 07:13:54 -0700232int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
minyuec8299f92016-09-27 02:08:47 -0700233 if (!inst)
234 return -1;
235 if (num_channels == 0) {
236 return opus_encoder_ctl(inst->encoder,
237 OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
238 } else if (num_channels == 1 || num_channels == 2) {
239 return opus_encoder_ctl(inst->encoder,
240 OPUS_SET_FORCE_CHANNELS(num_channels));
241 } else {
242 return -1;
243 }
244}
245
Peter Kasting69558702016-01-12 16:26:35 -0800246int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000247 int error;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000248 OpusDecInst* state;
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000249
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000250 if (inst != NULL) {
tina.legrand@webrtc.org45426ea2013-07-03 13:32:04 +0000251 /* Create Opus decoder state. */
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000252 state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
253 if (state == NULL) {
254 return -1;
255 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000256
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000257 /* Create new memory, always at 48000 Hz. */
Peter Kasting69558702016-01-12 16:26:35 -0800258 state->decoder = opus_decoder_create(48000, (int)channels, &error);
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000259 if (error == OPUS_OK && state->decoder != NULL) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000260 /* Creation of memory all ok. */
261 state->channels = channels;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000262 state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000263 state->in_dtx_mode = 0;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000264 *inst = state;
265 return 0;
266 }
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000267
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000268 /* If memory allocation was unsuccessful, free the entire state. */
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000269 if (state->decoder) {
270 opus_decoder_destroy(state->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000271 }
272 free(state);
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000273 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000274 return -1;
275}
276
277int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000278 if (inst) {
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000279 opus_decoder_destroy(inst->decoder);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000280 free(inst);
281 return 0;
282 } else {
283 return -1;
284 }
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000285}
286
Peter Kasting69558702016-01-12 16:26:35 -0800287size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
tina.legrand@webrtc.orgc4590582012-11-28 12:23:29 +0000288 return inst->channels;
289}
290
Karl Wiberg43766482015-08-27 15:22:11 +0200291void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
292 opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
293 inst->in_dtx_mode = 0;
tina.legrand@webrtc.org0ad3c1a2012-11-07 08:07:29 +0000294}
295
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000296/* For decoder to determine if it is to output speech or comfort noise. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700297static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000298 // Audio type becomes comfort noise if |encoded_byte| is 1 and keeps
299 // to be so if the following |encoded_byte| are 0 or 1.
300 if (encoded_bytes == 0 && inst->in_dtx_mode) {
301 return 2; // Comfort noise.
henrik.lundindeaf6fb2017-03-01 00:49:18 -0800302 } else if (encoded_bytes == 1 || encoded_bytes == 2) {
303 // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
304 // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
305 // interpreted as comfort noise output, but such a payload is probably
306 // faulty anyway.
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000307 inst->in_dtx_mode = 1;
308 return 2; // Comfort noise.
309 } else {
310 inst->in_dtx_mode = 0;
311 return 0; // Speech.
312 }
313}
314
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000315/* |frame_size| is set to maximum Opus frame size in the normal case, and
316 * is set to the number of samples needed for PLC in case of losses.
317 * It is up to the caller to make sure the value is correct. */
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000318static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700319 size_t encoded_bytes, int frame_size,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000320 int16_t* decoded, int16_t* audio_type, int decode_fec) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700321 int res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000322 (opus_int16*)decoded, frame_size, decode_fec);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000323
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000324 if (res <= 0)
325 return -1;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000326
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000327 *audio_type = DetermineAudioType(inst, encoded_bytes);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000328
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000329 return res;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000330}
331
Peter Kastingbba78072015-06-11 19:02:46 -0700332int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700333 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700334 int16_t* audio_type) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000335 int decoded_samples;
336
337 if (encoded_bytes == 0) {
338 *audio_type = DetermineAudioType(inst, encoded_bytes);
339 decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
340 } else {
341 decoded_samples = DecodeNative(inst,
342 encoded,
343 encoded_bytes,
344 kWebRtcOpusMaxFrameSizePerChannel,
345 decoded,
346 audio_type,
347 0);
348 }
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000349 if (decoded_samples < 0) {
350 return -1;
351 }
352
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000353 /* Update decoded sample memory, to be used by the PLC in case of losses. */
354 inst->prev_decoded_samples = decoded_samples;
355
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000356 return decoded_samples;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000357}
358
Peter Kastingbba78072015-06-11 19:02:46 -0700359int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
360 int number_of_lost_frames) {
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000361 int16_t audio_type = 0;
362 int decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000363 int plc_samples;
364
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000365 /* The number of samples we ask for is |number_of_lost_frames| times
366 * |prev_decoded_samples_|. Limit the number of samples to maximum
367 * |kWebRtcOpusMaxFrameSizePerChannel|. */
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000368 plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
369 plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
370 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000371 decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
372 decoded, &audio_type, 0);
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000373 if (decoded_samples < 0) {
374 return -1;
375 }
376
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000377 return decoded_samples;
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000378}
379
Peter Kastingbba78072015-06-11 19:02:46 -0700380int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700381 size_t encoded_bytes, int16_t* decoded,
Peter Kastingbba78072015-06-11 19:02:46 -0700382 int16_t* audio_type) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000383 int decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000384 int fec_samples;
385
386 if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
387 return 0;
388 }
389
390 fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
391
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000392 decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
393 fec_samples, decoded, audio_type, 1);
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000394 if (decoded_samples < 0) {
395 return -1;
396 }
397
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000398 return decoded_samples;
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000399}
400
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000401int WebRtcOpus_DurationEst(OpusDecInst* inst,
402 const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700403 size_t payload_length_bytes) {
minyuel6d92bf52015-09-23 15:20:39 +0200404 if (payload_length_bytes == 0) {
405 // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
406 // PLC duration correspondingly.
407 return WebRtcOpus_PlcDuration(inst);
408 }
409
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000410 int frames, samples;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700411 frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
tina.legrand@webrtc.org4275ab12012-12-19 09:52:45 +0000412 if (frames < 0) {
413 /* Invalid payload data. */
414 return 0;
415 }
416 samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
417 if (samples < 120 || samples > 5760) {
418 /* Invalid payload duration. */
419 return 0;
420 }
421 return samples;
422}
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000423
minyuel6d92bf52015-09-23 15:20:39 +0200424int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
425 /* The number of samples we ask for is |number_of_lost_frames| times
426 * |prev_decoded_samples_|. Limit the number of samples to maximum
427 * |kWebRtcOpusMaxFrameSizePerChannel|. */
428 const int plc_samples = inst->prev_decoded_samples;
429 return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
430 plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
431}
432
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000433int WebRtcOpus_FecDurationEst(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700434 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000435 int samples;
436 if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
437 return 0;
438 }
439
440 samples = opus_packet_get_samples_per_frame(payload, 48000);
441 if (samples < 480 || samples > 5760) {
442 /* Invalid payload duration. */
443 return 0;
444 }
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000445 return samples;
446}
447
448int WebRtcOpus_PacketHasFec(const uint8_t* payload,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700449 size_t payload_length_bytes) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000450 int frames, channels, payload_length_ms;
451 int n;
452 opus_int16 frame_sizes[48];
453 const unsigned char *frame_data[48];
454
Peter Kastingdce40cf2015-08-24 14:52:23 -0700455 if (payload == NULL || payload_length_bytes == 0)
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000456 return 0;
457
458 /* In CELT_ONLY mode, packets should not have FEC. */
459 if (payload[0] & 0x80)
460 return 0;
461
462 payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
463 if (10 > payload_length_ms)
464 payload_length_ms = 10;
465
466 channels = opus_packet_get_nb_channels(payload);
467
468 switch (payload_length_ms) {
469 case 10:
470 case 20: {
471 frames = 1;
472 break;
473 }
474 case 40: {
475 frames = 2;
476 break;
477 }
478 case 60: {
479 frames = 3;
480 break;
481 }
482 default: {
483 return 0; // It is actually even an invalid packet.
484 }
485 }
486
487 /* The following is to parse the LBRR flags. */
Peter Kastingdce40cf2015-08-24 14:52:23 -0700488 if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
489 frame_data, frame_sizes, NULL) < 0) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000490 return 0;
491 }
492
493 if (frame_sizes[0] <= 1) {
494 return 0;
495 }
496
497 for (n = 0; n < channels; n++) {
498 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
499 return 1;
500 }
501
502 return 0;
503}