Merge pull request #1 from irtimmer/master

Use a byte buffer for audio to minimize buffer copy's
This commit is contained in:
Cameron Gutman 2014-01-08 18:19:25 -08:00
commit 84551df36a
5 changed files with 14 additions and 40 deletions

View File

@ -1,28 +0,0 @@
package com.limelight.nvstream.av;
public class ShortBufferDescriptor {
public short[] data;
public int offset;
public int length;
public ShortBufferDescriptor(short[] data, int offset, int length)
{
this.data = data;
this.offset = offset;
this.length = length;
}
public ShortBufferDescriptor(ShortBufferDescriptor desc)
{
this.data = desc.data;
this.offset = desc.offset;
this.length = desc.length;
}
public void reinitialize(short[] data, int offset, int length)
{
this.data = data;
this.offset = offset;
this.length = length;
}
}

View File

@ -4,13 +4,15 @@ import java.util.concurrent.LinkedBlockingQueue;
import com.limelight.nvstream.av.ByteBufferDescriptor; import com.limelight.nvstream.av.ByteBufferDescriptor;
import com.limelight.nvstream.av.RtpPacket; import com.limelight.nvstream.av.RtpPacket;
import com.limelight.nvstream.av.ShortBufferDescriptor; import com.limelight.nvstream.av.ByteBufferDescriptor;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
public class AudioDepacketizer { public class AudioDepacketizer {
private static final int DU_LIMIT = 15; private static final int DU_LIMIT = 15;
private LinkedBlockingQueue<ShortBufferDescriptor> decodedUnits = private LinkedBlockingQueue<ByteBufferDescriptor> decodedUnits =
new LinkedBlockingQueue<ShortBufferDescriptor>(DU_LIMIT); new LinkedBlockingQueue<ByteBufferDescriptor>(DU_LIMIT);
// Sequencing state // Sequencing state
private short lastSequenceNumber; private short lastSequenceNumber;
@ -18,15 +20,15 @@ public class AudioDepacketizer {
private void decodeData(byte[] data, int off, int len) private void decodeData(byte[] data, int off, int len)
{ {
// Submit this data to the decoder // Submit this data to the decoder
short[] pcmData = new short[OpusDecoder.getMaxOutputShorts()]; byte[] pcmData = new byte[OpusDecoder.getMaxOutputShorts()*2];
int decodeLen = OpusDecoder.decode(data, off, len, pcmData); int decodeLen = OpusDecoder.decode(data, off, len, pcmData);
if (decodeLen > 0) { if (decodeLen > 0) {
// Return value of decode is frames decoded per channel // Return value of decode is frames (shorts) decoded per channel
decodeLen *= OpusDecoder.getChannelCount(); decodeLen *= 2*OpusDecoder.getChannelCount();
// Put it on the decoded queue // Put it on the decoded queue
if (!decodedUnits.offer(new ShortBufferDescriptor(pcmData, 0, decodeLen))) { if (!decodedUnits.offer(new ByteBufferDescriptor(pcmData, 0, decodeLen))) {
System.out.println("Audio player too slow! Forced to drop decoded samples"); System.out.println("Audio player too slow! Forced to drop decoded samples");
// Clear out the queue // Clear out the queue
decodedUnits.clear(); decodedUnits.clear();
@ -59,7 +61,7 @@ public class AudioDepacketizer {
decodeData(rtpPayload.data, rtpPayload.offset, rtpPayload.length); decodeData(rtpPayload.data, rtpPayload.offset, rtpPayload.length);
} }
public ShortBufferDescriptor getNextDecodedData() throws InterruptedException public ByteBufferDescriptor getNextDecodedData() throws InterruptedException
{ {
return decodedUnits.take(); return decodedUnits.take();
} }

View File

@ -3,7 +3,7 @@ package com.limelight.nvstream.av.audio;
public interface AudioRenderer { public interface AudioRenderer {
public void streamInitialized(int channelCount, int sampleRate); public void streamInitialized(int channelCount, int sampleRate);
public void playDecodedAudio(short[] audioData, int offset, int length); public void playDecodedAudio(byte[] audioData, int offset, int length);
public void streamClosing(); public void streamClosing();
} }

View File

@ -12,7 +12,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import com.limelight.nvstream.NvConnectionListener; import com.limelight.nvstream.NvConnectionListener;
import com.limelight.nvstream.av.ByteBufferDescriptor; import com.limelight.nvstream.av.ByteBufferDescriptor;
import com.limelight.nvstream.av.RtpPacket; import com.limelight.nvstream.av.RtpPacket;
import com.limelight.nvstream.av.ShortBufferDescriptor; import com.limelight.nvstream.av.ByteBufferDescriptor;
public class AudioStream { public class AudioStream {
public static final int RTP_PORT = 48000; public static final int RTP_PORT = 48000;
@ -140,7 +140,7 @@ public class AudioStream {
public void run() { public void run() {
while (!isInterrupted()) while (!isInterrupted())
{ {
ShortBufferDescriptor samples; ByteBufferDescriptor samples;
try { try {
samples = depacketizer.getNextDecodedData(); samples = depacketizer.getNextDecodedData();

View File

@ -10,5 +10,5 @@ public class OpusDecoder {
public static native int getChannelCount(); public static native int getChannelCount();
public static native int getMaxOutputShorts(); public static native int getMaxOutputShorts();
public static native int getSampleRate(); public static native int getSampleRate();
public static native int decode(byte[] indata, int inoff, int inlen, short[] outpcmdata); public static native int decode(byte[] indata, int inoff, int inlen, byte[] outpcmdata);
} }