44import com .sedmelluq .discord .lavaplayer .tools .io .BitStreamWriter ;
55import com .sedmelluq .discord .lavaplayer .tools .io .ByteBufferOutputStream ;
66import com .sedmelluq .lava .common .natives .NativeResourceHolder ;
7+ import org .slf4j .Logger ;
8+ import org .slf4j .LoggerFactory ;
79
810import java .io .ByteArrayInputStream ;
911import java .io .IOException ;
1618 * layer. The only AAC type verified to work with this is AAC_LC.
1719 */
1820public class AacDecoder extends NativeResourceHolder {
21+ private static final Logger log = LoggerFactory .getLogger (AacDecoder .class );
22+
1923 private static final int [] SAMPLERATE_TABLE = { 96000 , 88200 , 64000 , 48000 , 44100 ,
2024 32000 , 24000 , 22050 , 16000 , 12000 , 11025 , 8000 , 7350 };
2125
@@ -31,8 +35,13 @@ public class AacDecoder extends NativeResourceHolder {
3135 private static final int ERROR_NOT_ENOUGH_BITS = 4098 ;
3236 private static final int ERROR_OUTPUT_BUFFER_TOO_SMALL = 8204 ;
3337
38+ // per-frame decode errors are in the range 0x4000-0x4FFF
39+ private static final int DECODE_ERROR_START = 0x4000 ;
40+ private static final int DECODE_ERROR_END = 0x4FFF ;
41+
3442 private final AacDecoderLibrary library ;
35- private final long instance ;
43+ private long instance ;
44+ private Long lastConfig ;
3645
3746 /**
3847 * Create a new decoder.
@@ -102,6 +111,7 @@ private synchronized int configureRaw(long buffer) {
102111 buffer = Long .reverseBytes (buffer );
103112 }
104113
114+ lastConfig = buffer ;
105115 return library .configure (instance , buffer );
106116 }
107117
@@ -205,11 +215,28 @@ public synchronized boolean decode(ShortBuffer buffer, boolean flush) {
205215 }
206216
207217 int result = library .decode (instance , buffer , buffer .capacity (), flush );
208- if (result != 0 && result != ERROR_NOT_ENOUGH_BITS ) {
209- throw new IllegalStateException ("Error from decoder " + result );
218+
219+ if (result == 0 ) {
220+ return true ;
221+ } else if (result == ERROR_NOT_ENOUGH_BITS ) {
222+ return false ;
223+ } else if (result >= DECODE_ERROR_START && result <= DECODE_ERROR_END ) {
224+ // 0x4xxx errors are per-frame, so we can try to ignore the error and resume from the next frame
225+ log .warn ("Skipping corrupt AAC frame, decoder returned error {}." , result );
226+ resetInstance ();
227+ return false ;
210228 }
211229
212- return result == 0 ;
230+ throw new IllegalStateException ("Error from decoder " + result );
231+ }
232+
233+ private void resetInstance () {
234+ library .destroy (instance );
235+ instance = library .create (TRANSPORT_NONE );
236+
237+ if (lastConfig != null ) {
238+ library .configure (instance , lastConfig );
239+ }
213240 }
214241
215242 /**
0 commit comments