|
|
@ -7,6 +7,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
|
|
|
|
|
|
import android.util.Log;
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import net.ossrs.sea.rtmp.RtmpPublisher;
|
|
|
|
import net.ossrs.sea.rtmp.packets.Command;
|
|
|
|
import net.ossrs.sea.rtmp.packets.Command;
|
|
|
|
import net.ossrs.sea.rtmp.packets.RtmpPacket;
|
|
|
|
import net.ossrs.sea.rtmp.packets.RtmpPacket;
|
|
|
|
import net.ossrs.sea.rtmp.packets.Video;
|
|
|
|
import net.ossrs.sea.rtmp.packets.Video;
|
|
|
@ -20,18 +22,22 @@ public class WriteThread extends Thread {
|
|
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "WriteThread";
|
|
|
|
private static final String TAG = "WriteThread";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private RtmpPublisher.EventHandler handler;
|
|
|
|
private RtmpSessionInfo rtmpSessionInfo;
|
|
|
|
private RtmpSessionInfo rtmpSessionInfo;
|
|
|
|
private OutputStream out;
|
|
|
|
private OutputStream out;
|
|
|
|
private ConcurrentLinkedQueue<RtmpPacket> writeQueue = new ConcurrentLinkedQueue<RtmpPacket>();
|
|
|
|
private ConcurrentLinkedQueue<RtmpPacket> writeQueue = new ConcurrentLinkedQueue<RtmpPacket>();
|
|
|
|
private final Object txPacketLock = new Object();
|
|
|
|
private final Object txPacketLock = new Object();
|
|
|
|
private volatile boolean active = true;
|
|
|
|
private volatile boolean active = true;
|
|
|
|
|
|
|
|
private int videoFrameCount;
|
|
|
|
|
|
|
|
private long lastTimeMillis;
|
|
|
|
private AtomicInteger videoFrameCacheNumber;
|
|
|
|
private AtomicInteger videoFrameCacheNumber;
|
|
|
|
|
|
|
|
|
|
|
|
public WriteThread(RtmpSessionInfo rtmpSessionInfo, OutputStream out, AtomicInteger count) {
|
|
|
|
public WriteThread(RtmpSessionInfo rtmpSessionInfo, OutputStream out, AtomicInteger count, RtmpPublisher.EventHandler handler) {
|
|
|
|
super("RtmpWriteThread");
|
|
|
|
super("RtmpWriteThread");
|
|
|
|
this.rtmpSessionInfo = rtmpSessionInfo;
|
|
|
|
this.rtmpSessionInfo = rtmpSessionInfo;
|
|
|
|
this.out = out;
|
|
|
|
this.out = out;
|
|
|
|
this.videoFrameCacheNumber = count;
|
|
|
|
this.videoFrameCacheNumber = count;
|
|
|
|
|
|
|
|
this.handler = handler;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
@ -51,6 +57,7 @@ public class WriteThread extends Thread {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rtmpPacket instanceof Video) {
|
|
|
|
if (rtmpPacket instanceof Video) {
|
|
|
|
videoFrameCacheNumber.getAndDecrement();
|
|
|
|
videoFrameCacheNumber.getAndDecrement();
|
|
|
|
|
|
|
|
calcFps();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out.flush();
|
|
|
|
out.flush();
|
|
|
@ -100,4 +107,17 @@ public class WriteThread extends Thread {
|
|
|
|
txPacketLock.notify();
|
|
|
|
txPacketLock.notify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void calcFps() {
|
|
|
|
|
|
|
|
if (videoFrameCount == 0) {
|
|
|
|
|
|
|
|
lastTimeMillis = System.nanoTime() / 1000000;
|
|
|
|
|
|
|
|
videoFrameCount++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (++videoFrameCount >= 48) {
|
|
|
|
|
|
|
|
long diffTimeMillis = System.nanoTime() / 1000000 - lastTimeMillis;
|
|
|
|
|
|
|
|
handler.onRtmpOutputFps((double) videoFrameCount * 1000 / diffTimeMillis);
|
|
|
|
|
|
|
|
videoFrameCount = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|