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

Optimize RTMP read thread off


Signed-off-by: default avatarLeo Ma <begeekmyfriend@gmail.com>
parent 7e8e2338
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -21,7 +21,7 @@ Feature
Test
----
 
You may watch the live broadcasting at [srs.net](http://www.ossrs.net/players/srs_player.html).
You may build your own private RTMP server [srs](https://github.com/ossrs/srs/tree/2.0release).
Remember to modify the URL by yourself. Have fun!
 
**NOTE** if you feel high latency, please check your bandwidth limits and player buffering.
Loading
Loading
@@ -40,3 +40,8 @@ Thanks
- [MagicCamera](https://github.com/begeekmyfriend/MagicCamera)
- [x264](http://www.videolan.org/developers/x264.html)
- [mp4parser](https://android.googlesource.com/platform/external/mp4parser)
Sponsor
-------
- [dotEngine](https://dot.cc) -- A brilliant realtime multimedia communication service vendor with open cross-platform SDK ([github](https://github.com/dotEngine)).
Loading
Loading
@@ -31,7 +31,7 @@ public class MainActivity extends Activity {
Button btnSwitchEncoder = null;
 
private SharedPreferences sp;
private String rtmpUrl = "rtmp://ossrs.net/" + getRandomAlphaString(3) + '/' + getRandomAlphaDigitString(5);
private String rtmpUrl = "rtmp://0.0.0.0/" + getRandomAlphaString(3) + '/' + getRandomAlphaDigitString(5);
private String recPath = Environment.getExternalStorageDirectory().getPath() + "/test.mp4";
 
private SrsPublisher mPublisher;
Loading
Loading
Loading
Loading
@@ -38,8 +38,6 @@ public class SrsEncoder {
public static int aChannelConfig = AudioFormat.CHANNEL_IN_STEREO;
public static final int ABITRATE = 32 * 1000; // 32kbps
private EventHandler mHandler;
private boolean onNetworkWeakTriggered = false;
private int mOrientation = Configuration.ORIENTATION_PORTRAIT;
private SrsFlvMuxer flvMuxer;
Loading
Loading
@@ -51,6 +49,8 @@ public class SrsEncoder {
private MediaCodec.BufferInfo vebi = new MediaCodec.BufferInfo();
private MediaCodec.BufferInfo aebi = new MediaCodec.BufferInfo();
private EventHandler mHandler;
private boolean networkWeakTriggered = false;
private boolean mCameraFaceFront = true;
private boolean useSoftEncoder = false;
Loading
Loading
@@ -63,7 +63,7 @@ public class SrsEncoder {
private int audioFlvTrack;
private int audioMp4Track;
interface EventHandler {
public interface EventHandler {
void onNetworkResume(String msg);
Loading
Loading
@@ -393,13 +393,13 @@ public class SrsEncoder {
}
}
if (onNetworkWeakTriggered) {
onNetworkWeakTriggered = false;
if (networkWeakTriggered) {
networkWeakTriggered = false;
mHandler.onNetworkResume("Network resume");
}
} else {
mHandler.onNetworkWeak("Network weak");
onNetworkWeakTriggered = true;
networkWeakTriggered = true;
}
}
Loading
Loading
@@ -481,13 +481,13 @@ public class SrsEncoder {
}
}
if (onNetworkWeakTriggered) {
onNetworkWeakTriggered = false;
if (networkWeakTriggered) {
networkWeakTriggered = false;
mHandler.onNetworkResume("Network resume");
}
} else {
mHandler.onNetworkWeak("Network weak");
onNetworkWeakTriggered = true;
networkWeakTriggered = true;
}
}
Loading
Loading
Loading
Loading
@@ -10,7 +10,7 @@ import java.util.ArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
 
import net.ossrs.yasea.rtmp.RtmpPublisher;
import net.ossrs.yasea.rtmp.DefaultRtmpPublisher;
 
/**
* Created by winlin on 5/2/15.
Loading
Loading
@@ -46,7 +46,7 @@ import net.ossrs.yasea.rtmp.RtmpPublisher;
*/
public class SrsFlvMuxer {
private volatile boolean connected = false;
private SrsRtmpPublisher publisher;
private DefaultRtmpPublisher publisher;
 
private Thread worker;
private final Object txFrameLock = new Object();
Loading
Loading
@@ -66,8 +66,8 @@ public class SrsFlvMuxer {
* constructor.
* @param handler the rtmp event handler.
*/
public SrsFlvMuxer(RtmpPublisher.EventHandler handler) {
publisher = new SrsRtmpPublisher(handler);
public SrsFlvMuxer(DefaultRtmpPublisher.EventHandler handler) {
publisher = new DefaultRtmpPublisher(handler);
}
 
/**
Loading
Loading
Loading
Loading
@@ -112,7 +112,7 @@ public class SrsMp4Muxer {
/**
* MP4 recording event handler.
*/
interface EventHandler {
public interface EventHandler {
void onRecordPause(String msg);
Loading
Loading
Loading
Loading
@@ -35,7 +35,6 @@ public class SrsPublisher {
public SrsPublisher(SrsCameraView view) {
mCameraView = view;
mEncoder = new SrsEncoder();
mCameraView.setPreviewResolution(mEncoder.getPreviewWidth(), mEncoder.getPreviewHeight());
mCameraView.setPreviewCallback(new SrsCameraView.PreviewCallback() {
@Override
Loading
Loading
@@ -163,9 +162,11 @@ public class SrsPublisher {
public int getPreviewWidth() {
return mEncoder.getPreviewWidth();
}
public int getPreviewHeight() {
return mEncoder.getPreviewHeight();
}
public double getmSamplingFps() {
return mSamplingFps;
}
Loading
Loading
package net.ossrs.yasea;
package net.ossrs.yasea.rtmp;
 
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
 
import net.ossrs.yasea.rtmp.RtmpPublisher;
import net.ossrs.yasea.rtmp.io.RtmpConnection;
 
/**
Loading
Loading
@@ -11,11 +10,11 @@ import net.ossrs.yasea.rtmp.io.RtmpConnection;
*
* @author francois, leoma
*/
public class SrsRtmpPublisher implements RtmpPublisher {
public class DefaultRtmpPublisher implements RtmpPublisher {
 
private RtmpConnection rtmpConnection;
 
public SrsRtmpPublisher(RtmpPublisher.EventHandler handler) {
public DefaultRtmpPublisher(RtmpPublisher.EventHandler handler) {
rtmpConnection = new RtmpConnection(handler);
}
 
Loading
Loading
package net.ossrs.yasea.rtmp.io;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import android.util.Log;
import net.ossrs.yasea.rtmp.packets.RtmpPacket;
/**
* RTMPConnection's read thread
*
* @author francois, leo
*/
public class ReadThread extends Thread {
private static final String TAG = "ReadThread";
private RtmpDecoder rtmpDecoder;
private InputStream in;
private RtmpConnection.PacketRxHandler packetRxHandler;
public ReadThread(RtmpSessionInfo rtmpSessionInfo, InputStream in, RtmpConnection.PacketRxHandler packetRxHandler) {
super("RtmpReadThread");
this.in = in;
this.packetRxHandler = packetRxHandler;
this.rtmpDecoder = new RtmpDecoder(rtmpSessionInfo);
}
@Override
public void run() {
while (!Thread.interrupted()) {
try {
// It will be blocked when no data in input stream buffer
RtmpPacket rtmpPacket = rtmpDecoder.readPacket(in);
packetRxHandler.handleRxPacket(rtmpPacket);
} catch (EOFException eof) {
this.interrupt();
// } catch (WindowAckRequired war) {
// Log.i(TAG, "Window Acknowledgment required, notifying packet handler...");
// packetRxHandler.notifyWindowAckRequired(war.getBytesRead());
// if (war.getRtmpPacket() != null) {
// // Pass to handler
// packetRxHandler.handleRxPacket(war.getRtmpPacket());
// }
} catch (SocketException se) {
Log.e(TAG, "ReadThread: Caught SocketException while reading/decoding packet, shutting down: " + se.getMessage());
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(this, se);
} catch (IOException ioe) {
Log.e(TAG, "ReadThread: Caught exception while reading/decoding packet, shutting down: " + ioe.getMessage());
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(this, ioe);
}
}
Log.i(TAG, "exit");
}
public void shutdown() {
Log.d(TAG, "Stopping");
}
}
Loading
Loading
@@ -2,6 +2,7 @@ package net.ossrs.yasea.rtmp.io;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Loading
Loading
@@ -30,6 +31,7 @@ import net.ossrs.yasea.rtmp.packets.Data;
import net.ossrs.yasea.rtmp.packets.Handshake;
import net.ossrs.yasea.rtmp.packets.Command;
import net.ossrs.yasea.rtmp.packets.Audio;
import net.ossrs.yasea.rtmp.packets.SetPeerBandwidth;
import net.ossrs.yasea.rtmp.packets.Video;
import net.ossrs.yasea.rtmp.packets.UserControl;
import net.ossrs.yasea.rtmp.packets.RtmpPacket;
Loading
Loading
@@ -46,24 +48,6 @@ public class RtmpConnection implements RtmpPublisher {
private static final Pattern rtmpUrlPattern = Pattern.compile("^rtmp://([^/:]+)(:(\\d+))*/([^/]+)(/(.*))*$");
 
private RtmpPublisher.EventHandler mHandler;
private PacketRxHandler rxHandler = new PacketRxHandler() {
@Override
public void handleRxPacket(RtmpPacket rtmpPacket) {
if (rtmpPacket != null) {
rxPacketQueue.add(rtmpPacket);
}
synchronized (rxPacketLock) {
rxPacketLock.notify();
}
}
@Override
public void notifyWindowAckRequired(final int numBytesReadThusFar) {
Log.i(TAG, "notifyWindowAckRequired() called");
// Create and send window bytes read acknowledgement
sendRtmpPacket(new Acknowledgement(numBytesReadThusFar));
}
};
private String appName;
private String streamName;
private String publishType;
Loading
Loading
@@ -71,20 +55,18 @@ public class RtmpConnection implements RtmpPublisher {
private String tcUrl;
private String pageUrl;
private Socket socket;
private RtmpSessionInfo rtmpSessionInfo;
private RtmpSessionInfo rtmpSessionInfo = new RtmpSessionInfo();
private RtmpDecoder rtmpDecoder = new RtmpDecoder(rtmpSessionInfo);
private BufferedInputStream inputStream;
private BufferedOutputStream outputStream;
private ReadThread readThread;
private final ConcurrentLinkedQueue<RtmpPacket> rxPacketQueue = new ConcurrentLinkedQueue<>();
private final Object rxPacketLock = new Object();
private volatile boolean active = false;
private Thread rxPacketHandler;
private volatile boolean connecting = false;
private volatile boolean fullyConnected = false;
private volatile boolean publishPermitted = false;
private final Object connectingLock = new Object();
private final Object publishLock = new Object();
private AtomicInteger videoFrameCacheNumber = new AtomicInteger(0);
private int currentStreamId = -1;
private int currentStreamId = 0;
private int transactionIdCounter = 0;
private AmfString serverIpAddr;
private AmfNumber serverPid;
Loading
Loading
@@ -117,8 +99,8 @@ public class RtmpConnection implements RtmpPublisher {
Matcher matcher = rtmpUrlPattern.matcher(url);
if (matcher.matches()) {
tcUrl = url.substring(0, url.lastIndexOf('/'));
swfUrl = "";
pageUrl = "";
swfUrl = "";
pageUrl = "";
host = matcher.group(1);
String portStr = matcher.group(3);
port = portStr != null ? Integer.parseInt(portStr) : 1935;
Loading
Loading
@@ -137,14 +119,10 @@ public class RtmpConnection implements RtmpPublisher {
outputStream = new BufferedOutputStream(socket.getOutputStream());
Log.d(TAG, "connect(): socket connection established, doing handhake...");
handshake(inputStream, outputStream);
active = true;
Log.d(TAG, "connect(): handshake done");
rtmpSessionInfo = new RtmpSessionInfo();
readThread = new ReadThread(rtmpSessionInfo, inputStream, rxHandler);
readThread.start();
 
// Start the "main" handling thread
new Thread(new Runnable() {
rxPacketHandler = new Thread(new Runnable() {
 
@Override
public void run() {
Loading
Loading
@@ -155,7 +133,8 @@ public class RtmpConnection implements RtmpPublisher {
Logger.getLogger(RtmpConnection.class.getName()).log(Level.SEVERE, null, ex);
}
}
}).start();
});
rxPacketHandler.start();
 
rtmpConnect();
}
Loading
Loading
@@ -211,7 +190,7 @@ public class RtmpConnection implements RtmpPublisher {
if (!fullyConnected) {
throw new IllegalStateException("Not connected to RTMP server");
}
if (currentStreamId != -1) {
if (currentStreamId != 0) {
throw new IllegalStateException("Current stream object has existed");
}
 
Loading
Loading
@@ -252,7 +231,7 @@ public class RtmpConnection implements RtmpPublisher {
if (!fullyConnected) {
throw new IllegalStateException("Not connected to RTMP server");
}
if (currentStreamId == -1) {
if (currentStreamId == 0) {
throw new IllegalStateException("No current stream object exists");
}
 
Loading
Loading
@@ -271,7 +250,7 @@ public class RtmpConnection implements RtmpPublisher {
if (!fullyConnected) {
throw new IllegalStateException("Not connected to RTMP server");
}
if (currentStreamId == -1) {
if (currentStreamId == 0) {
throw new IllegalStateException("No current stream object exists");
}
 
Loading
Loading
@@ -299,13 +278,13 @@ public class RtmpConnection implements RtmpPublisher {
if (!fullyConnected) {
throw new IllegalStateException("Not connected to RTMP server");
}
if (currentStreamId == -1) {
if (currentStreamId == 0) {
throw new IllegalStateException("No current stream object exists");
}
if (!publishPermitted) {
throw new IllegalStateException("Not get the _result(Netstream.Publish.Start)");
}
Log.d(TAG, "closeStream(): setting current stream ID to -1");
Log.d(TAG, "closeStream(): setting current stream ID to 0");
Command closeStream = new Command("closeStream", 0);
closeStream.getHeader().setChunkStreamId(ChunkStreamInfo.RTMP_STREAM_CHANNEL);
closeStream.getHeader().setMessageStreamId(currentStreamId);
Loading
Loading
@@ -316,67 +295,53 @@ public class RtmpConnection implements RtmpPublisher {
 
@Override
public void shutdown() {
if (active) {
readThread.shutdown();
try {
// It will raise EOFException in handleRxPacketThread
socket.shutdownInput();
// It will raise SocketException in sendRtmpPacket
socket.shutdownOutput();
} catch (IOException ioe) {
ioe.printStackTrace();
}
 
try {
// It will invoke EOFException in read thread
socket.shutdownInput();
// It will invoke SocketException in write thread
socket.shutdownOutput();
} catch (IOException ioe) {
ioe.printStackTrace();
}
// shutdown rxPacketHandler
try {
rxPacketHandler.join();
} catch (InterruptedException ie) {
rxPacketHandler.interrupt();
}
 
// shutdown socket as well as its input and output stream
if (socket != null) {
try {
readThread.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
readThread.interrupt();
}
// shutdown handleRxPacketLoop
rxPacketQueue.clear();
active = false;
synchronized (rxPacketLock) {
rxPacketLock.notify();
}
// shutdown socket as well as its input and output stream
if (socket != null) {
try {
socket.close();
Log.d(TAG, "socket closed");
} catch (IOException ex) {
Log.e(TAG, "shutdown(): failed to close socket", ex);
}
socket.close();
Log.d(TAG, "socket closed");
} catch (IOException ex) {
Log.e(TAG, "shutdown(): failed to close socket", ex);
}
mHandler.onRtmpDisconnected("disconnected");
}
mHandler.onRtmpDisconnected("disconnected");
 
reset();
}
 
private void reset() {
active = false;
connecting = false;
fullyConnected = false;
publishPermitted = false;
tcUrl = null;
swfUrl = null;
pageUrl = null;
swfUrl = null;
pageUrl = null;
appName = null;
streamName = null;
publishType = null;
currentStreamId = -1;
currentStreamId = 0;
transactionIdCounter = 0;
videoFrameCacheNumber.set(0);
socketExceptionCause = "";
serverIpAddr = null;
serverPid = null;
serverId = null;
rtmpSessionInfo = null;
}
 
@Override
Loading
Loading
@@ -384,7 +349,7 @@ public class RtmpConnection implements RtmpPublisher {
if (!fullyConnected) {
throw new IllegalStateException("Not connected to RTMP server");
}
if (currentStreamId == -1) {
if (currentStreamId == 0) {
throw new IllegalStateException("No current stream object exists");
}
if (!publishPermitted) {
Loading
Loading
@@ -403,7 +368,7 @@ public class RtmpConnection implements RtmpPublisher {
if (!fullyConnected) {
throw new IllegalStateException("Not connected to RTMP server");
}
if (currentStreamId == -1) {
if (currentStreamId == 0) {
throw new IllegalStateException("No current stream object exists");
}
if (!publishPermitted) {
Loading
Loading
@@ -419,7 +384,9 @@ public class RtmpConnection implements RtmpPublisher {
mHandler.onRtmpVideoStreaming("video streaming");
}
 
/** Transmit the specified RTMP packet */
/**
* Transmit the specified RTMP packet
*/
public void sendRtmpPacket(RtmpPacket rtmpPacket) {
try {
ChunkStreamInfo chunkStreamInfo = rtmpSessionInfo.getChunkStreamInfo(rtmpPacket.getHeader().getChunkStreamId());
Loading
Loading
@@ -458,66 +425,72 @@ public class RtmpConnection implements RtmpPublisher {
}
}
 
public interface PacketRxHandler {
public void handleRxPacket(RtmpPacket rtmpPacket);
public void notifyWindowAckRequired(final int numBytesReadThusFar);
}
private void handleRxPacketLoop() throws IOException {
// Handle all queued received RTMP packets
while (active) {
while (!rxPacketQueue.isEmpty()) {
RtmpPacket rtmpPacket = rxPacketQueue.poll();
//Log.d(TAG, "handleRxPacketLoop(): RTMP rx packet message type: " + rtmpPacket.getHeader().getMessageType());
switch (rtmpPacket.getHeader().getMessageType()) {
case ABORT:
rtmpSessionInfo.getChunkStreamInfo(((Abort) rtmpPacket).getChunkStreamId()).clearStoredChunks();
break;
case USER_CONTROL_MESSAGE:
UserControl ping = (UserControl) rtmpPacket;
switch (ping.getType()) {
case PING_REQUEST:
ChunkStreamInfo channelInfo = rtmpSessionInfo.getChunkStreamInfo(ChunkStreamInfo.RTMP_CONTROL_CHANNEL);
Log.d(TAG, "handleRxPacketLoop(): Sending PONG reply..");
UserControl pong = new UserControl(ping, channelInfo);
sendRtmpPacket(pong);
break;
case STREAM_EOF:
Log.i(TAG, "handleRxPacketLoop(): Stream EOF reached, closing RTMP writer...");
break;
}
break;
case WINDOW_ACKNOWLEDGEMENT_SIZE:
WindowAckSize windowAckSize = (WindowAckSize) rtmpPacket;
int size = windowAckSize.getAcknowledgementWindowSize();
Log.d(TAG, "handleRxPacketLoop(): Setting acknowledgement window size: " + size);
rtmpSessionInfo.setAcknowledgmentWindowSize(size);
// Set socket option
socket.setSendBufferSize(size);
break;
case SET_PEER_BANDWIDTH:
int acknowledgementWindowsize = rtmpSessionInfo.getAcknowledgementWindowSize();
final ChunkStreamInfo chunkStreamInfo = rtmpSessionInfo.getChunkStreamInfo(ChunkStreamInfo.RTMP_CONTROL_CHANNEL);
Log.d(TAG, "handleRxPacketLoop(): Send acknowledgement window size: " + acknowledgementWindowsize);
sendRtmpPacket(new WindowAckSize(acknowledgementWindowsize, chunkStreamInfo));
break;
case COMMAND_AMF0:
handleRxInvoke((Command) rtmpPacket);
break;
default:
Log.w(TAG, "handleRxPacketLoop(): Not handling unimplemented/unknown packet of type: " + rtmpPacket.getHeader().getMessageType());
break;
}
}
// Wait for next received packet
synchronized (rxPacketLock) {
try {
rxPacketLock.wait(500);
} catch (InterruptedException ex) {
Log.w(TAG, "handleRxPacketLoop: Interrupted", ex);
while (!Thread.interrupted()) {
try {
// It will be blocked when no data in input stream buffer
RtmpPacket rtmpPacket = rtmpDecoder.readPacket(inputStream);
if (rtmpPacket != null) {
//Log.d(TAG, "handleRxPacketLoop(): RTMP rx packet message type: " + rtmpPacket.getHeader().getMessageType());
switch (rtmpPacket.getHeader().getMessageType()) {
case ABORT:
rtmpSessionInfo.getChunkStreamInfo(((Abort) rtmpPacket).getChunkStreamId()).clearStoredChunks();
break;
case USER_CONTROL_MESSAGE:
UserControl user = (UserControl) rtmpPacket;
switch (user.getType()) {
case STREAM_BEGIN:
if (currentStreamId != user.getFirstEventData()) {
throw new IllegalStateException("Current stream ID error!");
}
break;
case PING_REQUEST:
ChunkStreamInfo channelInfo = rtmpSessionInfo.getChunkStreamInfo(ChunkStreamInfo.RTMP_CONTROL_CHANNEL);
Log.d(TAG, "handleRxPacketLoop(): Sending PONG reply..");
UserControl pong = new UserControl(user, channelInfo);
sendRtmpPacket(pong);
break;
case STREAM_EOF:
Log.i(TAG, "handleRxPacketLoop(): Stream EOF reached, closing RTMP writer...");
break;
default:
// Ignore...
break;
}
break;
case WINDOW_ACKNOWLEDGEMENT_SIZE:
WindowAckSize windowAckSize = (WindowAckSize) rtmpPacket;
int size = windowAckSize.getAcknowledgementWindowSize();
Log.d(TAG, "handleRxPacketLoop(): Setting acknowledgement window size: " + size);
rtmpSessionInfo.setAcknowledgmentWindowSize(size);
break;
case SET_PEER_BANDWIDTH:
SetPeerBandwidth bw = (SetPeerBandwidth) rtmpPacket;
rtmpSessionInfo.setAcknowledgmentWindowSize(bw.getAcknowledgementWindowSize());
int acknowledgementWindowsize = rtmpSessionInfo.getAcknowledgementWindowSize();
ChunkStreamInfo chunkStreamInfo = rtmpSessionInfo.getChunkStreamInfo(ChunkStreamInfo.RTMP_CONTROL_CHANNEL);
Log.d(TAG, "handleRxPacketLoop(): Send acknowledgement window size: " + acknowledgementWindowsize);
sendRtmpPacket(new WindowAckSize(acknowledgementWindowsize, chunkStreamInfo));
// Set socket option
socket.setSendBufferSize(acknowledgementWindowsize);
break;
case COMMAND_AMF0:
handleRxInvoke((Command) rtmpPacket);
break;
default:
Log.w(TAG, "handleRxPacketLoop(): Not handling unimplemented/unknown packet of type: " + rtmpPacket.getHeader().getMessageType());
break;
}
}
} catch (EOFException eof) {
Thread.currentThread().interrupt();
} catch (SocketException se) {
Log.e(TAG, "Caught SocketException while reading/decoding packet, shutting down: " + se.getMessage());
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), se);
} catch (IOException ioe) {
Log.e(TAG, "Caught exception while reading/decoding packet, shutting down: " + ioe.getMessage());
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), ioe);
}
}
}
Loading
Loading
Loading
Loading
@@ -19,7 +19,6 @@ import net.ossrs.yasea.rtmp.packets.WindowAckSize;
import net.ossrs.yasea.rtmp.packets.Acknowledgement;
 
/**
*
* @author francois
*/
public class RtmpDecoder {
Loading
Loading
@@ -35,29 +34,25 @@ public class RtmpDecoder {
public RtmpPacket readPacket(InputStream in) throws IOException {
 
RtmpHeader header = RtmpHeader.readHeader(in, rtmpSessionInfo);
RtmpPacket rtmpPacket;
Log.d(TAG, "readPacket(): header.messageType: " + header.getMessageType());
// Log.d(TAG, "readPacket(): header.messageType: " + header.getMessageType());
 
ChunkStreamInfo chunkStreamInfo = rtmpSessionInfo.getChunkStreamInfo(header.getChunkStreamId());
chunkStreamInfo.setPrevHeaderRx(header);
 
if (header.getPacketLength() > rtmpSessionInfo.getRxChunkSize()) {
//Log.d(TAG, "readPacket(): packet size (" + header.getPacketLength() + ") is bigger than chunk size (" + rtmpSessionInfo.getChunkSize() + "); storing chunk data");
// This packet consists of more than one chunk; store the chunks in the chunk stream until everything is read
// If the packet consists of more than one chunk,
// store the chunks in the chunk stream until everything is read
if (!chunkStreamInfo.storePacketChunk(in, rtmpSessionInfo.getRxChunkSize())) {
Log.d(TAG, " readPacket(): returning null because of incomplete packet");
return null; // packet is not yet complete
// return null because of incomplete packet
return null;
} else {
Log.d(TAG, " readPacket(): stored chunks complete packet; reading packet");
// stored chunks complete packet, get the input stream of the chunk stream
in = chunkStreamInfo.getStoredPacketInputStream();
}
} else {
//Log.d(TAG, "readPacket(): packet size (" + header.getPacketLength() + ") is LESS than chunk size (" + rtmpSessionInfo.getChunkSize() + "); reading packet fully");
}
 
RtmpPacket rtmpPacket;
switch (header.getMessageType()) {
case SET_CHUNK_SIZE:
SetChunkSize setChunkSize = new SetChunkSize(header);
setChunkSize.readBody(in);
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