Good evening guys, I have a problem with my code, I'm trying to do the following application. A client - server connection that makes a video stream.
It turns out that the code works if I test from one machine to another on a local network.
Follow the client and server codes - I could not add two missing classes for RTPpacket, anything I send.
Server
package com.exemple.rtspserver;
/ * ------------------ 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 {
/**
*
*/
private static final long serialVersionUID = 1L;
// 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 = 8554;// 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:
System.out.println("Criando o buffer reader ... ");
System.out.println("socket : " + theServer.RTSPsocket);
RTSPBufferedReader = new BufferedReader(new InputStreamReader(theServer.RTSPsocket.getInputStream()));
RTSPBufferedWriter = new BufferedWriter(new OutputStreamWriter(theServer.RTSPsocket.getOutputStream()));
System.out.println("Meu Reader : " + RTSPBufferedReader);
System.out.println("Meu Writer : " + RTSPBufferedWriter);
// 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) {
System.out.println("ENTROU NO ACTION PERFORMED");
System.out.println("tAMANHO VIDEO : " + VIDEO_LENGTH);
// if the current image nb is less than the length of the video
if (imagenb < VIDEO_LENGTH) {
// update current imagenb
System.out.println("ENTROU NO IF ACTION PERFORMED");
imagenb++;
try {
// get next frame to send from the video, as well as its size
System.out.println("ENTROU NO TRY ACTION PERFORMED");
System.out.println("Buf: " + buf);
System.out.println("video: " + video);
if(video == null) {
video = new VideoStream(VideoFileName);
}
int image_length = video.getnextframe(buf);
System.out.print("\n" + image_length);
// 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);
System.out.print("RTP_dest_port =" + RTP_dest_port + "\n");
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 action: " + ex);
System.exit(0);
}
} else {
// if we have reached the end of the video file, stop the timer
System.out.println("Timer stop : ");
timer.stop();
}
}
// ------------------------------------
// Parse RTSP Request
// ------------------------------------
private int parse_RTSP_request() {
int request_type = -1;
// System.out.println("RTSP Buffer começo");
try {
// parse request line and extract the request_type:
//System.out.println("RTSPBufferedReader:" + RTSPBufferedReader);
//System.out.println("Antes If:");
String RequestLine = "";
if (RTSPBufferedReader != null && RTSPBufferedReader.ready()
&& (RequestLine = RTSPBufferedReader.readLine()) != null) {
System.out.println("Depois If carai:");
// System.out.println("RTSP Server - Received from Client:");
System.out.println("RequestLine " + 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" + SeqNumLine);
tokens = new StringTokenizer(SeqNumLine);
tokens.nextToken();
RTSPSeqNb = Integer.parseInt(tokens.nextToken());
// get LastLine
String LastLine = RTSPBufferedReader.readLine();
System.out.println("LastLine" + 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 here: " + ex);
System.exit(0);
}
//System.out.println("Retornando Request Type: " + request_type);
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);
}
}
}
VideoStream - on Server
package com.exemple.rtspserver;
import java.io.File; import java.io.FileInputStream; import java.nio.file.Path; import java.nio.file.Paths;
public class VideoStream { FileInputStream fis; // video file int frame_nb; // current frame nb
//-----------------------------------
//constructor
//-----------------------------------
public VideoStream(String filename) throws Exception{
Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
File [] files = new File(s).listFiles();
for(File file : files) {
if(file.isFile())
System.out.println("Nome Arquivo: " + file.getName());
}
System.out.println("FIM ARQUIVOS");
//init variables
//fis = (FileInputStream) getClass().getResourceAsStream(filename);
fis = new FileInputStream(filename);
System.out.println("Fis" + fis);
frame_nb = 0;
}
//-----------------------------------
// getnextframe
//returns the next frame as an array of byte and the size of the frame
//-----------------------------------
public int getnextframe(byte[] frame) throws Exception
{
int length = 0;
String length_string;
byte[] frame_length = new byte[5];
System.out.println("getNextFrame ");
System.out.println("fis " + fis);
System.out.println("tamanho fis " + frame_length );
//read current frame length
fis.read(frame_length,0,5);
System.out.println("foi o fis ");
//transform frame_length to integer
length_string = new String(frame_length);
length = Integer.parseInt(length_string);
return(fis.read(frame,0,length));
}
}
Customer
package com.exemple.clientRTSP;
/ * ------------------ Client usage: java Client [Server hostname] [Server RTSP listening port] [Video file requested] ---------------------- * /
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.io.OutputStreamWriter; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import java.util.StringTokenizer;
import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.Timer;
public class Client {
// GUI
// ----
JFrame f = new JFrame("Client");
JButton setupButton = new JButton("Setup");
JButton playButton = new JButton("Play");
JButton pauseButton = new JButton("Pause");
JButton tearButton = new JButton("Teardown");
JPanel mainPanel = new JPanel();
JPanel buttonPanel = new JPanel();
JLabel iconLabel = new JLabel();
ImageIcon icon;
// RTP variables:
// ----------------
DatagramPacket rcvdp; // UDP packet received from the server
DatagramSocket RTPsocket; // socket to be used to send and receive UDP packets
static int RTP_RCV_PORT = 25000; // port where the client will receive the RTP packets
Timer timer; // timer used to receive data from the UDP socket
byte[] buf; // buffer used to store data received from the server
// RTSP variables
// ----------------
// rtsp states
final static int INIT = 0;
final static int READY = 1;
final static int PLAYING = 2;
static int state; // RTSP state == INIT or READY or PLAYING
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 to request to the server
int RTSPSeqNb = 0; // Sequence number of RTSP messages within the session
int RTSPid = 0; // ID of the RTSP session (given by the RTSP Server)
final static String CRLF = "\r\n";
// Video constants:
// ------------------
static int MJPEG_TYPE = 26; // RTP payload type for MJPEG video
// --------------------------
// Constructor
// --------------------------
public Client() {
// build GUI
// --------------------------
// Frame
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// Buttons
buttonPanel.setLayout(new GridLayout(1, 0));
buttonPanel.add(setupButton);
buttonPanel.add(playButton);
buttonPanel.add(pauseButton);
buttonPanel.add(tearButton);
setupButton.addActionListener(new setupButtonListener());
playButton.addActionListener(new playButtonListener());
pauseButton.addActionListener(new pauseButtonListener());
tearButton.addActionListener(new tearButtonListener());
// Image display label
iconLabel.setIcon(null);
// frame layout
mainPanel.setLayout(null);
mainPanel.add(iconLabel);
mainPanel.add(buttonPanel);
iconLabel.setBounds(0, 0, 380, 280);
buttonPanel.setBounds(0, 280, 380, 50);
f.getContentPane().add(mainPanel, BorderLayout.CENTER);
f.setSize(new Dimension(390, 370));
f.setVisible(true);
// init timer
// --------------------------
System.out.println("timer init");
timer = new Timer(20, new timerListener());
timer.setInitialDelay(0);
timer.setCoalesce(true);
// allocate enough memory for the buffer used to receive data from the server
buf = new byte[15000];
}
// ------------------------------------
// main
// ------------------------------------
public static void main(String argv[]) throws Exception {
// Create a Client object
Client theClient = new Client();
// get server RTSP port and IP address from the command line
// ------------------
// int RTSP_server_port = 8554; //Integer.parseInt(argv[1]);
// String ServerHost ="35.173.160.243"; //argv[0];
// InetAddress ServerIPAddr = InetAddress.getByName(ServerHost);
// get video filename to request:
VideoFileName = "movie.mjpeg"; // argv[2];
// Establish a TCP connection with the server to exchange RTSP messages
// ------------------
// theClient.RTSPsocket = new Socket(ServerIPAddr, RTSP_server_port);
// Set input and output stream filters:
try {
System.out.println("ante socket: ");
// System.out.println(new Socket("35.173.160.243", 8554));
//theClient.RTSPsocket = new Socket("ec2-35-173-160-243.compute-1.amazonaws.com", 8554);
theClient.RTSPsocket = new Socket("192.168.0.31", 8554);
System.out.println("depois socket: ");
System.out.println("socket: " + theClient.RTSPsocket);
RTSPBufferedReader = new BufferedReader(new InputStreamReader(theClient.RTSPsocket.getInputStream()));
RTSPBufferedWriter = new BufferedWriter(new OutputStreamWriter(theClient.RTSPsocket.getOutputStream()));
} catch (IOException ex) {
System.out.println("buffer: " + ex);
System.exit(0);
}
// init RTSP state:
state = INIT;
}
// ------------------------------------
// Handler for buttons
// ------------------------------------
// .............
// TO COMPLETE
// .............
// Handler for Setup button
// -----------------------
class setupButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// System.out.println("Setup Button pressed !");
if (state == INIT) {
// Init non-blocking RTPsocket that will be used to receive data
try {
// construct a new DatagramSocket to receive RTP packets from the server, on
// port RTP_RCV_PORT
// RTPsocket = ...
RTPsocket = new DatagramSocket(RTP_RCV_PORT);
// set TimeOut value of the socket to 5msec.
System.out.println("Socket RTPsocket: " + RTPsocket);
RTPsocket.setSoTimeout(2000);
// set TimeOut value of the socket to 5msec.
// ....
} catch (SocketException se) {
System.out.println("Socket exception: " + se);
System.exit(0);
}
// init RTSP sequence number
RTSPSeqNb = 1;
// Send SETUP message to the server
send_RTSP_request("SETUP");
// Wait for the response
if (parse_server_response() != 200)
System.out.println("Invalid Server Response");
else {
// change RTSP state and print new state
state = READY;
System.out.println("New RTSP state: READY");
// System.out.println("New RTSP state: ....");
}
} // else if state != INIT then do nothing
}
}
// Handler for Play button
// -----------------------
class playButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Play Button pressed !");
if (state == READY) {
// increase RTSP sequence number
RTSPSeqNb++;
// send PLAY message to the server
send_RTSP_request("PLAY");
// wait for the response
if (parse_server_response() != 200)
System.out.println("Invalid Server Response");
else {
// change RTSP state and print out new state
state = PLAYING;
System.out.println("New RTSP state: PLAYING");
// start the timer
System.out.println("timer START");
timer.start();
}
} // else if state != READY then do nothing
}
}
// Handler for Pause button
// -----------------------
class pauseButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// System.out.println("Pause Button pressed !");
if (state == PLAYING) {
// increase RTSP sequence number
// ........
// Send PAUSE message to the server
send_RTSP_request("PAUSE");
// Wait for the response
if (parse_server_response() != 200)
System.out.println("Invalid Server Response");
else {
// change RTSP state and print out new state
// ........
// System.out.println("New RTSP state: ...");
// stop the timer
timer.stop();
System.out.println("TIME STOP");
}
}
// else if state != PLAYING then do nothing
}
}
// Handler for Teardown button
// -----------------------
class tearButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// System.out.println("Teardown Button pressed !");
// increase RTSP sequence number
// ..........
// Send TEARDOWN message to the server
send_RTSP_request("TEARDOWN");
// Wait for the response
if (parse_server_response() != 200)
System.out.println("Invalid Server Response");
else {
// change RTSP state and print out new state
// ........
// System.out.println("New RTSP state: ...");
// stop the timer
timer.stop();
System.out.println("timer STOP");
// exit
System.exit(0);
}
}
}
// ------------------------------------
// Handler for timer
// ------------------------------------
class timerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("timer listener entrou");
// Construct a DatagramPacket to receive data from the UDP socket
rcvdp = new DatagramPacket(buf, buf.length);
System.out.println("timer listener rcvdp" + rcvdp.getData());
System.out.println("timer listener rcvdp" + rcvdp.getLength());
try {
// receive the DP from the socket:
System.out.println("lindooo RTPsocket " + RTPsocket);
RTPsocket.receive(rcvdp);
System.out.println("timer listener recebeu");
// create an RTPpacket object from the DP
RTPpacket rtp_packet = new RTPpacket(rcvdp.getData(), rcvdp.getLength());
System.out.println("rtp_packet" + rtp_packet);
System.out.println("rtp_packet" + rtp_packet.getsequencenumber());
// print important header fields of the RTP packet received:
System.out.println("Got RTP packet with SeqNum # " + rtp_packet.getsequencenumber() + " TimeStamp "
+ rtp_packet.gettimestamp() + " ms, of type " + rtp_packet.getpayloadtype());
// print header bitstream:
rtp_packet.printheader();
// get the payload bitstream from the RTPpacket object
int payload_length = rtp_packet.getpayload_length();
byte[] payload = new byte[payload_length];
rtp_packet.getpayload(payload);
// get an Image object from the payload bitstream
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.createImage(payload, 0, payload_length);
// display the image as an ImageIcon object
icon = new ImageIcon(image);
iconLabel.setIcon(icon);
} catch (InterruptedIOException iioe) {
// System.out.println("Nothing to read");
} catch (IOException ioe) {
System.out.println("Exception caught 1: " + ioe);
}
}
}
// ------------------------------------
// Parse Server Response
// ------------------------------------
private int parse_server_response() {
int reply_code = 0;
try {
// parse status line and extract the reply_code:
String StatusLine = RTSPBufferedReader.readLine();
// System.out.println("RTSP Client - Received from Server:");
System.out.println(StatusLine);
StringTokenizer tokens = new StringTokenizer(StatusLine);
tokens.nextToken(); // skip over the RTSP version
reply_code = Integer.parseInt(tokens.nextToken());
// if reply code is OK get and print the 2 other lines
if (reply_code == 200) {
String SeqNumLine = RTSPBufferedReader.readLine();
System.out.println(SeqNumLine);
String SessionLine = RTSPBufferedReader.readLine();
System.out.println(SessionLine);
// if state == INIT gets the Session Id from the SessionLine
tokens = new StringTokenizer(SessionLine);
tokens.nextToken(); // skip over the Session:
RTSPid = Integer.parseInt(tokens.nextToken());
}
} catch (Exception ex) {
System.out.println("Exception caught 2: " + ex);
System.exit(0);
}
return (reply_code);
}
// ------------------------------------
// Send RTSP Request
// ------------------------------------
// .............
// TO COMPLETE
// .............
private void send_RTSP_request(String request_type) {
try {
RTSPBufferedWriter.write(request_type + " " + VideoFileName + " " + "RTSP/1.0" + CRLF);
RTSPBufferedWriter.write("CSeq: " + RTSPSeqNb + CRLF);
if (request_type.equals("SETUP")) {
RTSPBufferedWriter.write("Transport: RTP/UDP; client_port= " + RTP_RCV_PORT + CRLF);
}
else {
RTSPBufferedWriter.write("Session: " + RTSPid + CRLF);
}
RTSPBufferedWriter.flush();
} catch (Exception ex) {
System.out.println("Exception caught 3: " + ex);
}
}
} // end of Class Client
If someone can help me, I'm stuck with it.
Some more details I'm using the Amazon server that stays in the United States.
Thank you