Rename AvBufferX -> AvByteBufferX and create AvShortBufferX

This commit is contained in:
Cameron Gutman 2013-11-10 03:42:29 -05:00
parent 62a9040cb8
commit 34e87ca899
11 changed files with 115 additions and 68 deletions

View File

@ -3,29 +3,22 @@ package com.limelight.nvstream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;
import jlibrtp.Participant;
import jlibrtp.RTPSession;
import com.limelight.nvstream.av.AvBufferDescriptor;
import com.limelight.nvstream.av.AvBufferPool;
import com.limelight.nvstream.av.AvDecodeUnit;
import com.limelight.nvstream.av.AvByteBufferDescriptor;
import com.limelight.nvstream.av.AvByteBufferPool;
import com.limelight.nvstream.av.AvRtpPacket;
import com.limelight.nvstream.av.AvShortBufferDescriptor;
import com.limelight.nvstream.av.audio.AvAudioDepacketizer;
import com.limelight.nvstream.av.audio.OpusDecoder;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.net.rtp.AudioGroup;
import android.net.rtp.AudioStream;
import android.view.Surface;
public class NvAudioStream {
public static final int RTP_PORT = 48000;
@ -40,7 +33,7 @@ public class NvAudioStream {
private AvAudioDepacketizer depacketizer = new AvAudioDepacketizer();
private AvBufferPool pool = new AvBufferPool(1500);
private AvByteBufferPool pool = new AvByteBufferPool(1500);
public void startAudioStream(final String host)
{
@ -147,7 +140,8 @@ public class NvAudioStream {
public void run() {
for (;;)
{
short[] samples;
AvShortBufferDescriptor samples;
try {
samples = depacketizer.getNextDecodedData();
} catch (InterruptedException e) {
@ -155,7 +149,7 @@ public class NvAudioStream {
return;
}
track.write(samples, 0, samples.length);
track.write(samples.data, samples.offset, samples.length);
}
}
}).start();
@ -168,7 +162,7 @@ public class NvAudioStream {
@Override
public void run() {
DatagramPacket packet = new DatagramPacket(pool.allocate(), 1500);
AvBufferDescriptor desc = new AvBufferDescriptor(null, 0, 0);
AvByteBufferDescriptor desc = new AvByteBufferDescriptor(null, 0, 0);
for (;;)
{

View File

@ -10,8 +10,8 @@ import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;
import com.limelight.nvstream.av.AvBufferDescriptor;
import com.limelight.nvstream.av.AvBufferPool;
import com.limelight.nvstream.av.AvByteBufferDescriptor;
import com.limelight.nvstream.av.AvByteBufferPool;
import com.limelight.nvstream.av.AvDecodeUnit;
import com.limelight.nvstream.av.AvRtpPacket;
import com.limelight.nvstream.av.video.AvVideoDepacketizer;
@ -37,7 +37,7 @@ public class NvVideoStream {
private RTPSession session;
private DatagramSocket rtp;
private AvBufferPool pool = new AvBufferPool(1500);
private AvByteBufferPool pool = new AvByteBufferPool(1500);
private AvVideoDepacketizer depacketizer = new AvVideoDepacketizer();
@ -176,7 +176,7 @@ public class NvVideoStream {
buf.clear();
// Copy data from our buffer list into the input buffer
for (AvBufferDescriptor desc : du.getBufferList())
for (AvByteBufferDescriptor desc : du.getBufferList())
{
buf.put(desc.data, desc.offset, desc.length);
@ -234,7 +234,7 @@ public class NvVideoStream {
@Override
public void run() {
DatagramPacket packet = new DatagramPacket(pool.allocate(), 1500);
AvBufferDescriptor desc = new AvBufferDescriptor(null, 0, 0);
AvByteBufferDescriptor desc = new AvByteBufferDescriptor(null, 0, 0);
for (;;)
{

View File

@ -1,18 +1,18 @@
package com.limelight.nvstream.av;
public class AvBufferDescriptor {
public class AvByteBufferDescriptor {
public byte[] data;
public int offset;
public int length;
public AvBufferDescriptor(byte[] data, int offset, int length)
public AvByteBufferDescriptor(byte[] data, int offset, int length)
{
this.data = data;
this.offset = offset;
this.length = length;
}
public AvBufferDescriptor(AvBufferDescriptor desc)
public AvByteBufferDescriptor(AvByteBufferDescriptor desc)
{
this.data = desc.data;
this.offset = desc.offset;

View File

@ -2,11 +2,11 @@ package com.limelight.nvstream.av;
import java.util.LinkedList;
public class AvBufferPool {
public class AvByteBufferPool {
private LinkedList<byte[]> bufferList = new LinkedList<byte[]>();
private int bufferSize;
public AvBufferPool(int size)
public AvByteBufferPool(int size)
{
this.bufferSize = size;
}

View File

@ -8,11 +8,11 @@ public class AvDecodeUnit {
public static final int TYPE_OPUS = 2;
private int type;
private List<AvBufferDescriptor> bufferList;
private List<AvByteBufferDescriptor> bufferList;
private int dataLength;
private int flags;
public AvDecodeUnit(int type, List<AvBufferDescriptor> bufferList, int dataLength, int flags)
public AvDecodeUnit(int type, List<AvByteBufferDescriptor> bufferList, int dataLength, int flags)
{
this.type = type;
this.bufferList = bufferList;
@ -30,7 +30,7 @@ public class AvDecodeUnit {
return flags;
}
public List<AvBufferDescriptor> getBufferList()
public List<AvByteBufferDescriptor> getBufferList()
{
return bufferList;
}

View File

@ -6,11 +6,11 @@ public class AvRtpPacket {
private byte packetType;
private short seqNum;
private AvBufferDescriptor buffer;
private AvByteBufferDescriptor buffer;
public AvRtpPacket(AvBufferDescriptor buffer)
public AvRtpPacket(AvByteBufferDescriptor buffer)
{
this.buffer = new AvBufferDescriptor(buffer);
this.buffer = new AvByteBufferDescriptor(buffer);
ByteBuffer bb = ByteBuffer.wrap(buffer.data, buffer.offset, buffer.length);
@ -34,8 +34,8 @@ public class AvRtpPacket {
return seqNum;
}
public AvBufferDescriptor getNewPayloadDescriptor()
public AvByteBufferDescriptor getNewPayloadDescriptor()
{
return new AvBufferDescriptor(buffer.data, buffer.offset+12, buffer.length-12);
return new AvByteBufferDescriptor(buffer.data, buffer.offset+12, buffer.length-12);
}
}

View File

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

View File

@ -0,0 +1,30 @@
package com.limelight.nvstream.av;
import java.util.LinkedList;
public class AvShortBufferPool {
private LinkedList<short[]> bufferList = new LinkedList<short[]>();
private int bufferSize;
public AvShortBufferPool(int size)
{
this.bufferSize = size;
}
public synchronized short[] allocate()
{
if (bufferList.isEmpty())
{
return new short[bufferSize];
}
else
{
return bufferList.removeFirst();
}
}
public synchronized void free(short[] buffer)
{
bufferList.addFirst(buffer);
}
}

View File

@ -2,11 +2,16 @@ package com.limelight.nvstream.av.audio;
import java.util.concurrent.LinkedBlockingQueue;
import com.limelight.nvstream.av.AvBufferDescriptor;
import com.limelight.nvstream.av.AvByteBufferDescriptor;
import com.limelight.nvstream.av.AvRtpPacket;
import com.limelight.nvstream.av.AvShortBufferDescriptor;
import com.limelight.nvstream.av.AvShortBufferPool;
public class AvAudioDepacketizer {
private LinkedBlockingQueue<short[]> decodedUnits = new LinkedBlockingQueue<short[]>();
private LinkedBlockingQueue<AvShortBufferDescriptor> decodedUnits =
new LinkedBlockingQueue<AvShortBufferDescriptor>();
private AvShortBufferPool pool = new AvShortBufferPool(OpusDecoder.getMaxOutputShorts());
// Sequencing state
private short lastSequenceNumber;
@ -34,25 +39,22 @@ public class AvAudioDepacketizer {
lastSequenceNumber = seq;
// This is all the depacketizing we need to do
AvBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor();
AvByteBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor();
// Submit this data to the decoder
short[] pcmData = new short[OpusDecoder.getMaxOutputShorts()];
short[] pcmData = pool.allocate();
int decodeLen = OpusDecoder.decode(rtpPayload.data, rtpPayload.offset, rtpPayload.length, pcmData);
if (decodeLen > 0) {
// Return value of decode is frames decoded per channel
decodeLen *= OpusDecoder.getChannelCount();
if (decodeLen > 0) {
// Jank!
short[] trimmedPcmData = new short[decodeLen];
System.arraycopy(pcmData, 0, trimmedPcmData, 0, decodeLen);
decodedUnits.add(trimmedPcmData);
// Put it on the decoded queue
decodedUnits.add(new AvShortBufferDescriptor(pcmData, 0, decodeLen));
}
}
public short[] getNextDecodedData() throws InterruptedException
public AvShortBufferDescriptor getNextDecodedData() throws InterruptedException
{
return decodedUnits.take();
}

View File

@ -3,7 +3,7 @@ package com.limelight.nvstream.av.video;
import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingQueue;
import com.limelight.nvstream.av.AvBufferDescriptor;
import com.limelight.nvstream.av.AvByteBufferDescriptor;
import com.limelight.nvstream.av.AvDecodeUnit;
import com.limelight.nvstream.av.AvRtpPacket;
@ -12,7 +12,7 @@ import android.media.MediaCodec;
public class AvVideoDepacketizer {
// Current NAL state
private LinkedList<AvBufferDescriptor> avcNalDataChain = null;
private LinkedList<AvByteBufferDescriptor> avcNalDataChain = null;
private int avcNalDataLength = 0;
private int currentlyDecoding;
@ -29,8 +29,8 @@ public class AvVideoDepacketizer {
int flags = 0;
// Check if this is a special NAL unit
AvBufferDescriptor header = avcNalDataChain.getFirst();
AvBufferDescriptor specialSeq = NAL.getSpecialSequenceDescriptor(header);
AvByteBufferDescriptor header = avcNalDataChain.getFirst();
AvByteBufferDescriptor specialSeq = NAL.getSpecialSequenceDescriptor(header);
if (specialSeq != null)
{
@ -85,7 +85,7 @@ public class AvVideoDepacketizer {
public void addInputData(AvVideoPacket packet)
{
AvBufferDescriptor location = packet.getNewPayloadDescriptor();
AvByteBufferDescriptor location = packet.getNewPayloadDescriptor();
while (location.length != 0)
{
@ -93,7 +93,7 @@ public class AvVideoDepacketizer {
int start = location.offset;
// Check for a special sequence
AvBufferDescriptor specialSeq = NAL.getSpecialSequenceDescriptor(location);
AvByteBufferDescriptor specialSeq = NAL.getSpecialSequenceDescriptor(location);
if (specialSeq != null)
{
if (NAL.isAvcStartSequence(specialSeq))
@ -108,7 +108,7 @@ public class AvVideoDepacketizer {
reassembleAvcNal();
// Setup state for the new NAL
avcNalDataChain = new LinkedList<AvBufferDescriptor>();
avcNalDataChain = new LinkedList<AvByteBufferDescriptor>();
avcNalDataLength = 0;
}
}
@ -141,7 +141,7 @@ public class AvVideoDepacketizer {
}
}
AvBufferDescriptor data = new AvBufferDescriptor(location.data, start, location.offset-start);
AvByteBufferDescriptor data = new AvByteBufferDescriptor(location.data, start, location.offset-start);
if (currentlyDecoding == AvDecodeUnit.TYPE_H264 && avcNalDataChain != null)
{
@ -172,7 +172,7 @@ public class AvVideoDepacketizer {
lastSequenceNumber = seq;
// Pass the payload to the non-sequencing parser
AvBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor();
AvByteBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor();
addInputData(new AvVideoPacket(rtpPayload));
}
@ -185,7 +185,7 @@ public class AvVideoDepacketizer {
class NAL {
// This assumes that the buffer passed in is already a special sequence
public static boolean isAvcStartSequence(AvBufferDescriptor specialSeq)
public static boolean isAvcStartSequence(AvByteBufferDescriptor specialSeq)
{
if (specialSeq.length != 3 && specialSeq.length != 4)
return false;
@ -195,7 +195,7 @@ class NAL {
}
// This assumes that the buffer passed in is already a special sequence
public static boolean isUnknownStartSequence(AvBufferDescriptor specialSeq)
public static boolean isUnknownStartSequence(AvByteBufferDescriptor specialSeq)
{
if (specialSeq.length != 3)
return false;
@ -205,7 +205,7 @@ class NAL {
}
// This assumes that the buffer passed in is already a special sequence
public static boolean isAvcFrameStart(AvBufferDescriptor specialSeq)
public static boolean isAvcFrameStart(AvByteBufferDescriptor specialSeq)
{
if (specialSeq.length != 4)
return false;
@ -215,7 +215,7 @@ class NAL {
}
// Returns a buffer descriptor describing the start sequence
public static AvBufferDescriptor getSpecialSequenceDescriptor(AvBufferDescriptor buffer)
public static AvByteBufferDescriptor getSpecialSequenceDescriptor(AvByteBufferDescriptor buffer)
{
// NAL start sequence is 00 00 00 01 or 00 00 01
if (buffer.length < 3)
@ -233,19 +233,19 @@ class NAL {
buffer.data[buffer.offset+3] == 0x01)
{
// It's the AVC start sequence 00 00 00 01
return new AvBufferDescriptor(buffer.data, buffer.offset, 4);
return new AvByteBufferDescriptor(buffer.data, buffer.offset, 4);
}
else
{
// It's 00 00 00
return new AvBufferDescriptor(buffer.data, buffer.offset, 3);
return new AvByteBufferDescriptor(buffer.data, buffer.offset, 3);
}
}
else if (buffer.data[buffer.offset+2] == 0x01 ||
buffer.data[buffer.offset+2] == 0x02)
{
// These are easy: 00 00 01 or 00 00 02
return new AvBufferDescriptor(buffer.data, buffer.offset, 3);
return new AvByteBufferDescriptor(buffer.data, buffer.offset, 3);
}
else if (buffer.data[buffer.offset+2] == 0x03)
{
@ -267,7 +267,7 @@ class NAL {
else
{
// It's not a standard replacement so it's a special sequence
return new AvBufferDescriptor(buffer.data, buffer.offset, 3);
return new AvByteBufferDescriptor(buffer.data, buffer.offset, 3);
}
}
}

View File

@ -1,17 +1,17 @@
package com.limelight.nvstream.av.video;
import com.limelight.nvstream.av.AvBufferDescriptor;
import com.limelight.nvstream.av.AvByteBufferDescriptor;
public class AvVideoPacket {
private AvBufferDescriptor buffer;
private AvByteBufferDescriptor buffer;
public AvVideoPacket(AvBufferDescriptor rtpPayload)
public AvVideoPacket(AvByteBufferDescriptor rtpPayload)
{
buffer = new AvBufferDescriptor(rtpPayload);
buffer = new AvByteBufferDescriptor(rtpPayload);
}
public AvBufferDescriptor getNewPayloadDescriptor()
public AvByteBufferDescriptor getNewPayloadDescriptor()
{
return new AvBufferDescriptor(buffer.data, buffer.offset+56, buffer.length-56);
return new AvByteBufferDescriptor(buffer.data, buffer.offset+56, buffer.length-56);
}
}