diff --git a/jni/nv_opus_dec.c b/jni/nv_opus_dec.c index 60425aec..c3514a82 100644 --- a/jni/nv_opus_dec.c +++ b/jni/nv_opus_dec.c @@ -30,7 +30,7 @@ int nv_opus_get_channel_count(void) { // This number assumes 2 channels at 48 KHz int nv_opus_get_max_out_shorts(void) { - return 5760*2; + return 512*nv_opus_get_channel_count(); } // The Opus stream is 48 KHz @@ -48,7 +48,7 @@ int nv_opus_decode(unsigned char* indata, int inlen, short* outpcmdata) { // Decoding to 16-bit PCM with FEC off // Maximum length assuming 48KHz sample rate err = opus_decode(decoder, indata, inlen, - outpcmdata, 5760, 0); + outpcmdata, 512, 0); return err; } diff --git a/jni/nv_opus_dec_jni.c b/jni/nv_opus_dec_jni.c index bb99568b..1df69883 100644 --- a/jni/nv_opus_dec_jni.c +++ b/jni/nv_opus_dec_jni.c @@ -1,5 +1,6 @@ #include "nv_opus_dec.h" +#include #include // This function must be called before @@ -48,13 +49,19 @@ Java_com_limelight_nvstream_av_audio_OpusDecoder_decode( jbyte* jni_input_data; jshort* jni_pcm_data; - jni_input_data = (*env)->GetByteArrayElements(env, indata, 0); - jni_pcm_data = (*env)->GetShortArrayElements(env, outpcmdata, 0); + jni_pcm_data = (*env)->GetShortArrayElements(env, outpcmdata, 0); + if (indata != NULL) { + jni_input_data = (*env)->GetByteArrayElements(env, indata, 0); - ret = nv_opus_decode(&jni_input_data[inoff], inlen, jni_pcm_data); + ret = nv_opus_decode(&jni_input_data[inoff], inlen, jni_pcm_data); + + // The input data isn't changed so it can be safely aborted + (*env)->ReleaseByteArrayElements(env, indata, jni_input_data, JNI_ABORT); + } + else { + ret = nv_opus_decode(NULL, 0, jni_pcm_data); + } - // The input data isn't changed so it can be safely aborted - (*env)->ReleaseByteArrayElements(env, indata, jni_input_data, JNI_ABORT); (*env)->ReleaseShortArrayElements(env, outpcmdata, jni_pcm_data, 0); return ret; diff --git a/libs/armeabi-v7a/libnv_opus_dec.so b/libs/armeabi-v7a/libnv_opus_dec.so index 4f8be297..1c02515a 100644 Binary files a/libs/armeabi-v7a/libnv_opus_dec.so and b/libs/armeabi-v7a/libnv_opus_dec.so differ diff --git a/src/com/limelight/nvstream/av/audio/AvAudioDepacketizer.java b/src/com/limelight/nvstream/av/audio/AvAudioDepacketizer.java index beffca91..13a78f4b 100644 --- a/src/com/limelight/nvstream/av/audio/AvAudioDepacketizer.java +++ b/src/com/limelight/nvstream/av/audio/AvAudioDepacketizer.java @@ -11,7 +11,7 @@ public class AvAudioDepacketizer { private LinkedBlockingQueue decodedUnits = new LinkedBlockingQueue(15); - private AvShortBufferPool pool = new AvShortBufferPool(512); + private AvShortBufferPool pool = new AvShortBufferPool(OpusDecoder.getMaxOutputShorts()); // Sequencing state private short lastSequenceNumber; @@ -21,34 +21,11 @@ public class AvAudioDepacketizer { pool.purge(); } - public void decodeInputData(AvRtpPacket packet) + private void decodeData(byte[] data, int off, int len) { - short seq = packet.getSequenceNumber(); - - if (packet.getPacketType() != 97) { - // Only type 97 is audio - return; - } - - // Toss out the current NAL if we receive a packet that is - // out of sequence - if (lastSequenceNumber != 0 && - (short)(lastSequenceNumber + 1) != seq) - { - System.out.println("Received OOS audio data (expected "+(lastSequenceNumber + 1)+", got "+seq+")"); - - // Tell the decoder about this packet loss - //OpusDecoder.decode(null, 0, 0, null); - } - - lastSequenceNumber = seq; - - // This is all the depacketizing we need to do - AvByteBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor(); - // Submit this data to the decoder short[] pcmData = pool.allocate(); - int decodeLen = OpusDecoder.decode(rtpPayload.data, rtpPayload.offset, rtpPayload.length, pcmData); + int decodeLen = OpusDecoder.decode(data, off, len, pcmData); if (decodeLen > 0) { // Return value of decode is frames decoded per channel @@ -66,6 +43,31 @@ public class AvAudioDepacketizer { } } + public void decodeInputData(AvRtpPacket packet) + { + short seq = packet.getSequenceNumber(); + + if (packet.getPacketType() != 97) { + // Only type 97 is audio + return; + } + + // Toss out the current NAL if we receive a packet that is + // out of sequence + if (lastSequenceNumber != 0 && + (short)(lastSequenceNumber + 1) != seq) + { + System.out.println("Received OOS audio data (expected "+(lastSequenceNumber + 1)+", got "+seq+")"); + decodeData(null, 0, 0); + } + + lastSequenceNumber = seq; + + // This is all the depacketizing we need to do + AvByteBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor(); + decodeData(rtpPayload.data, rtpPayload.offset, rtpPayload.length); + } + public void releaseBuffer(AvShortBufferDescriptor decodedData) { pool.free(decodedData.data);