summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libopus/opus_decoder.c
diff options
context:
space:
mode:
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}