Skip to content

Instantly share code, notes, and snippets.

@carsontang
Created July 26, 2012 18:53
Show Gist options
  • Save carsontang/3183792 to your computer and use it in GitHub Desktop.
Save carsontang/3183792 to your computer and use it in GitHub Desktop.
Server
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