summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libopus/opus_decoder.c
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2013-05-20 22:25:57 +0200
committerNils Wallménius <nils@rockbox.org>2013-08-31 08:30:51 +0200
commit580b307fd791c0997a8831bc800bba87797bfb7e (patch)
tree807846056f06fd944a750ce41217a877910ebd59 /lib/rbcodec/codecs/libopus/opus_decoder.c
parent74761b70acd96cecc0d35450dd56a98ad9ee7d3d (diff)
downloadrockbox-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.c259
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
50struct OpusDecoder { 51struct 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 */
135static char s_dec[STATIC_DECODER_SIZE] IBSS_ATTR MEM_ALIGN_ATTR; 142static char s_dec[STATIC_DECODER_SIZE] IBSS_ATTR MEM_ALIGN_ATTR;
136 143
137OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error) 144OpusDecoder *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
542static int parse_size(const unsigned char *data, opus_int32 len, short *size) 572static 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
562static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, 592static 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
709int opus_packet_parse(const unsigned char *data, opus_int32 len, 739int 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
717int opus_decode_native(OpusDecoder *st, const unsigned char *data, 747int 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,
768int opus_decode(OpusDecoder *st, const unsigned char *data, 868int 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,
822int opus_decode_float(OpusDecoder *st, const unsigned char *data, 922int 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;
1038bad_arg:
1039 va_end(ap);
1040 return OPUS_BAD_ARG;
924} 1041}
925 1042
926void opus_decoder_destroy(OpusDecoder *st) 1043void 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
992int opus_decoder_get_nb_samples(const OpusDecoder *dec, 1109int 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
1126int 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}