Skip to content
Snippets Groups Projects
Commit 2767ac54 authored by Leo Ma's avatar Leo Ma
Browse files

GC optimization


Reduce the count of garbage collection in data flow and improve the
reusability of the data buffer.

Signed-off-by: default avatarLeo Ma <begeekmyfriend@gmail.com>
parent e24eeb9b
No related branches found
No related tags found
No related merge requests found
Showing
with 428 additions and 244 deletions
package com.github.faucamp.simplertmp;
 
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
 
import com.github.faucamp.simplertmp.io.RtmpConnection;
Loading
Loading
@@ -34,13 +33,13 @@ public class DefaultRtmpPublisher implements RtmpPublisher {
}
 
@Override
public void publishVideoData(byte[] data, int dts) {
rtmpConnection.publishVideoData(data, dts);
public void publishVideoData(byte[] data, int size, int dts) {
rtmpConnection.publishVideoData(data, size, dts);
}
 
@Override
public void publishAudioData(byte[] data, int dts) {
rtmpConnection.publishAudioData(data, dts);
public void publishAudioData(byte[] data, int size, int dts) {
rtmpConnection.publishAudioData(data, size, dts);
}
 
@Override
Loading
Loading
package com.github.faucamp.simplertmp;
 
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
 
/**
Loading
Loading
@@ -38,17 +37,19 @@ public interface RtmpPublisher {
* publish a video content packet to server
*
* @param data video stream byte array
* @param size video stream byte size (not the whole length of byte array)
* @param dts video stream decoding timestamp
*/
void publishVideoData(byte[] data, int dts);
void publishVideoData(byte[] data, int size, int dts);
 
/**
* publish an audio content packet to server
*
* @param data audio stream byte array
* @param size audio stream byte size (not the whole length of byte array)
* @param dts audio stream decoding timestamp
*/
void publishAudioData(byte[] data, int dts);
void publishAudioData(byte[] data, int size, int dts);
 
/**
* obtain video frame number cached in publisher
Loading
Loading
Loading
Loading
@@ -391,7 +391,7 @@ public class RtmpConnection implements RtmpPublisher {
}
 
@Override
public void publishAudioData(byte[] data, int dts) {
public void publishAudioData(byte[] data, int size, int dts) {
if (data == null || data.length == 0 || dts < 0) {
mHandler.notifyRtmpIllegalArgumentException(new IllegalArgumentException("Invalid Audio Data"));
return;
Loading
Loading
@@ -409,7 +409,7 @@ public class RtmpConnection implements RtmpPublisher {
return;
}
Audio audio = new Audio();
audio.setData(data);
audio.setData(data, size);
audio.getHeader().setAbsoluteTimestamp(dts);
audio.getHeader().setMessageStreamId(currentStreamId);
sendRtmpPacket(audio);
Loading
Loading
@@ -418,7 +418,7 @@ public class RtmpConnection implements RtmpPublisher {
}
 
@Override
public void publishVideoData(byte[] data, int dts) {
public void publishVideoData(byte[] data, int size, int dts) {
if (data == null || data.length == 0 || dts < 0) {
mHandler.notifyRtmpIllegalArgumentException(new IllegalArgumentException("Invalid Video Data"));
return;
Loading
Loading
@@ -436,7 +436,7 @@ public class RtmpConnection implements RtmpPublisher {
return;
}
Video video = new Video();
video.setData(data);
video.setData(data, size);
video.getHeader().setAbsoluteTimestamp(dts);
video.getHeader().setMessageStreamId(currentStreamId);
sendRtmpPacket(video);
Loading
Loading
Loading
Loading
@@ -41,6 +41,16 @@ public class Abort extends RtmpPacket {
chunkStreamId = Util.readUnsignedInt32(in);
}
 
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
@Override
protected void writeBody(OutputStream out) throws IOException {
Util.writeUnsignedInt32(out, chunkStreamId);
Loading
Loading
Loading
Loading
@@ -56,6 +56,16 @@ public class Acknowledgement extends RtmpPacket {
Util.writeUnsignedInt32(out, sequenceNumber);
}
 
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
@Override
public String toString() {
return "RTMP Acknowledgment (sequence number: " + sequenceNumber + ")";
Loading
Loading
Loading
Loading
@@ -73,7 +73,17 @@ public class Command extends VariableBodyRtmpPacket {
// Write body data
writeVariableData(out);
}
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
@Override
public String toString() {
return "RTMP Command (command: " + commandName + ", transaction ID: " + transactionId + ")";
Loading
Loading
package com.github.faucamp.simplertmp.packets;
 
import android.support.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Loading
Loading
@@ -14,6 +16,7 @@ import com.github.faucamp.simplertmp.Util;
public abstract class ContentData extends RtmpPacket {
 
protected byte[] data;
protected int size;
 
public ContentData(RtmpHeader header) {
super(header);
Loading
Loading
@@ -23,8 +26,9 @@ public abstract class ContentData extends RtmpPacket {
return data;
}
 
public void setData(byte[] data) {
public void setData(byte[] data, int size) {
this.data = data;
this.size = size;
}
 
@Override
Loading
Loading
@@ -40,6 +44,15 @@ public abstract class ContentData extends RtmpPacket {
*/
@Override
public void writeBody(OutputStream out) throws IOException {
out.write(data);
}
@Override
public byte[] array() {
return data;
}
@Override
public int size() {
return size;
}
}
Loading
Loading
@@ -53,8 +53,18 @@ public class Data extends VariableBodyRtmpPacket {
* another output stream
*/
@Override
public void writeBody(OutputStream out) throws IOException {
protected void writeBody(OutputStream out) throws IOException {
AmfString.writeStringTo(out, type, false);
writeVariableData(out);
}
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
}
package com.github.faucamp.simplertmp.packets;
 
import android.content.res.Configuration;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
Loading
Loading
@@ -26,24 +28,28 @@ public abstract class RtmpPacket {
public abstract void readBody(InputStream in) throws IOException;
protected abstract void writeBody(OutputStream out) throws IOException;
public void writeTo(OutputStream out, final int chunkSize, final ChunkStreamInfo chunkStreamInfo) throws IOException {
protected abstract byte[] array();
protected abstract int size();
public void writeTo(OutputStream out, final int chunkSize, final ChunkStreamInfo chunkStreamInfo) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
writeBody(baos);
byte[] body = baos.toByteArray();
header.setPacketLength(body.length);
writeBody(baos);
byte[] body = this instanceof ContentData ? array() : baos.toByteArray();
int length = this instanceof ContentData ? size() : body.length;
header.setPacketLength(length);
// Write header for first chunk
header.writeTo(out, RtmpHeader.ChunkType.TYPE_0_FULL, chunkStreamInfo);
int remainingBytes = body.length;
int pos = 0;
while (remainingBytes > chunkSize) {
while (length > chunkSize) {
// Write packet for chunk
out.write(body, pos, chunkSize);
remainingBytes -= chunkSize;
length -= chunkSize;
pos += chunkSize;
// Write header for remain chunk
header.writeTo(out, RtmpHeader.ChunkType.TYPE_3_RELATIVE_SINGLE_BYTE, chunkStreamInfo);
}
out.write(body, pos, remainingBytes);
out.write(body, pos, length);
}
}
Loading
Loading
@@ -43,4 +43,14 @@ public class SetChunkSize extends RtmpPacket {
protected void writeBody(OutputStream out) throws IOException {
Util.writeUnsignedInt32(out, chunkSize);
}
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
}
Loading
Loading
@@ -97,7 +97,17 @@ public class SetPeerBandwidth extends RtmpPacket {
Util.writeUnsignedInt32(out, acknowledgementWindowSize);
out.write(limitType.getIntValue());
}
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
@Override
public String toString() {
return "RTMP Set Peer Bandwidth";
Loading
Loading
Loading
Loading
@@ -235,6 +235,16 @@ public class UserControl extends RtmpPacket {
}
}
 
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
@Override
public String toString() {
return "RTMP User Control (type: " + type + ", event data: " + eventData + ")";
Loading
Loading
Loading
Loading
@@ -42,10 +42,20 @@ public class WindowAckSize extends RtmpPacket {
}
 
@Override
protected void writeBody(OutputStream out) throws IOException {
protected void writeBody(OutputStream out) throws IOException {
Util.writeUnsignedInt32(out, acknowledgementWindowSize);
}
@Override
protected byte[] array() {
return null;
}
@Override
protected int size() {
return 0;
}
@Override
public String toString() {
return "RTMP Window Acknowledgment Size";
Loading
Loading
package net.ossrs.yasea;
import java.util.Arrays;
public final class SrsAllocator {
public class Allocation {
private byte[] data;
private int size;
public Allocation(int size) {
this.data = new byte[size];
this.size = 0;
}
public byte[] array() {
return data;
}
public int size() {
return size;
}
public void appendOffset(int offset) {
size += offset;
}
public void clear() {
size = 0;
}
public void put(byte b) {
data[size++] = b;
}
public void put(byte b, int pos) {
data[pos++] = b;
size = pos > size ? pos : size;
}
public void put(short s) {
put((byte) s);
put((byte) (s >>> 8));
}
public void put(int i) {
put((byte) i);
put((byte) (i >>> 8));
put((byte) (i >>> 16));
put((byte) (i >>> 24));
}
public void put(byte[] bs) {
System.arraycopy(bs, 0, data, size, bs.length);
size += bs.length;
}
}
private final int individualAllocationSize;
private final Allocation[] singleAllocationReleaseHolder;
private volatile int allocatedCount;
private volatile int availableCount;
private Allocation[] availableAllocations;
/**
* Constructs an instance without creating any {@link Allocation}s up front.
*
* @param individualAllocationSize The length of each individual {@link Allocation}.
*/
public SrsAllocator(int individualAllocationSize) {
this(individualAllocationSize, 0);
}
/**
* Constructs an instance with some {@link Allocation}s created up front.
* <p>
*
* @param individualAllocationSize The length of each individual {@link Allocation}.
* @param initialAllocationCount The number of allocations to create up front.
*/
public SrsAllocator(int individualAllocationSize, int initialAllocationCount) {
this.individualAllocationSize = individualAllocationSize;
this.availableCount = initialAllocationCount + 10;
this.availableAllocations = new Allocation[availableCount];
for (int i = 0; i < availableCount; i++) {
availableAllocations[i] = new Allocation(individualAllocationSize);
}
singleAllocationReleaseHolder = new Allocation[1];
}
public synchronized Allocation allocate() {
allocatedCount++;
Allocation allocation;
if (availableCount > 0) {
allocation = availableAllocations[--availableCount];
availableAllocations[availableCount] = null;
} else {
allocation = new Allocation(individualAllocationSize);
}
return allocation;
}
public synchronized void release(Allocation allocation) {
singleAllocationReleaseHolder[0] = allocation;
release(singleAllocationReleaseHolder);
}
public synchronized void release(Allocation[] allocations) {
if (availableCount + allocations.length >= availableAllocations.length) {
availableAllocations = Arrays.copyOf(availableAllocations,
Math.max(availableAllocations.length * 2, availableCount + allocations.length));
}
for (Allocation allocation : allocations) {
allocation.clear();
availableAllocations[availableCount++] = allocation;
}
allocatedCount -= allocations.length;
}
public synchronized int getTotalBytesAllocated() {
return allocatedCount * individualAllocationSize;
}
}
This diff is collapsed.
package net.ossrs.yasea;
import android.content.Context;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.audiofx.AcousticEchoCanceler;
import android.media.audiofx.AutomaticGainControl;
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment