mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Use ring buffers for audio and video handling to remove the last large allocations that were happening very frequently
This commit is contained in:
parent
a39f4c5eab
commit
8c9d0d171c
@ -12,9 +12,14 @@ public class AudioDepacketizer {
|
|||||||
private LinkedBlockingQueue<ByteBufferDescriptor> decodedUnits =
|
private LinkedBlockingQueue<ByteBufferDescriptor> decodedUnits =
|
||||||
new LinkedBlockingQueue<ByteBufferDescriptor>(DU_LIMIT);
|
new LinkedBlockingQueue<ByteBufferDescriptor>(DU_LIMIT);
|
||||||
|
|
||||||
|
// Direct submit state
|
||||||
private AudioRenderer directSubmitRenderer;
|
private AudioRenderer directSubmitRenderer;
|
||||||
private byte[] directSubmitData;
|
private byte[] directSubmitData;
|
||||||
|
|
||||||
|
// Non-direct submit state
|
||||||
|
private byte[][] pcmRing;
|
||||||
|
private int ringIndex;
|
||||||
|
|
||||||
// Sequencing state
|
// Sequencing state
|
||||||
private short lastSequenceNumber;
|
private short lastSequenceNumber;
|
||||||
|
|
||||||
@ -24,6 +29,9 @@ public class AudioDepacketizer {
|
|||||||
if (directSubmitRenderer != null) {
|
if (directSubmitRenderer != null) {
|
||||||
this.directSubmitData = new byte[OpusDecoder.getMaxOutputShorts()*2];
|
this.directSubmitData = new byte[OpusDecoder.getMaxOutputShorts()*2];
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
pcmRing = new byte[DU_LIMIT][OpusDecoder.getMaxOutputShorts()*2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decodeData(byte[] data, int off, int len)
|
private void decodeData(byte[] data, int off, int len)
|
||||||
@ -36,11 +44,11 @@ public class AudioDepacketizer {
|
|||||||
decodeLen = OpusDecoder.decode(data, off, len, directSubmitData);
|
decodeLen = OpusDecoder.decode(data, off, len, directSubmitData);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pcmData = new byte[OpusDecoder.getMaxOutputShorts()*2];
|
pcmData = pcmRing[ringIndex];
|
||||||
decodeLen = OpusDecoder.decode(data, off, len, pcmData);
|
decodeLen = OpusDecoder.decode(data, off, len, pcmData);
|
||||||
|
ringIndex = (ringIndex + 1) % DU_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (decodeLen > 0) {
|
if (decodeLen > 0) {
|
||||||
// Return value of decode is frames (shorts) decoded per channel
|
// Return value of decode is frames (shorts) decoded per channel
|
||||||
decodeLen *= 2*OpusDecoder.getChannelCount();
|
decodeLen *= 2*OpusDecoder.getChannelCount();
|
||||||
|
@ -24,8 +24,14 @@ public class VideoStream {
|
|||||||
|
|
||||||
public static final int FIRST_FRAME_TIMEOUT = 5000;
|
public static final int FIRST_FRAME_TIMEOUT = 5000;
|
||||||
public static final int RTP_RECV_BUFFER = 128 * 1024;
|
public static final int RTP_RECV_BUFFER = 128 * 1024;
|
||||||
|
|
||||||
public static final int MAX_PACKET_SIZE = 1050;
|
public static final int MAX_PACKET_SIZE = 1050;
|
||||||
|
|
||||||
|
// The ring size MUST be greater than or equal to
|
||||||
|
// the maximum number of packets in a fully
|
||||||
|
// presentable frame
|
||||||
|
public static final int VIDEO_RING_SIZE = 192;
|
||||||
|
|
||||||
private InetAddress host;
|
private InetAddress host;
|
||||||
private DatagramSocket rtp;
|
private DatagramSocket rtp;
|
||||||
private Socket firstFrameSocket;
|
private Socket firstFrameSocket;
|
||||||
@ -211,22 +217,36 @@ public class VideoStream {
|
|||||||
Thread t = new Thread() {
|
Thread t = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ByteBufferDescriptor desc = new ByteBufferDescriptor(new byte[MAX_PACKET_SIZE], 0, MAX_PACKET_SIZE);
|
ByteBufferDescriptor ring[] = new ByteBufferDescriptor[VIDEO_RING_SIZE];
|
||||||
DatagramPacket packet = new DatagramPacket(desc.data, desc.length);
|
int ringIndex = 0;
|
||||||
|
|
||||||
|
// Preinitialize the ring buffer
|
||||||
|
for (int i = 0; i < VIDEO_RING_SIZE; i++) {
|
||||||
|
ring[i] = new ByteBufferDescriptor(new byte[MAX_PACKET_SIZE], 0, MAX_PACKET_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBufferDescriptor desc;
|
||||||
|
DatagramPacket packet = new DatagramPacket(new byte[1], 1); // Placeholder array
|
||||||
while (!isInterrupted())
|
while (!isInterrupted())
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// Pull the next buffer in the ring and reset it
|
||||||
|
desc = ring[ringIndex];
|
||||||
|
desc.length = MAX_PACKET_SIZE;
|
||||||
|
desc.offset = 0;
|
||||||
|
|
||||||
|
// Read the video data off the network
|
||||||
|
packet.setData(desc.data, desc.offset, desc.length);
|
||||||
rtp.receive(packet);
|
rtp.receive(packet);
|
||||||
|
|
||||||
|
// Submit video data to the depacketizer
|
||||||
desc.length = packet.getLength();
|
desc.length = packet.getLength();
|
||||||
depacketizer.addInputData(new RtpPacket(desc));
|
depacketizer.addInputData(new RtpPacket(desc));
|
||||||
desc.reinitialize(new byte[MAX_PACKET_SIZE], 0, MAX_PACKET_SIZE);
|
ringIndex = (ringIndex + 1) % VIDEO_RING_SIZE;
|
||||||
packet.setData(desc.data, desc.offset, desc.length);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
listener.connectionTerminated(e);
|
listener.connectionTerminated(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user