summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libopus/opus_decoder.c
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2014-01-19 16:31:59 +0100
committerNils Wallménius <nils@rockbox.org>2014-07-13 11:12:40 +0200
commit9b7ec42403073ee887efc531c153e6b1b6c15bab (patch)
tree07e72fe9d817c65a6fede22955344a870842d5e6 /lib/rbcodec/codecs/libopus/opus_decoder.c
parente557951c94c1efa769900257e466900f0ffeb53b (diff)
downloadrockbox-9b7ec42403073ee887efc531c153e6b1b6c15bab.tar.gz
rockbox-9b7ec42403073ee887efc531c153e6b1b6c15bab.zip
Sync to upstream libopus
Sync to commit bb4b6885a139644cf3ac14e7deda9f633ec2d93c This brings in a bunch of optimizations to decode speed and memory usage. Allocations are switched from using the pseudostack to using the real stack. Enabled hacks to reduce stack usage. This should fix crashes on sansa clip, although some files will not play due to failing allocations in the codec buffer. Speeds up decoding of the following test files: H300 (cf) C200 (arm7tdmi) ipod classic (arm9e) 16 kbps (silk) 14.28 MHz 4.00 MHz 2.61 MHz 64 kbps (celt) 4.09 MHz 8.08 MHz 6.24 MHz 128 kbps (celt) 1.93 MHz 8.83 MHz 6.53 MHz Change-Id: I851733a8a5824b61feb363a173091bc7e6629b58
Diffstat (limited to 'lib/rbcodec/codecs/libopus/opus_decoder.c')
-rw-r--r--lib/rbcodec/codecs/libopus/opus_decoder.c85
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
81static 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
87int opus_decoder_get_size(int channels) 81int 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
914int 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
935int opus_packet_get_nb_channels(const unsigned char *data) 944int 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;