diff options
Diffstat (limited to 'lib/rbcodec/codecs/libopus/opus_decoder.c')
-rw-r--r-- | lib/rbcodec/codecs/libopus/opus_decoder.c | 85 |
1 files changed, 47 insertions, 38 deletions
diff --git a/lib/rbcodec/codecs/libopus/opus_decoder.c b/lib/rbcodec/codecs/libopus/opus_decoder.c index 198d168898..5d35ed2675 100644 --- a/lib/rbcodec/codecs/libopus/opus_decoder.c +++ b/lib/rbcodec/codecs/libopus/opus_decoder.c | |||
@@ -77,12 +77,6 @@ struct OpusDecoder { | |||
77 | opus_uint32 rangeFinal; | 77 | opus_uint32 rangeFinal; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | #ifdef FIXED_POINT | ||
81 | static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { | ||
82 | return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x; | ||
83 | } | ||
84 | #endif | ||
85 | |||
86 | 80 | ||
87 | int opus_decoder_get_size(int channels) | 81 | int opus_decoder_get_size(int channels) |
88 | { | 82 | { |
@@ -222,7 +216,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
222 | VARDECL(opus_val16, pcm_transition_silk); | 216 | VARDECL(opus_val16, pcm_transition_silk); |
223 | int pcm_transition_celt_size; | 217 | int pcm_transition_celt_size; |
224 | VARDECL(opus_val16, pcm_transition_celt); | 218 | VARDECL(opus_val16, pcm_transition_celt); |
225 | opus_val16 *pcm_transition = NULL; /* Silence false positive "may be used uninitialized" warning */ | 219 | opus_val16 *pcm_transition=NULL; |
226 | int redundant_audio_size; | 220 | int redundant_audio_size; |
227 | VARDECL(opus_val16, redundant_audio); | 221 | VARDECL(opus_val16, redundant_audio); |
228 | 222 | ||
@@ -237,6 +231,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
237 | int F2_5, F5, F10, F20; | 231 | int F2_5, F5, F10, F20; |
238 | const opus_val16 *window; | 232 | const opus_val16 *window; |
239 | opus_uint32 redundant_rng = 0; | 233 | opus_uint32 redundant_rng = 0; |
234 | int celt_accum; | ||
240 | ALLOC_STACK; | 235 | ALLOC_STACK; |
241 | 236 | ||
242 | silk_dec = (char*)st+st->silk_dec_offset; | 237 | silk_dec = (char*)st+st->silk_dec_offset; |
@@ -302,6 +297,14 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
302 | } | 297 | } |
303 | } | 298 | } |
304 | 299 | ||
300 | /* In fixed-point, we can tell CELT to do the accumulation on top of the | ||
301 | SILK PCM buffer. This saves some stack space. */ | ||
302 | #ifdef FIXED_POINT | ||
303 | celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10); | ||
304 | #else | ||
305 | celt_accum = 0; | ||
306 | #endif | ||
307 | |||
305 | pcm_transition_silk_size = ALLOC_NONE; | 308 | pcm_transition_silk_size = ALLOC_NONE; |
306 | pcm_transition_celt_size = ALLOC_NONE; | 309 | pcm_transition_celt_size = ALLOC_NONE; |
307 | if (data!=NULL && st->prev_mode > 0 && ( | 310 | if (data!=NULL && st->prev_mode > 0 && ( |
@@ -332,14 +335,20 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
332 | } | 335 | } |
333 | 336 | ||
334 | /* Don't allocate any memory when in CELT-only mode */ | 337 | /* Don't allocate any memory when in CELT-only mode */ |
335 | pcm_silk_size = (mode != MODE_CELT_ONLY) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; | 338 | pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; |
336 | ALLOC(pcm_silk, pcm_silk_size, opus_int16); | 339 | ALLOC(pcm_silk, pcm_silk_size, opus_int16); |
337 | 340 | ||
338 | /* SILK processing */ | 341 | /* SILK processing */ |
339 | if (mode != MODE_CELT_ONLY) | 342 | if (mode != MODE_CELT_ONLY) |
340 | { | 343 | { |
341 | int lost_flag, decoded_samples; | 344 | int lost_flag, decoded_samples; |
342 | opus_int16 *pcm_ptr = pcm_silk; | 345 | opus_int16 *pcm_ptr; |
346 | #ifdef FIXED_POINT | ||
347 | if (celt_accum) | ||
348 | pcm_ptr = pcm; | ||
349 | else | ||
350 | #endif | ||
351 | pcm_ptr = pcm_silk; | ||
343 | 352 | ||
344 | if (st->prev_mode==MODE_CELT_ONLY) | 353 | if (st->prev_mode==MODE_CELT_ONLY) |
345 | silk_InitDecoder( silk_dec ); | 354 | silk_InitDecoder( silk_dec ); |
@@ -469,7 +478,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
469 | { | 478 | { |
470 | celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); | 479 | celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); |
471 | celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, | 480 | celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, |
472 | redundant_audio, F5, NULL); | 481 | redundant_audio, F5, NULL, 0); |
473 | celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); | 482 | celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); |
474 | } | 483 | } |
475 | 484 | ||
@@ -484,25 +493,28 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
484 | celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); | 493 | celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); |
485 | /* Decode CELT */ | 494 | /* Decode CELT */ |
486 | celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, | 495 | celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, |
487 | len, pcm, celt_frame_size, &dec); | 496 | len, pcm, celt_frame_size, &dec, celt_accum); |
488 | } else { | 497 | } else { |
489 | unsigned char silence[2] = {0xFF, 0xFF}; | 498 | unsigned char silence[2] = {0xFF, 0xFF}; |
490 | for (i=0;i<frame_size*st->channels;i++) | 499 | if (!celt_accum) |
491 | pcm[i] = 0; | 500 | { |
501 | for (i=0;i<frame_size*st->channels;i++) | ||
502 | pcm[i] = 0; | ||
503 | } | ||
492 | /* For hybrid -> SILK transitions, we let the CELT MDCT | 504 | /* For hybrid -> SILK transitions, we let the CELT MDCT |
493 | do a fade-out by decoding a silence frame */ | 505 | do a fade-out by decoding a silence frame */ |
494 | if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) ) | 506 | if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) ) |
495 | { | 507 | { |
496 | celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); | 508 | celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); |
497 | celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL); | 509 | celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum); |
498 | } | 510 | } |
499 | } | 511 | } |
500 | 512 | ||
501 | if (mode != MODE_CELT_ONLY) | 513 | if (mode != MODE_CELT_ONLY && !celt_accum) |
502 | { | 514 | { |
503 | #ifdef FIXED_POINT | 515 | #ifdef FIXED_POINT |
504 | for (i=0;i<frame_size*st->channels;i++) | 516 | for (i=0;i<frame_size*st->channels;i++) |
505 | pcm[i] = SAT16(pcm[i] + pcm_silk[i]); | 517 | pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i])); |
506 | #else | 518 | #else |
507 | for (i=0;i<frame_size*st->channels;i++) | 519 | for (i=0;i<frame_size*st->channels;i++) |
508 | pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); | 520 | pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); |
@@ -521,7 +533,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
521 | celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); | 533 | celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); |
522 | celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); | 534 | celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); |
523 | 535 | ||
524 | celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL); | 536 | celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0); |
525 | celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); | 537 | celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); |
526 | smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5, | 538 | smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5, |
527 | pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs); | 539 | pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs); |
@@ -717,6 +729,7 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data, | |||
717 | { | 729 | { |
718 | VARDECL(opus_int16, out); | 730 | VARDECL(opus_int16, out); |
719 | int ret, i; | 731 | int ret, i; |
732 | int nb_samples; | ||
720 | ALLOC_STACK; | 733 | ALLOC_STACK; |
721 | 734 | ||
722 | if(frame_size<=0) | 735 | if(frame_size<=0) |
@@ -724,6 +737,14 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data, | |||
724 | RESTORE_STACK; | 737 | RESTORE_STACK; |
725 | return OPUS_BAD_ARG; | 738 | return OPUS_BAD_ARG; |
726 | } | 739 | } |
740 | if (data != NULL && len > 0 && !decode_fec) | ||
741 | { | ||
742 | nb_samples = opus_decoder_get_nb_samples(st, data, len); | ||
743 | if (nb_samples>0) | ||
744 | frame_size = IMIN(frame_size, nb_samples); | ||
745 | else | ||
746 | return OPUS_INVALID_PACKET; | ||
747 | } | ||
727 | ALLOC(out, frame_size*st->channels, opus_int16); | 748 | ALLOC(out, frame_size*st->channels, opus_int16); |
728 | 749 | ||
729 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); | 750 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); |
@@ -744,6 +765,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, | |||
744 | { | 765 | { |
745 | VARDECL(float, out); | 766 | VARDECL(float, out); |
746 | int ret, i; | 767 | int ret, i; |
768 | int nb_samples; | ||
747 | ALLOC_STACK; | 769 | ALLOC_STACK; |
748 | 770 | ||
749 | if(frame_size<=0) | 771 | if(frame_size<=0) |
@@ -752,6 +774,14 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, | |||
752 | return OPUS_BAD_ARG; | 774 | return OPUS_BAD_ARG; |
753 | } | 775 | } |
754 | 776 | ||
777 | if (data != NULL && len > 0 && !decode_fec) | ||
778 | { | ||
779 | nb_samples = opus_decoder_get_nb_samples(st, data, len); | ||
780 | if (nb_samples>0) | ||
781 | frame_size = IMIN(frame_size, nb_samples); | ||
782 | else | ||
783 | return OPUS_INVALID_PACKET; | ||
784 | } | ||
755 | ALLOC(out, frame_size*st->channels, float); | 785 | ALLOC(out, frame_size*st->channels, float); |
756 | 786 | ||
757 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); | 787 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); |
@@ -911,27 +941,6 @@ int opus_packet_get_bandwidth(const unsigned char *data) | |||
911 | return bandwidth; | 941 | return bandwidth; |
912 | } | 942 | } |
913 | 943 | ||
914 | int opus_packet_get_samples_per_frame(const unsigned char *data, | ||
915 | opus_int32 Fs) | ||
916 | { | ||
917 | int audiosize; | ||
918 | if (data[0]&0x80) | ||
919 | { | ||
920 | audiosize = ((data[0]>>3)&0x3); | ||
921 | audiosize = (Fs<<audiosize)/400; | ||
922 | } else if ((data[0]&0x60) == 0x60) | ||
923 | { | ||
924 | audiosize = (data[0]&0x08) ? Fs/50 : Fs/100; | ||
925 | } else { | ||
926 | audiosize = ((data[0]>>3)&0x3); | ||
927 | if (audiosize == 3) | ||
928 | audiosize = Fs*60/1000; | ||
929 | else | ||
930 | audiosize = (Fs<<audiosize)/100; | ||
931 | } | ||
932 | return audiosize; | ||
933 | } | ||
934 | |||
935 | int opus_packet_get_nb_channels(const unsigned char *data) | 944 | int opus_packet_get_nb_channels(const unsigned char *data) |
936 | { | 945 | { |
937 | return (data[0]&0x4) ? 2 : 1; | 946 | return (data[0]&0x4) ? 2 : 1; |