RTSPConnection.java
上传用户:gmxazy
上传日期:2022-06-06
资源大小:70k
文件大小:7k
- import java.io.*;
- import java.util.*;
- import javax.microedition.io.*;
- /**
- * Handles a single RTSP client.
- */
- public class RTSPConnection implements Runnable {
- /**
- * Connection to the client.
- */
- private SocketConnection client;
-
- /**
- * IP address/domain name of the server.
- */
- private String serverAddr;
-
- /**
- * IP address/domain name of the client.
- */
- private String clientAddr;
-
- /**
- * Output stream to the client.
- */
- private OutputStream send;
-
- /**
- * Input stream from the client.
- */
- private InputStream recv;
-
- /**
- * String buffer where lines of text are built up.
- */
- private StringBuffer buf = new StringBuffer(256);
-
- /**
- * Last sequence number (from the client request).
- */
- private int cseq = 0;
-
- /**
- * Port the server will be broadcasting from.
- */
- private int audioPort = 0;
-
- /**
- * Port the client is listening on (taken from the Transport header in
- * the client request).
- */
- private int clientPort = 0;
-
- /**
- * Creates a new instance to handle a client.
- */
- public RTSPConnection(SocketConnection client) throws IOException {
- this.client = client;
- serverAddr = client.getLocalAddress();
- clientAddr = client.getAddress();
- send = client.openOutputStream();
- recv = client.openInputStream();
-
- new Thread(this).start();
- }
-
- /**
- * Reads the next line of text from <code>recv</code>, up to and
- * including the newline char. If there are no bytes to be read a <code>
- * null</code> is returned instead.
- *
- * @returns the next line or <code>null</code>
- */
- public String readLine() throws IOException {
- buf.setLength(0);
- while (true) {
- int val = recv.read();
- if (val == -1) {
- break;
- }
- if (val == 'r') {
- continue;
- }
- buf.append((char) val);
- if (val == 'n') {
- break;
- }
- }
- if (buf.length() == 0) {
- return null;
- } else {
- return buf.toString();
- }
- }
-
- /**
- * Writes a line of ASCII text to <code>send</code> terminated with CRLF.
- */
- public void writeLine(String line) throws IOException {
- for (int n = 0; n < line.length(); n++) {
- send.write(line.charAt(n));
- }
- send.write('r');
- send.write('n');
- }
-
- /**
- * Writes a line of ASCII text to <code>send</code> terminated with CRLF.
- */
- public void writeLine(StringBuffer line) throws IOException {
- for (int n = 0; n < line.length(); n++) {
- send.write(line.charAt(n));
- }
- send.write('r');
- send.write('n');
- }
-
- /**
- * Appends text to the buffer terminated with CFLF.
- */
- public void appendBuf(String line) {
- buf.append(line);
- buf.append('r');
- buf.append('n');
- }
-
- /**
- * Writes a static SDP to <code>send</code>.
- */
- public void writeSDP() throws IOException {
- buf.setLength(0);
-
- appendBuf("v=0");
- appendBuf("o=- 0 0 IN IP4 " + serverAddr);
- appendBuf("s=AudioStream");
- appendBuf("i=<No author>");
- appendBuf("t=0 0");
- appendBuf("a=tool:RTSP Demo");
-
- appendBuf("a=type:broadcast");
- appendBuf("a=control:*");
- appendBuf("a=range:npt=now-");
-
- appendBuf("m=audio 0 RTP/AVP 96");
- appendBuf("c=IN IP4 0.0.0.0");
- appendBuf("a=rtpmap:96 L8/22050/1"); // this is the audio type: 8-bit PCM, 22k, mono
- appendBuf("a=ptime:40");
- appendBuf("a=control:track1");
-
- //appendBuf("a=AvgBitRate:integer;22350");
- //appendBuf("a=AvgPacketSize:integer;894");
- //appendBuf("a=MaxBitRate:integer;22350");
- //appendBuf("a=MaxPacketSize:integer;894");
-
- writeLine("Content-Type: application/sdp");
- writeLine("Content-Length: " + (buf.length() + 4));
- writeLine("");
- writeLine(buf);
- }
-
- /**
- * Sends the common 200 response to the client along with a sequence
- * number.
- */
- public void writeOK() throws IOException {
- writeLine("RTSP/1.0 200 OK");
- writeLine("CSeq: " + cseq);
- }
-
- /**
- * Handles the connection with a single client.
- */
- public void run() {
- AudioStream stream = null;
- try {
- loop: while (true) {
- String line = readLine();
- dprint(line);
- if (line == null) {
- break;
- }
- parseIncoming();
-
- switch (getCommand(line)) {
- case COMMAND_OPTIONS:
- writeOK();
- writeLine("Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN");
- break;
- case COMMAND_DESCRIBE:
- writeOK();
- writeLine("Content-Base: rtsp://" + serverAddr + ":8554/stream.wav/");
- writeSDP();
- break;
- case COMMAND_SETUP:
- if (stream == null) {
- stream = new AudioStream(-1);
- audioPort = stream.getPort();
- }
- writeOK();
- writeLine("Session: 1-0");
- writeLine("Transport: RTP/AVP;unicast;client_port=" + clientPort + "-" + (clientPort + 1)
- + ";server_port=" + audioPort + "-" + (audioPort + 1));
- break;
- case COMMAND_PLAY:
- writeOK();
- writeLine("Session: 1-0");
- writeLine("RTP-Info: url=rtsp://" + serverAddr + ":8554/stream.wav/track1;seq=0;");
-
- stream.play(clientAddr, clientPort);
- break;
- case COMMAND_PAUSE:
- writeOK();
- writeLine("Session: 1-0");
- stream.pause();
- break;
- case COMMAND_TEARDOWN:
- break loop;
- default:
- continue;
- }
- writeLine("");
- send.flush();
- }
- } catch (IOException e) {
- dprint(e);
- }
- dprint("Closing connectionn");
- stream.stop();
- try {
- send.close();
- recv.close();
- client.close();
- } catch (IOException e) {
- dprint(e);
- }
- }
-
- /**
- * Reads the remainder of the client request and stores any interesting
- * data (namely the sequence number and client port for now).
- */
- private void parseIncoming() throws IOException {
- boolean hasCseq = false;
- while (true) {
- String line = readLine();
- dprint(line);
- if (line == null || line.equals("n")) {
- break;
- }
- if (line.indexOf("CSeq: ") == 0) {
- cseq = Integer.parseInt(line.substring(line.indexOf(':') + 1).trim());
- }
- if (line.indexOf("Transport: ") == 0) {
- int beg = line.indexOf("client_port=") + 12;
- if (beg < 0) {
- break;
- }
- int end = line.indexOf("-", beg);
- if (end < 0) {
- break;
- }
- clientPort = Integer.parseInt(line.substring(beg, end).trim());
- }
- }
- }
-
- public void dprint(Object obj) {
- System.out.print(obj);
- }
-
- /**
- * List of RTSP commands supported.
- */
- private static final Vector COMMANDS = new Vector(5);
- static {
- COMMANDS.addElement("OPTIONS ");
- COMMANDS.addElement("DESCRIBE ");
- COMMANDS.addElement("SETUP ");
- COMMANDS.addElement("PLAY ");
- COMMANDS.addElement("PAUSE ");
- COMMANDS.addElement("TEARDOWN ");
- }
-
- /*
- * Command indices.
- */
- private static final int COMMAND_OPTIONS = 0;
- private static final int COMMAND_DESCRIBE = 1;
- private static final int COMMAND_SETUP = 2;
- private static final int COMMAND_PLAY = 3;
- private static final int COMMAND_PAUSE = 4;
- private static final int COMMAND_TEARDOWN = 5;
-
- /**
- * Returns a command index for a given string, or -1 if no match.
- */
- private static int getCommand(String line) {
- for (int n = COMMANDS.size() - 1; n >= 0; n--) {
- if (line.indexOf((String) COMMANDS.elementAt(n)) == 0) {
- return n;
- }
- }
- return -1;
- }
- }