Created
July 26, 2012 18:53
-
-
Save carsontang/3183792 to your computer and use it in GitHub Desktop.
Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Server.java | |
/* ------------------ | |
Server | |
usage: java Server [RTSP listening port] | |
---------------------- */ | |
import java.io.*; | |
import java.net.*; | |
import java.awt.*; | |
import java.util.*; | |
import java.awt.event.*; | |
import javax.swing.*; | |
import javax.swing.Timer; | |
public class Server extends JFrame implements ActionListener { | |
//RTP variables: | |
//---------------- | |
DatagramSocket RTPsocket; //socket to be used to send and receive UDP packets | |
DatagramPacket senddp; //UDP packet containing the video frames | |
InetAddress ClientIPAddr; //Client IP address | |
int RTP_dest_port = 0; //destination port for RTP packets (given by the RTSP Client) | |
//GUI: | |
//---------------- | |
JLabel label; | |
//Video variables: | |
//---------------- | |
int imagenb = 0; //image nb of the image currently transmitted | |
VideoStream video; //VideoStream object used to access video frames | |
static int MJPEG_TYPE = 26; //RTP payload type for MJPEG video | |
static int FRAME_PERIOD = 100; //Frame period of the video to stream, in ms | |
static int VIDEO_LENGTH = 500; //length of the video in frames | |
Timer timer; //timer used to send the images at the video frame rate | |
byte[] buf; //buffer used to store the images to send to the client | |
//RTSP variables | |
//---------------- | |
//rtsp states | |
final static int INIT = 0; | |
final static int READY = 1; | |
final static int PLAYING = 2; | |
//rtsp message types | |
final static int SETUP = 3; | |
final static int PLAY = 4; | |
final static int PAUSE = 5; | |
final static int TEARDOWN = 6; | |
static int state; //RTSP Server state == INIT or READY or PLAY | |
Socket RTSPsocket; //socket used to send/receive RTSP messages | |
//input and output stream filters | |
static BufferedReader RTSPBufferedReader; | |
static BufferedWriter RTSPBufferedWriter; | |
static String VideoFileName; //video file requested from the client | |
static int RTSP_ID = 123456; //ID of the RTSP session | |
int RTSPSeqNb = 0; //Sequence number of RTSP messages within the session | |
final static String CRLF = "\r\n"; | |
//-------------------------------- | |
//Constructor | |
//-------------------------------- | |
public Server(){ | |
//init Frame | |
super("Server"); | |
//init Timer | |
timer = new Timer(FRAME_PERIOD, this); | |
timer.setInitialDelay(0); | |
timer.setCoalesce(true); | |
//allocate memory for the sending buffer | |
buf = new byte[15000]; | |
//Handler to close the main window | |
addWindowListener(new WindowAdapter() { | |
public void windowClosing(WindowEvent e) { | |
//stop the timer and exit | |
timer.stop(); | |
System.exit(0); | |
}}); | |
//GUI: | |
label = new JLabel("Send frame # ", JLabel.CENTER); | |
getContentPane().add(label, BorderLayout.CENTER); | |
} | |
//------------------------------------ | |
//main | |
//------------------------------------ | |
public static void main(String argv[]) throws Exception | |
{ | |
//create a Server object | |
Server theServer = new Server(); | |
//show GUI: | |
theServer.pack(); | |
theServer.setVisible(true); | |
//get RTSP socket port from the command line | |
int RTSPport = Integer.parseInt(argv[0]); | |
//Initiate TCP connection with the client for the RTSP session | |
ServerSocket listenSocket = new ServerSocket(RTSPport); | |
theServer.RTSPsocket = listenSocket.accept(); | |
listenSocket.close(); | |
//Get Client IP address | |
theServer.ClientIPAddr = theServer.RTSPsocket.getInetAddress(); | |
//Initiate RTSPstate | |
state = INIT; | |
//Set input and output stream filters: | |
RTSPBufferedReader = new BufferedReader(new InputStreamReader(theServer.RTSPsocket.getInputStream()) ); | |
RTSPBufferedWriter = new BufferedWriter(new OutputStreamWriter(theServer.RTSPsocket.getOutputStream()) ); | |
//Wait for the SETUP message from the client | |
int request_type; | |
boolean done = false; | |
while(!done) | |
{ | |
request_type = theServer.parse_RTSP_request(); //blocking | |
if (request_type == SETUP) | |
{ | |
done = true; | |
//update RTSP state | |
state = READY; | |
System.out.println("New RTSP state: READY"); | |
//Send response | |
theServer.send_RTSP_response(); | |
//init the VideoStream object: | |
theServer.video = new VideoStream(VideoFileName); | |
//init RTP socket | |
theServer.RTPsocket = new DatagramSocket(); | |
} | |
} | |
//loop to handle RTSP requests | |
while(true) | |
{ | |
//parse the request | |
request_type = theServer.parse_RTSP_request(); //blocking | |
if ((request_type == PLAY) && (state == READY)) | |
{ | |
//send back response | |
theServer.send_RTSP_response(); | |
//start timer | |
theServer.timer.start(); | |
//update state | |
state = PLAYING; | |
System.out.println("New RTSP state: PLAYING"); | |
} | |
else if ((request_type == PAUSE) && (state == PLAYING)) | |
{ | |
//send back response | |
theServer.send_RTSP_response(); | |
//stop timer | |
theServer.timer.stop(); | |
//update state | |
state = READY; | |
System.out.println("New RTSP state: READY"); | |
} | |
else if (request_type == TEARDOWN) | |
{ | |
//send back response | |
theServer.send_RTSP_response(); | |
//stop timer | |
theServer.timer.stop(); | |
//close sockets | |
theServer.RTSPsocket.close(); | |
theServer.RTPsocket.close(); | |
System.exit(0); | |
} | |
} | |
} | |
//------------------------ | |
//Handler for timer | |
//------------------------ | |
public void actionPerformed(ActionEvent e) { | |
//if the current image nb is less than the length of the video | |
if (imagenb < VIDEO_LENGTH) | |
{ | |
//update current imagenb | |
imagenb++; | |
try { | |
//get next frame to send from the video, as well as its size | |
int image_length = video.getnextframe(buf); | |
//Builds an RTPpacket object containing the frame | |
RTPpacket rtp_packet = new RTPpacket(MJPEG_TYPE, imagenb, imagenb*FRAME_PERIOD, buf, image_length); | |
//get to total length of the full rtp packet to send | |
int packet_length = rtp_packet.getlength(); | |
//retrieve the packet bitstream and store it in an array of bytes | |
byte[] packet_bits = new byte[packet_length]; | |
rtp_packet.getpacket(packet_bits); | |
//send the packet as a DatagramPacket over the UDP socket | |
senddp = new DatagramPacket(packet_bits, packet_length, ClientIPAddr, RTP_dest_port); | |
RTPsocket.send(senddp); | |
//System.out.println("Send frame #"+imagenb); | |
//print the header bitstream | |
rtp_packet.printheader(); | |
//update GUI | |
label.setText("Send frame #" + imagenb); | |
} | |
catch(Exception ex) | |
{ | |
System.out.println("Exception caught: "+ex); | |
System.exit(0); | |
} | |
} | |
else | |
{ | |
//if we have reached the end of the video file, stop the timer | |
timer.stop(); | |
} | |
} | |
//------------------------------------ | |
//Parse RTSP Request | |
//------------------------------------ | |
private int parse_RTSP_request() | |
{ | |
int request_type = -1; | |
try{ | |
//parse request line and extract the request_type: | |
String RequestLine = RTSPBufferedReader.readLine(); | |
//System.out.println("RTSP Server - Received from Client:"); | |
System.out.println(RequestLine); | |
StringTokenizer tokens = new StringTokenizer(RequestLine); | |
String request_type_string = tokens.nextToken(); | |
//convert to request_type structure: | |
if ((new String(request_type_string)).compareTo("SETUP") == 0) | |
request_type = SETUP; | |
else if ((new String(request_type_string)).compareTo("PLAY") == 0) | |
request_type = PLAY; | |
else if ((new String(request_type_string)).compareTo("PAUSE") == 0) | |
request_type = PAUSE; | |
else if ((new String(request_type_string)).compareTo("TEARDOWN") == 0) | |
request_type = TEARDOWN; | |
if (request_type == SETUP) | |
{ | |
//extract VideoFileName from RequestLine | |
VideoFileName = tokens.nextToken(); | |
} | |
//parse the SeqNumLine and extract CSeq field | |
String SeqNumLine = RTSPBufferedReader.readLine(); | |
System.out.println(SeqNumLine); | |
tokens = new StringTokenizer(SeqNumLine); | |
tokens.nextToken(); | |
RTSPSeqNb = Integer.parseInt(tokens.nextToken()); | |
//get LastLine | |
String LastLine = RTSPBufferedReader.readLine(); | |
System.out.println(LastLine); | |
if (request_type == SETUP) | |
{ | |
//extract RTP_dest_port from LastLine | |
tokens = new StringTokenizer(LastLine); | |
for (int i=0; i<3; i++) | |
tokens.nextToken(); //skip unused stuff | |
RTP_dest_port = Integer.parseInt(tokens.nextToken()); | |
} | |
//else LastLine will be the SessionId line ... do not check for now. | |
} | |
catch(Exception ex) | |
{ | |
System.out.println("Exception caught: "+ex); | |
System.exit(0); | |
} | |
return(request_type); | |
} | |
//------------------------------------ | |
//Send RTSP Response | |
//------------------------------------ | |
private void send_RTSP_response() | |
{ | |
try{ | |
RTSPBufferedWriter.write("RTSP/1.0 200 OK"+CRLF); | |
RTSPBufferedWriter.write("CSeq: "+RTSPSeqNb+CRLF); | |
RTSPBufferedWriter.write("Session: "+RTSP_ID+CRLF); | |
RTSPBufferedWriter.flush(); | |
//System.out.println("RTSP Server - Sent response to Client."); | |
} | |
catch(Exception ex) | |
{ | |
System.out.println("Exception caught: "+ex); | |
System.exit(0); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment