diff options
author | Nils Wallménius <nils@rockbox.org> | 2013-05-20 22:25:57 +0200 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2013-08-31 08:30:51 +0200 |
commit | 580b307fd791c0997a8831bc800bba87797bfb7e (patch) | |
tree | 807846056f06fd944a750ce41217a877910ebd59 /lib/rbcodec/codecs/libopus/opus_decoder.c | |
parent | 74761b70acd96cecc0d35450dd56a98ad9ee7d3d (diff) | |
download | rockbox-580b307fd791c0997a8831bc800bba87797bfb7e.tar.gz rockbox-580b307fd791c0997a8831bc800bba87797bfb7e.zip |
Sync opus codec to upstream git
Sync opus codec to upstream commit
02fed471a4568852d6618e041c4f2af0d7730ee2 (August 30 2013)
This brings in a lot of optimizations but also makes the diff
between our codec and the upstream much smaller as most of our
optimizations have been upstreamed or supeceded.
Speedups across the board for CELT mode files:
64kbps 128kbps
H300 9.82MHz 15.48MHz
c200 4.86MHz 9.63MHz
fuze v1 10.32MHz 15.92MHz
For the silk mode test file (16kbps) arm targets get a speedup
of about 2MHz while the H300 is 7.8MHz slower, likely because it's
now using the pseudostack more rather than the real stack which
is in iram. Patches to get around that are upcomming.
Change-Id: Ifecf963e461c51ac42e09dac1e91bc4bc3b12fa3
Diffstat (limited to 'lib/rbcodec/codecs/libopus/opus_decoder.c')
-rw-r--r-- | lib/rbcodec/codecs/libopus/opus_decoder.c | 259 |
1 files changed, 191 insertions, 68 deletions
diff --git a/lib/rbcodec/codecs/libopus/opus_decoder.c b/lib/rbcodec/codecs/libopus/opus_decoder.c index 3d42bb2e70..b430a4df07 100644 --- a/lib/rbcodec/codecs/libopus/opus_decoder.c +++ b/lib/rbcodec/codecs/libopus/opus_decoder.c | |||
@@ -26,11 +26,11 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #ifdef HAVE_CONFIG_H | 28 | #ifdef HAVE_CONFIG_H |
29 | #include "opus_config.h" | 29 | #include "config.h" |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #ifndef OPUS_BUILD | 32 | #ifndef OPUS_BUILD |
33 | #error "OPUS_BUILD _MUST_ be defined to build Opus and you probably want a decent config.h, see README for more details." | 33 | #error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details." |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #include <stdarg.h> | 36 | #include <stdarg.h> |
@@ -46,6 +46,7 @@ | |||
46 | #include "structs.h" | 46 | #include "structs.h" |
47 | #include "define.h" | 47 | #include "define.h" |
48 | #include "mathops.h" | 48 | #include "mathops.h" |
49 | #include "cpu_support.h" | ||
49 | 50 | ||
50 | struct OpusDecoder { | 51 | struct OpusDecoder { |
51 | int celt_dec_offset; | 52 | int celt_dec_offset; |
@@ -64,8 +65,13 @@ struct OpusDecoder { | |||
64 | int prev_mode; | 65 | int prev_mode; |
65 | int frame_size; | 66 | int frame_size; |
66 | int prev_redundancy; | 67 | int prev_redundancy; |
68 | int last_packet_duration; | ||
69 | #ifndef FIXED_POINT | ||
70 | opus_val16 softclip_mem[2]; | ||
71 | #endif | ||
67 | 72 | ||
68 | opus_uint32 rangeFinal; | 73 | opus_uint32 rangeFinal; |
74 | int arch; | ||
69 | }; | 75 | }; |
70 | 76 | ||
71 | #ifdef FIXED_POINT | 77 | #ifdef FIXED_POINT |
@@ -115,6 +121,7 @@ int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels) | |||
115 | st->Fs = Fs; | 121 | st->Fs = Fs; |
116 | st->DecControl.API_sampleRate = st->Fs; | 122 | st->DecControl.API_sampleRate = st->Fs; |
117 | st->DecControl.nChannelsAPI = st->channels; | 123 | st->DecControl.nChannelsAPI = st->channels; |
124 | st->arch = opus_select_arch(); | ||
118 | 125 | ||
119 | /* Reset decoder */ | 126 | /* Reset decoder */ |
120 | ret = silk_InitDecoder( silk_dec ); | 127 | ret = silk_InitDecoder( silk_dec ); |
@@ -131,7 +138,7 @@ int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels) | |||
131 | return OPUS_OK; | 138 | return OPUS_OK; |
132 | } | 139 | } |
133 | 140 | ||
134 | #define STATIC_DECODER_SIZE 26532 /* 26486 for 32bit, 26532 for 64bit environment */ | 141 | #define STATIC_DECODER_SIZE 26540 /* 26540 for 64bit environment */ |
135 | static char s_dec[STATIC_DECODER_SIZE] IBSS_ATTR MEM_ALIGN_ATTR; | 142 | static char s_dec[STATIC_DECODER_SIZE] IBSS_ATTR MEM_ALIGN_ATTR; |
136 | 143 | ||
137 | OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error) | 144 | OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error) |
@@ -208,8 +215,14 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
208 | int i, silk_ret=0, celt_ret=0; | 215 | int i, silk_ret=0, celt_ret=0; |
209 | ec_dec dec; | 216 | ec_dec dec; |
210 | opus_int32 silk_frame_size; | 217 | opus_int32 silk_frame_size; |
218 | int pcm_silk_size; | ||
211 | VARDECL(opus_int16, pcm_silk); | 219 | VARDECL(opus_int16, pcm_silk); |
212 | VARDECL(opus_val16, pcm_transition); | 220 | int pcm_transition_silk_size; |
221 | VARDECL(opus_val16, pcm_transition_silk); | ||
222 | int pcm_transition_celt_size; | ||
223 | VARDECL(opus_val16, pcm_transition_celt); | ||
224 | opus_val16 *pcm_transition = NULL; /* Silence false positive "may be used uninitialized" warning */ | ||
225 | int redundant_audio_size; | ||
213 | VARDECL(opus_val16, redundant_audio); | 226 | VARDECL(opus_val16, redundant_audio); |
214 | 227 | ||
215 | int audiosize; | 228 | int audiosize; |
@@ -265,33 +278,30 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
265 | } | 278 | } |
266 | } | 279 | } |
267 | 280 | ||
268 | /* For CELT/hybrid PLC of more than 20 ms, do multiple calls */ | 281 | /* For CELT/hybrid PLC of more than 20 ms, opus_decode_native() will do |
269 | if (data==NULL && frame_size > F20 && mode != MODE_SILK_ONLY) | 282 | multiple calls */ |
270 | { | 283 | if (data==NULL && mode != MODE_SILK_ONLY) |
271 | int nb_samples = 0; | 284 | frame_size = IMIN(frame_size, F20); |
272 | do { | ||
273 | int ret = opus_decode_frame(st, NULL, 0, pcm, F20, 0); | ||
274 | if (ret != F20) | ||
275 | { | ||
276 | RESTORE_STACK; | ||
277 | return OPUS_INTERNAL_ERROR; | ||
278 | } | ||
279 | pcm += F20*st->channels; | ||
280 | nb_samples += F20; | ||
281 | } while (nb_samples < frame_size); | ||
282 | RESTORE_STACK; | ||
283 | return frame_size; | ||
284 | } | ||
285 | ALLOC(pcm_transition, F5*st->channels, opus_val16); | ||
286 | 285 | ||
286 | pcm_transition_silk_size = 0; | ||
287 | pcm_transition_celt_size = 0; | ||
287 | if (data!=NULL && st->prev_mode > 0 && ( | 288 | if (data!=NULL && st->prev_mode > 0 && ( |
288 | (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy) | 289 | (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy) |
289 | || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ) | 290 | || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ) |
290 | ) | 291 | ) |
291 | { | 292 | { |
292 | transition = 1; | 293 | transition = 1; |
294 | /* Decide where to allocate the stack memory for pcm_transition */ | ||
293 | if (mode == MODE_CELT_ONLY) | 295 | if (mode == MODE_CELT_ONLY) |
294 | opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); | 296 | pcm_transition_celt_size = F5*st->channels; |
297 | else | ||
298 | pcm_transition_silk_size = F5*st->channels; | ||
299 | } | ||
300 | ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16); | ||
301 | if (transition && mode == MODE_CELT_ONLY) | ||
302 | { | ||
303 | pcm_transition = pcm_transition_celt; | ||
304 | opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); | ||
295 | } | 305 | } |
296 | if (audiosize > frame_size) | 306 | if (audiosize > frame_size) |
297 | { | 307 | { |
@@ -302,8 +312,9 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
302 | frame_size = audiosize; | 312 | frame_size = audiosize; |
303 | } | 313 | } |
304 | 314 | ||
305 | ALLOC(pcm_silk, IMAX(F10, frame_size)*st->channels, opus_int16); | 315 | /* Don't allocate any memory when in CELT-only mode */ |
306 | ALLOC(redundant_audio, F5*st->channels, opus_val16); | 316 | pcm_silk_size = (mode != MODE_CELT_ONLY) ? IMAX(F10, frame_size)*st->channels : 0; |
317 | ALLOC(pcm_silk, pcm_silk_size, opus_int16); | ||
307 | 318 | ||
308 | /* SILK processing */ | 319 | /* SILK processing */ |
309 | if (mode != MODE_CELT_ONLY) | 320 | if (mode != MODE_CELT_ONLY) |
@@ -417,10 +428,22 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
417 | } | 428 | } |
418 | 429 | ||
419 | if (redundancy) | 430 | if (redundancy) |
431 | { | ||
420 | transition = 0; | 432 | transition = 0; |
433 | pcm_transition_silk_size=0; | ||
434 | } | ||
435 | |||
436 | ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); | ||
421 | 437 | ||
422 | if (transition && mode != MODE_CELT_ONLY) | 438 | if (transition && mode != MODE_CELT_ONLY) |
439 | { | ||
440 | pcm_transition = pcm_transition_silk; | ||
423 | opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); | 441 | opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); |
442 | } | ||
443 | |||
444 | /* Only allocation memory for redundancy if/when needed */ | ||
445 | redundant_audio_size = redundancy ? F5*st->channels : 0; | ||
446 | ALLOC(redundant_audio, redundant_audio_size, opus_val16); | ||
424 | 447 | ||
425 | /* 5 ms redundant frame for CELT->SILK*/ | 448 | /* 5 ms redundant frame for CELT->SILK*/ |
426 | if (redundancy && celt_to_silk) | 449 | if (redundancy && celt_to_silk) |
@@ -534,12 +557,19 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, | |||
534 | 557 | ||
535 | st->prev_mode = mode; | 558 | st->prev_mode = mode; |
536 | st->prev_redundancy = redundancy && !celt_to_silk; | 559 | st->prev_redundancy = redundancy && !celt_to_silk; |
560 | |||
561 | if (celt_ret>=0) | ||
562 | { | ||
563 | if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels)) | ||
564 | OPUS_PRINT_INT(audiosize); | ||
565 | } | ||
566 | |||
537 | RESTORE_STACK; | 567 | RESTORE_STACK; |
538 | return celt_ret < 0 ? celt_ret : audiosize; | 568 | return celt_ret < 0 ? celt_ret : audiosize; |
539 | 569 | ||
540 | } | 570 | } |
541 | 571 | ||
542 | static int parse_size(const unsigned char *data, opus_int32 len, short *size) | 572 | static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) |
543 | { | 573 | { |
544 | if (len<1) | 574 | if (len<1) |
545 | { | 575 | { |
@@ -561,14 +591,14 @@ static int parse_size(const unsigned char *data, opus_int32 len, short *size) | |||
561 | 591 | ||
562 | static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, | 592 | static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, |
563 | int self_delimited, unsigned char *out_toc, | 593 | int self_delimited, unsigned char *out_toc, |
564 | const unsigned char *frames[48], short size[48], int *payload_offset) | 594 | const unsigned char *frames[48], opus_int16 size[48], int *payload_offset) |
565 | { | 595 | { |
566 | int i, bytes; | 596 | int i, bytes; |
567 | int count; | 597 | int count; |
568 | int cbr; | 598 | int cbr; |
569 | unsigned char ch, toc; | 599 | unsigned char ch, toc; |
570 | int framesize; | 600 | int framesize; |
571 | int last_size; | 601 | opus_int32 last_size; |
572 | const unsigned char *data0 = data; | 602 | const unsigned char *data0 = data; |
573 | 603 | ||
574 | if (size==NULL) | 604 | if (size==NULL) |
@@ -594,7 +624,9 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, | |||
594 | { | 624 | { |
595 | if (len&0x1) | 625 | if (len&0x1) |
596 | return OPUS_INVALID_PACKET; | 626 | return OPUS_INVALID_PACKET; |
597 | size[0] = last_size = len/2; | 627 | last_size = len/2; |
628 | /* If last_size doesn't fit in size[0], we'll catch it later */ | ||
629 | size[0] = (opus_int16)last_size; | ||
598 | } | 630 | } |
599 | break; | 631 | break; |
600 | /* Two VBR frames */ | 632 | /* Two VBR frames */ |
@@ -620,16 +652,14 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, | |||
620 | /* Padding flag is bit 6 */ | 652 | /* Padding flag is bit 6 */ |
621 | if (ch&0x40) | 653 | if (ch&0x40) |
622 | { | 654 | { |
623 | int padding=0; | ||
624 | int p; | 655 | int p; |
625 | do { | 656 | do { |
626 | if (len<=0) | 657 | if (len<=0) |
627 | return OPUS_INVALID_PACKET; | 658 | return OPUS_INVALID_PACKET; |
628 | p = *data++; | 659 | p = *data++; |
629 | len--; | 660 | len--; |
630 | padding += p==255 ? 254: p; | 661 | len -= p==255 ? 254: p; |
631 | } while (p==255); | 662 | } while (p==255); |
632 | len -= padding; | ||
633 | } | 663 | } |
634 | if (len<0) | 664 | if (len<0) |
635 | return OPUS_INVALID_PACKET; | 665 | return OPUS_INVALID_PACKET; |
@@ -657,7 +687,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, | |||
657 | if (last_size*count!=len) | 687 | if (last_size*count!=len) |
658 | return OPUS_INVALID_PACKET; | 688 | return OPUS_INVALID_PACKET; |
659 | for (i=0;i<count-1;i++) | 689 | for (i=0;i<count-1;i++) |
660 | size[i] = last_size; | 690 | size[i] = (opus_int16)last_size; |
661 | } | 691 | } |
662 | break; | 692 | break; |
663 | } | 693 | } |
@@ -685,7 +715,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, | |||
685 | 1275. Reject them here.*/ | 715 | 1275. Reject them here.*/ |
686 | if (last_size > 1275) | 716 | if (last_size > 1275) |
687 | return OPUS_INVALID_PACKET; | 717 | return OPUS_INVALID_PACKET; |
688 | size[count-1] = last_size; | 718 | size[count-1] = (opus_int16)last_size; |
689 | } | 719 | } |
690 | 720 | ||
691 | if (frames) | 721 | if (frames) |
@@ -701,14 +731,14 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, | |||
701 | *out_toc = toc; | 731 | *out_toc = toc; |
702 | 732 | ||
703 | if (payload_offset) | 733 | if (payload_offset) |
704 | *payload_offset = data-data0; | 734 | *payload_offset = (int)(data-data0); |
705 | 735 | ||
706 | return count; | 736 | return count; |
707 | } | 737 | } |
708 | 738 | ||
709 | int opus_packet_parse(const unsigned char *data, opus_int32 len, | 739 | int opus_packet_parse(const unsigned char *data, opus_int32 len, |
710 | unsigned char *out_toc, const unsigned char *frames[48], | 740 | unsigned char *out_toc, const unsigned char *frames[48], |
711 | short size[48], int *payload_offset) | 741 | opus_int16 size[48], int *payload_offset) |
712 | { | 742 | { |
713 | return opus_packet_parse_impl(data, len, 0, out_toc, | 743 | return opus_packet_parse_impl(data, len, 0, out_toc, |
714 | frames, size, payload_offset); | 744 | frames, size, payload_offset); |
@@ -716,50 +746,120 @@ int opus_packet_parse(const unsigned char *data, opus_int32 len, | |||
716 | 746 | ||
717 | int opus_decode_native(OpusDecoder *st, const unsigned char *data, | 747 | int opus_decode_native(OpusDecoder *st, const unsigned char *data, |
718 | opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, | 748 | opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, |
719 | int self_delimited, int *packet_offset) | 749 | int self_delimited, int *packet_offset, int soft_clip) |
720 | { | 750 | { |
721 | int i, nb_samples; | 751 | int i, nb_samples; |
722 | int count, offset; | 752 | int count, offset; |
723 | unsigned char toc; | 753 | unsigned char toc; |
724 | int tot_offset; | 754 | int tot_offset; |
755 | int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; | ||
725 | /* 48 x 2.5 ms = 120 ms */ | 756 | /* 48 x 2.5 ms = 120 ms */ |
726 | short size[48]; | 757 | opus_int16 size[48]; |
727 | if (decode_fec<0 || decode_fec>1) | 758 | if (decode_fec<0 || decode_fec>1) |
728 | return OPUS_BAD_ARG; | 759 | return OPUS_BAD_ARG; |
760 | /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ | ||
761 | if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) | ||
762 | return OPUS_BAD_ARG; | ||
729 | if (len==0 || data==NULL) | 763 | if (len==0 || data==NULL) |
730 | return opus_decode_frame(st, NULL, 0, pcm, frame_size, 0); | 764 | { |
731 | else if (len<0) | 765 | int pcm_count=0; |
766 | do { | ||
767 | int ret; | ||
768 | ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); | ||
769 | if (ret<0) | ||
770 | return ret; | ||
771 | pcm_count += ret; | ||
772 | } while (pcm_count < frame_size); | ||
773 | celt_assert(pcm_count == frame_size); | ||
774 | if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) | ||
775 | OPUS_PRINT_INT(pcm_count); | ||
776 | st->last_packet_duration = pcm_count; | ||
777 | return pcm_count; | ||
778 | } else if (len<0) | ||
732 | return OPUS_BAD_ARG; | 779 | return OPUS_BAD_ARG; |
733 | 780 | ||
734 | tot_offset = 0; | 781 | packet_mode = opus_packet_get_mode(data); |
735 | st->mode = opus_packet_get_mode(data); | 782 | packet_bandwidth = opus_packet_get_bandwidth(data); |
736 | st->bandwidth = opus_packet_get_bandwidth(data); | 783 | packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); |
737 | st->frame_size = opus_packet_get_samples_per_frame(data, st->Fs); | 784 | packet_stream_channels = opus_packet_get_nb_channels(data); |
738 | st->stream_channels = opus_packet_get_nb_channels(data); | ||
739 | 785 | ||
740 | count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); | 786 | count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); |
787 | |||
788 | data += offset; | ||
789 | |||
790 | if (decode_fec) | ||
791 | { | ||
792 | int duration_copy; | ||
793 | int ret; | ||
794 | /* If no FEC can be present, run the PLC (recursive call) */ | ||
795 | if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) | ||
796 | return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip); | ||
797 | /* Otherwise, run the PLC on everything except the size for which we might have FEC */ | ||
798 | duration_copy = st->last_packet_duration; | ||
799 | if (frame_size-packet_frame_size!=0) | ||
800 | { | ||
801 | ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); | ||
802 | if (ret<0) | ||
803 | { | ||
804 | st->last_packet_duration = duration_copy; | ||
805 | return ret; | ||
806 | } | ||
807 | celt_assert(ret==frame_size-packet_frame_size); | ||
808 | } | ||
809 | /* Complete with FEC */ | ||
810 | st->mode = packet_mode; | ||
811 | st->bandwidth = packet_bandwidth; | ||
812 | st->frame_size = packet_frame_size; | ||
813 | st->stream_channels = packet_stream_channels; | ||
814 | ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), | ||
815 | packet_frame_size, 1); | ||
816 | if (ret<0) | ||
817 | return ret; | ||
818 | else { | ||
819 | if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) | ||
820 | OPUS_PRINT_INT(frame_size); | ||
821 | st->last_packet_duration = frame_size; | ||
822 | return frame_size; | ||
823 | } | ||
824 | } | ||
825 | tot_offset = 0; | ||
741 | if (count < 0) | 826 | if (count < 0) |
742 | return count; | 827 | return count; |
743 | 828 | ||
744 | data += offset; | ||
745 | tot_offset += offset; | 829 | tot_offset += offset; |
746 | 830 | ||
747 | if (count*st->frame_size > frame_size) | 831 | if (count*packet_frame_size > frame_size) |
748 | return OPUS_BUFFER_TOO_SMALL; | 832 | return OPUS_BUFFER_TOO_SMALL; |
833 | |||
834 | /* Update the state as the last step to avoid updating it on an invalid packet */ | ||
835 | st->mode = packet_mode; | ||
836 | st->bandwidth = packet_bandwidth; | ||
837 | st->frame_size = packet_frame_size; | ||
838 | st->stream_channels = packet_stream_channels; | ||
839 | |||
749 | nb_samples=0; | 840 | nb_samples=0; |
750 | for (i=0;i<count;i++) | 841 | for (i=0;i<count;i++) |
751 | { | 842 | { |
752 | int ret; | 843 | int ret; |
753 | ret = opus_decode_frame(st, data, size[i], pcm, frame_size-nb_samples, decode_fec); | 844 | ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); |
754 | if (ret<0) | 845 | if (ret<0) |
755 | return ret; | 846 | return ret; |
847 | celt_assert(ret==packet_frame_size); | ||
756 | data += size[i]; | 848 | data += size[i]; |
757 | tot_offset += size[i]; | 849 | tot_offset += size[i]; |
758 | pcm += ret*st->channels; | ||
759 | nb_samples += ret; | 850 | nb_samples += ret; |
760 | } | 851 | } |
761 | if (packet_offset != NULL) | 852 | if (packet_offset != NULL) |
762 | *packet_offset = tot_offset; | 853 | *packet_offset = tot_offset; |
854 | st->last_packet_duration = nb_samples; | ||
855 | if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) | ||
856 | OPUS_PRINT_INT(nb_samples); | ||
857 | #ifndef FIXED_POINT | ||
858 | if (soft_clip) | ||
859 | opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); | ||
860 | else | ||
861 | st->softclip_mem[0]=st->softclip_mem[1]=0; | ||
862 | #endif | ||
763 | return nb_samples; | 863 | return nb_samples; |
764 | } | 864 | } |
765 | 865 | ||
@@ -768,7 +868,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data, | |||
768 | int opus_decode(OpusDecoder *st, const unsigned char *data, | 868 | int opus_decode(OpusDecoder *st, const unsigned char *data, |
769 | opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) | 869 | opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) |
770 | { | 870 | { |
771 | return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL); | 871 | return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); |
772 | } | 872 | } |
773 | 873 | ||
774 | #ifndef DISABLE_FLOAT_API | 874 | #ifndef DISABLE_FLOAT_API |
@@ -781,7 +881,7 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data, | |||
781 | 881 | ||
782 | ALLOC(out, frame_size*st->channels, opus_int16); | 882 | ALLOC(out, frame_size*st->channels, opus_int16); |
783 | 883 | ||
784 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL); | 884 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); |
785 | if (ret > 0) | 885 | if (ret > 0) |
786 | { | 886 | { |
787 | for (i=0;i<ret*st->channels;i++) | 887 | for (i=0;i<ret*st->channels;i++) |
@@ -809,7 +909,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, | |||
809 | 909 | ||
810 | ALLOC(out, frame_size*st->channels, float); | 910 | ALLOC(out, frame_size*st->channels, float); |
811 | 911 | ||
812 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL); | 912 | ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); |
813 | if (ret > 0) | 913 | if (ret > 0) |
814 | { | 914 | { |
815 | for (i=0;i<ret*st->channels;i++) | 915 | for (i=0;i<ret*st->channels;i++) |
@@ -822,7 +922,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, | |||
822 | int opus_decode_float(OpusDecoder *st, const unsigned char *data, | 922 | int opus_decode_float(OpusDecoder *st, const unsigned char *data, |
823 | opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) | 923 | opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) |
824 | { | 924 | { |
825 | return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL); | 925 | return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); |
826 | } | 926 | } |
827 | 927 | ||
828 | #endif | 928 | #endif |
@@ -845,12 +945,20 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) | |||
845 | case OPUS_GET_BANDWIDTH_REQUEST: | 945 | case OPUS_GET_BANDWIDTH_REQUEST: |
846 | { | 946 | { |
847 | opus_int32 *value = va_arg(ap, opus_int32*); | 947 | opus_int32 *value = va_arg(ap, opus_int32*); |
948 | if (!value) | ||
949 | { | ||
950 | goto bad_arg; | ||
951 | } | ||
848 | *value = st->bandwidth; | 952 | *value = st->bandwidth; |
849 | } | 953 | } |
850 | break; | 954 | break; |
851 | case OPUS_GET_FINAL_RANGE_REQUEST: | 955 | case OPUS_GET_FINAL_RANGE_REQUEST: |
852 | { | 956 | { |
853 | opus_uint32 *value = va_arg(ap, opus_uint32*); | 957 | opus_uint32 *value = va_arg(ap, opus_uint32*); |
958 | if (!value) | ||
959 | { | ||
960 | goto bad_arg; | ||
961 | } | ||
854 | *value = st->rangeFinal; | 962 | *value = st->rangeFinal; |
855 | } | 963 | } |
856 | break; | 964 | break; |
@@ -869,10 +977,9 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) | |||
869 | case OPUS_GET_SAMPLE_RATE_REQUEST: | 977 | case OPUS_GET_SAMPLE_RATE_REQUEST: |
870 | { | 978 | { |
871 | opus_int32 *value = va_arg(ap, opus_int32*); | 979 | opus_int32 *value = va_arg(ap, opus_int32*); |
872 | if (value==NULL) | 980 | if (!value) |
873 | { | 981 | { |
874 | ret = OPUS_BAD_ARG; | 982 | goto bad_arg; |
875 | break; | ||
876 | } | 983 | } |
877 | *value = st->Fs; | 984 | *value = st->Fs; |
878 | } | 985 | } |
@@ -880,10 +987,9 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) | |||
880 | case OPUS_GET_PITCH_REQUEST: | 987 | case OPUS_GET_PITCH_REQUEST: |
881 | { | 988 | { |
882 | opus_int32 *value = va_arg(ap, opus_int32*); | 989 | opus_int32 *value = va_arg(ap, opus_int32*); |
883 | if (value==NULL) | 990 | if (!value) |
884 | { | 991 | { |
885 | ret = OPUS_BAD_ARG; | 992 | goto bad_arg; |
886 | break; | ||
887 | } | 993 | } |
888 | if (st->prev_mode == MODE_CELT_ONLY) | 994 | if (st->prev_mode == MODE_CELT_ONLY) |
889 | celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value)); | 995 | celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value)); |
@@ -894,10 +1000,9 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) | |||
894 | case OPUS_GET_GAIN_REQUEST: | 1000 | case OPUS_GET_GAIN_REQUEST: |
895 | { | 1001 | { |
896 | opus_int32 *value = va_arg(ap, opus_int32*); | 1002 | opus_int32 *value = va_arg(ap, opus_int32*); |
897 | if (value==NULL) | 1003 | if (!value) |
898 | { | 1004 | { |
899 | ret = OPUS_BAD_ARG; | 1005 | goto bad_arg; |
900 | break; | ||
901 | } | 1006 | } |
902 | *value = st->decode_gain; | 1007 | *value = st->decode_gain; |
903 | } | 1008 | } |
@@ -907,12 +1012,21 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) | |||
907 | opus_int32 value = va_arg(ap, opus_int32); | 1012 | opus_int32 value = va_arg(ap, opus_int32); |
908 | if (value<-32768 || value>32767) | 1013 | if (value<-32768 || value>32767) |
909 | { | 1014 | { |
910 | ret = OPUS_BAD_ARG; | 1015 | goto bad_arg; |
911 | break; | ||
912 | } | 1016 | } |
913 | st->decode_gain = value; | 1017 | st->decode_gain = value; |
914 | } | 1018 | } |
915 | break; | 1019 | break; |
1020 | case OPUS_GET_LAST_PACKET_DURATION_REQUEST: | ||
1021 | { | ||
1022 | opus_uint32 *value = va_arg(ap, opus_uint32*); | ||
1023 | if (!value) | ||
1024 | { | ||
1025 | goto bad_arg; | ||
1026 | } | ||
1027 | *value = st->last_packet_duration; | ||
1028 | } | ||
1029 | break; | ||
916 | default: | 1030 | default: |
917 | /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/ | 1031 | /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/ |
918 | ret = OPUS_UNIMPLEMENTED; | 1032 | ret = OPUS_UNIMPLEMENTED; |
@@ -921,6 +1035,9 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) | |||
921 | 1035 | ||
922 | va_end(ap); | 1036 | va_end(ap); |
923 | return ret; | 1037 | return ret; |
1038 | bad_arg: | ||
1039 | va_end(ap); | ||
1040 | return OPUS_BAD_ARG; | ||
924 | } | 1041 | } |
925 | 1042 | ||
926 | void opus_decoder_destroy(OpusDecoder *st) | 1043 | void opus_decoder_destroy(OpusDecoder *st) |
@@ -989,8 +1106,8 @@ int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) | |||
989 | return packet[1]&0x3F; | 1106 | return packet[1]&0x3F; |
990 | } | 1107 | } |
991 | 1108 | ||
992 | int opus_decoder_get_nb_samples(const OpusDecoder *dec, | 1109 | int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, |
993 | const unsigned char packet[], opus_int32 len) | 1110 | opus_int32 Fs) |
994 | { | 1111 | { |
995 | int samples; | 1112 | int samples; |
996 | int count = opus_packet_get_nb_frames(packet, len); | 1113 | int count = opus_packet_get_nb_frames(packet, len); |
@@ -998,10 +1115,16 @@ int opus_decoder_get_nb_samples(const OpusDecoder *dec, | |||
998 | if (count<0) | 1115 | if (count<0) |
999 | return count; | 1116 | return count; |
1000 | 1117 | ||
1001 | samples = count*opus_packet_get_samples_per_frame(packet, dec->Fs); | 1118 | samples = count*opus_packet_get_samples_per_frame(packet, Fs); |
1002 | /* Can't have more than 120 ms */ | 1119 | /* Can't have more than 120 ms */ |
1003 | if (samples*25 > dec->Fs*3) | 1120 | if (samples*25 > Fs*3) |
1004 | return OPUS_INVALID_PACKET; | 1121 | return OPUS_INVALID_PACKET; |
1005 | else | 1122 | else |
1006 | return samples; | 1123 | return samples; |
1007 | } | 1124 | } |
1125 | |||
1126 | int opus_decoder_get_nb_samples(const OpusDecoder *dec, | ||
1127 | const unsigned char packet[], opus_int32 len) | ||
1128 | { | ||
1129 | return opus_packet_get_nb_samples(packet, len, dec->Fs); | ||
1130 | } | ||