/**
* Copyright (c) 2006 - 2014 Smaxe Ltd (www.smaxe.com).
* All rights reserved.
*/
import com.smaxe.uv.client.rtsp.IMessageInterceptor;
import com.smaxe.uv.client.rtsp.IPresentation;
import com.smaxe.uv.client.rtsp.IVideo;
import com.smaxe.uv.client.rtsp.RtspClient;
import com.smaxe.uv.client.rtsp.RtspPlaySession;
import com.smaxe.uv.client.rtsp.RtspRequest;
import com.smaxe.uv.client.rtsp.RtspResponse;
import com.smaxe.uv.client.rtsp.UnicastUdpTransport;
import com.smaxe.uv.client.rtsp.video.AbstractVideo;
import com.smaxe.uv.media.core.MediaTrackInfo;
import com.smaxe.uv.stream.MediaData;
import java.util.Arrays;
/**
* <code>ExRtspPlayStreamsWithUdpPortsDemux</code> - {@link RtspClient} usage example.
* <p> Note:
* <br> - The example 'plays' many streams using the same UDP ports.
* <br> - The example uses STUN protocol to define public UDP ports.
*
* @author Andrei Sochirca
* @see <a href="http://www.smaxe.com/product.jsf?id=juv-rtsp-client" target="_blank">JUV RTSP/RTP Client</a>
*/
public final class ExRtspPlayStreamsWithUdpPortsDemux extends Object
{
/**
* Entry point.
*
* @param args
* @throws Exception if an exception occurred
*/
public static void main(final String[] args) throws Exception
{
// NOTE:
// you can get Evaluation Key at:
// http://www.smaxe.com/order.jsf#request_evaluation_key
// or buy at:
// http://www.smaxe.com/order.jsf
// Android-specific:
// - please add permission to the AndroidManifest.xml :
// <uses-permission android:name="android.permission.INTERNET" />
// - please use separate thread to connect to the server (not UI thread) :
// RtspClient#connect() connects to the remote server in the invocation thread,
// so it causes NetworkOnMainThreadException on 4.0 (http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html)
com.smaxe.uv.client.rtsp.License.setKey("SET-YOUR-KEY");
// url
final String[] url =
{
"rtsp://username:password@184.72.239.149/vod/mp4:BigBuckBunny_175k.mov",
"rtsp://username:password@184.72.239.149/vod/mp4:BigBuckBunny_175k.mov",
"rtsp://username:password@184.72.239.149/vod/mp4:BigBuckBunny_175k.mov",
};
final RtspClient client = new RtspClient();
// configure client
client.configuration().put(RtspClient.Configuration.DATAGRAM_JITTER_BUFFER_MARGIN, 16 /*packets*/);
client.configuration().put(RtspClient.Configuration.DATAGRAM_SO_ENABLE_CONFIGURATION, true);
client.configuration().put(RtspClient.Configuration.DATAGRAM_SO_RCVBUF, 256 * 1024);
client.configuration().put(RtspClient.Configuration.RESPONSE_TIMEOUT, 10 /*seconds*/);
client.configuration().put(RtspClient.Configuration.STUN_SERVERS, "stun.easyvoip.com,numb.viagenie.ca,stun.bluesip.net");
client.configuration().put(RtspClient.Configuration.MESSAGE_INTERCEPTOR, new IMessageInterceptor()
{
public RtspRequest onRequest(final String source, final RtspRequest request)
{
// NOTE: please use the method below to add custom headers
// request.putHeader("Custom-header", "value");
System.out.println("onRequest: " + source + " " + request);
return request;
}
public RtspResponse onResponse(final String source, final RtspResponse response)
{
System.out.println("onResponse: " + source + " " + response);
return response;
}
});
final UnicastUdpTransport transport = client.prepareUnicastUdpTransport();
System.out.println("UnicastUdpTransport#publicAddresses: " + Arrays.toString(transport.getPublicAddresses()));
for (int i = 0; i < url.length; i++)
{
final String id = "RtspClient" + i;
playRtspStreamInSeparateThread(id, client, url[i], transport, new LogVideo(id));
Thread.sleep(5 * 1000);
}
Thread.sleep(30 * 1000);
client.release();
}
/**
* Plays the stream in a separate thread.
*
* @param id client id
* @param client
* @param url
* @param transport
* @param video
*/
public static void playRtspStreamInSeparateThread(final String id, final RtspClient client, final String url,
final UnicastUdpTransport transport, final IVideo video)
{
new Thread(new Runnable()
{
public void run()
{
// UDP port sharing is possible by using 'new RtspClient(RtspClient parent)' constructor
// that shares RtspClient resources
playRtspStream(new RtspClient(client), transport, url, new LogVideo(id));
}
}, "ExRtspPlayStreamsWithUdpPortsDemux-" + id).start();
}
/**
* Plays the stream.
*
* @param client
* @param transport
* @param url
* @param video
*/
public static void playRtspStream(final RtspClient client, final UnicastUdpTransport transport,
final String url, final IVideo video)
{
try
{
// connect
client.connect(url);
// get and print media stream presentation (SDP)
final IPresentation presentation = client.describe(url);
System.out.println("*** Presentation ***");
System.out.println(presentation);
// create 'PLAY' session
final RtspPlaySession session = client.createPlaySession(presentation);
if (!RtspClient.isOK(session.setup(transport)))
{
session.setup();
}
session.play(video);
Thread.sleep(10 * 60 * 1000);
session.teardown();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
client.close("ExRtspPlayStreamsWithUdpPortsDemux '" + url + "' is completed");
}
}
/**
* <code>LogVideo</code>
*/
public static class LogVideo extends AbstractVideo
{
// fields
private final String prefix;
/**
* Constructor.
*
* @param prefix
*/
public LogVideo(final String prefix)
{
this.prefix = prefix;
}
// IVideo implementation
@Override
public void onPlay(final MediaTrackInfo[] tracks)
{
System.out.println(prefix + "-IVideo#onPlay: " + Arrays.toString(tracks));
}
@Override
public void onMediaData(final MediaTrackInfo track, final MediaData data)
{
// NOTE: please use the method below to get media data content
// ByteArray payload = MediaDataFactory.getMediaDataPayload(data);
System.out.println(prefix + "-IVideo#onMediaData: " + data + " " + track);
}
@Override
public void onTeardown()
{
System.out.println(prefix + "-IVideo#onTeardown");
}
}
/**
* Constructor.
*/
private ExRtspPlayStreamsWithUdpPortsDemux()
{
}
}