|
|
@ -67,6 +67,8 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
private AmfString serverIpAddr;
|
|
|
|
private AmfString serverIpAddr;
|
|
|
|
private AmfNumber serverPid;
|
|
|
|
private AmfNumber serverPid;
|
|
|
|
private AmfNumber serverId;
|
|
|
|
private AmfNumber serverId;
|
|
|
|
|
|
|
|
private int videoWidth;
|
|
|
|
|
|
|
|
private int videoHeight;
|
|
|
|
|
|
|
|
|
|
|
|
public RtmpConnection(RtmpPublisher.EventHandler handler) {
|
|
|
|
public RtmpConnection(RtmpPublisher.EventHandler handler) {
|
|
|
|
mHandler = handler;
|
|
|
|
mHandler = handler;
|
|
|
@ -114,7 +116,7 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
Log.d(TAG, "connect(): handshake done");
|
|
|
|
Log.d(TAG, "connect(): handshake done");
|
|
|
|
rtmpSessionInfo = new RtmpSessionInfo();
|
|
|
|
rtmpSessionInfo = new RtmpSessionInfo();
|
|
|
|
readThread = new ReadThread(rtmpSessionInfo, in, this);
|
|
|
|
readThread = new ReadThread(rtmpSessionInfo, in, this);
|
|
|
|
writeThread = new WriteThread(rtmpSessionInfo, out, videoFrameCacheNumber, mHandler);
|
|
|
|
writeThread = new WriteThread(rtmpSessionInfo, out, this);
|
|
|
|
readThread.start();
|
|
|
|
readThread.start();
|
|
|
|
writeThread.start();
|
|
|
|
writeThread.start();
|
|
|
|
|
|
|
|
|
|
|
@ -251,11 +253,22 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "onMetaData(): Sending empty onMetaData...");
|
|
|
|
Log.d(TAG, "onMetaData(): Sending empty onMetaData...");
|
|
|
|
Data emptyMetaData = new Data("@setDataFrame");
|
|
|
|
Data metadata = new Data("@setDataFrame");
|
|
|
|
emptyMetaData.addData("onMetaData");
|
|
|
|
metadata.getHeader().setMessageStreamId(currentStreamId);
|
|
|
|
emptyMetaData.addData(new AmfNull());
|
|
|
|
metadata.addData("onMetaData");
|
|
|
|
emptyMetaData.getHeader().setMessageStreamId(currentStreamId);
|
|
|
|
AmfMap ecmaArray = new AmfMap();
|
|
|
|
writeThread.send(emptyMetaData);
|
|
|
|
ecmaArray.setProperty("duration", 0);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("width", videoWidth);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("height", videoHeight);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("videodatarate", 0);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("framerate", 0);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("audiodatarate", 0);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("audiosamplerate", 44100);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("audiosamplesize", 16);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("stereo", true);
|
|
|
|
|
|
|
|
ecmaArray.setProperty("filesize", 0);
|
|
|
|
|
|
|
|
metadata.addData(ecmaArray);
|
|
|
|
|
|
|
|
writeThread.send(metadata);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
@ -281,14 +294,18 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void shutdown() {
|
|
|
|
public void shutdown() {
|
|
|
|
if (active) {
|
|
|
|
if (active) {
|
|
|
|
// shutdown read thread
|
|
|
|
readThread.shutdown();
|
|
|
|
|
|
|
|
writeThread.shutdown();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
// It will invoke EOFException in read thread
|
|
|
|
// It will invoke EOFException in read thread
|
|
|
|
socket.shutdownInput();
|
|
|
|
socket.shutdownInput();
|
|
|
|
|
|
|
|
// It will invoke SocketException in write thread
|
|
|
|
|
|
|
|
socket.shutdownOutput();
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
ioe.printStackTrace();
|
|
|
|
ioe.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
readThread.shutdown();
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
readThread.join();
|
|
|
|
readThread.join();
|
|
|
|
} catch (InterruptedException ie) {
|
|
|
|
} catch (InterruptedException ie) {
|
|
|
@ -296,8 +313,6 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
readThread.interrupt();
|
|
|
|
readThread.interrupt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// shutdown write thread
|
|
|
|
|
|
|
|
writeThread.shutdown();
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
writeThread.join();
|
|
|
|
writeThread.join();
|
|
|
|
} catch (InterruptedException ie) {
|
|
|
|
} catch (InterruptedException ie) {
|
|
|
@ -412,7 +427,7 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
case ABORT:
|
|
|
|
case ABORT:
|
|
|
|
rtmpSessionInfo.getChunkStreamInfo(((Abort) rtmpPacket).getChunkStreamId()).clearStoredChunks();
|
|
|
|
rtmpSessionInfo.getChunkStreamInfo(((Abort) rtmpPacket).getChunkStreamId()).clearStoredChunks();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case USER_CONTROL_MESSAGE: {
|
|
|
|
case USER_CONTROL_MESSAGE:
|
|
|
|
UserControl ping = (UserControl) rtmpPacket;
|
|
|
|
UserControl ping = (UserControl) rtmpPacket;
|
|
|
|
switch (ping.getType()) {
|
|
|
|
switch (ping.getType()) {
|
|
|
|
case PING_REQUEST:
|
|
|
|
case PING_REQUEST:
|
|
|
@ -426,7 +441,6 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WINDOW_ACKNOWLEDGEMENT_SIZE:
|
|
|
|
case WINDOW_ACKNOWLEDGEMENT_SIZE:
|
|
|
|
WindowAckSize windowAckSize = (WindowAckSize) rtmpPacket;
|
|
|
|
WindowAckSize windowAckSize = (WindowAckSize) rtmpPacket;
|
|
|
|
int size = windowAckSize.getAcknowledgementWindowSize();
|
|
|
|
int size = windowAckSize.getAcknowledgementWindowSize();
|
|
|
@ -499,6 +513,7 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
} else if (commandName.equals("onStatus")) {
|
|
|
|
} else if (commandName.equals("onStatus")) {
|
|
|
|
String code = ((AmfString) ((AmfObject) invoke.getData().get(1)).getProperty("code")).getValue();
|
|
|
|
String code = ((AmfString) ((AmfObject) invoke.getData().get(1)).getProperty("code")).getValue();
|
|
|
|
if (code.equals("NetStream.Publish.Start")) {
|
|
|
|
if (code.equals("NetStream.Publish.Start")) {
|
|
|
|
|
|
|
|
onMetaData();
|
|
|
|
// We can now publish AV data
|
|
|
|
// We can now publish AV data
|
|
|
|
publishPermitted = true;
|
|
|
|
publishPermitted = true;
|
|
|
|
synchronized (publishLock) {
|
|
|
|
synchronized (publishLock) {
|
|
|
@ -526,19 +541,34 @@ public class RtmpConnection implements RtmpPublisher, PacketRxHandler {
|
|
|
|
return info;
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public final int getVideoFrameCacheNumber() {
|
|
|
|
@Override
|
|
|
|
return videoFrameCacheNumber.get();
|
|
|
|
public AtomicInteger getVideoFrameCacheNumber() {
|
|
|
|
|
|
|
|
return videoFrameCacheNumber;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public EventHandler getEventHandler() {
|
|
|
|
|
|
|
|
return mHandler;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public final String getServerIpAddr() {
|
|
|
|
public final String getServerIpAddr() {
|
|
|
|
return serverIpAddr == null ? null : serverIpAddr.getValue();
|
|
|
|
return serverIpAddr == null ? null : serverIpAddr.getValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public final int getServerPid() {
|
|
|
|
public final int getServerPid() {
|
|
|
|
return serverPid == null ? 0 : (int) serverPid.getValue();
|
|
|
|
return serverPid == null ? 0 : (int) serverPid.getValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public final int getServerId() {
|
|
|
|
public final int getServerId() {
|
|
|
|
return serverId == null ? 0 : (int) serverId.getValue();
|
|
|
|
return serverId == null ? 0 : (int) serverId.getValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void setVideoResolution(int width, int height) {
|
|
|
|
|
|
|
|
videoWidth = width;
|
|
|
|
|
|
|
|
videoHeight = height;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|