/** * 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() { } }