Client-server live stream using RPi camera using JAVA - java

I am trying to do live stream from RPi camera in java but I have problem because I am very new in this kind of programming and didn't find answer that would help me with this.
I have my server app from this page: enter link description here
It works with .NET but I want to do whole thing in Java(UDP version in my case).
I was following documentation on enter link description here but it still doesn't work.
Here is my code of the client app:
public class CamService {
public static IDuplexOutputChannel myVideoChannel;
public static String StreamAddr = "udp://192.168.0.145:8093/";
public static OutputStream myVideoStream;
public static BufferedOutputStream bOut;
public static String pName;
public static void main(String[] args) throws Exception {
JFrame frame;
EmbeddedMediaPlayerComponent mediaPlayerComponent;
new NativeDiscovery().discover();
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "c:\\program files (x86)\\videolan\\vlc\\");
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
IMessagingSystemFactory aMessaging = new UdpMessagingSystemFactory();
myVideoChannel = aMessaging.createDuplexOutputChannel(StreamAddr);
myVideoChannel.responseMessageReceived().subscribe(myOnResponseMessageReceived);
frame = new JFrame("AWWWW!");
frame.setBounds(100, 100, 600, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
myVideoChannel.closeConnection();
System.exit(0);
}
});
frame.setContentPane(mediaPlayerComponent);
frame.setVisible(true);
String[] mediaOptions = {
":sout=#transcode{vcodec=h264,venc=x264{preset=ultrafast},vb=512 }"
+ ":std{access=udp,mux=ts}" };
Media media = new SimpleMedia(StreamAddr, mediaOptions);
mediaPlayerComponent.getMediaPlayer().playMedia(media);
myVideoChannel.openConnection();
}
private static void onResponseMessageReceived(Object sender, DuplexChannelMessageEventArgs e) throws IOException
{
byte[] aMessage = (byte[])e.getMessage();
System.out.println("Byte message: " + aMessage);
myVideoStream.write(aMessage, 0, aMessage.length);
bOut = new BufferedOutputStream(myVideoStream);
System.out.println("Buffered Output: " + myVideoStream);
}
private static EventHandler<DuplexChannelMessageEventArgs> myOnResponseMessageReceived = new EventHandler<DuplexChannelMessageEventArgs>()
{
#Override
public void onEvent(Object sender, DuplexChannelMessageEventArgs e)
{
try {
onResponseMessageReceived(sender, e);
} catch (IOException e1) {
System.out.println("NOPE");
e1.printStackTrace();
}
}
};
}
I am not getting any errors while compiling it. It connects to server, turning on the camera but it doesn't stream it. After closing program i am getting:
main stream error: cannot pre fill buffer
Would be very thankful for ANY help with this.
Thanks.

Related

Video doesn't play on loop or repeat (vlcj-java)

I am using vlcj on my java program. I need the video to play repeatedly. I've used setRepeat(true); but it doesn't work for me. Is this any other to loop the video? Or am I doing it wrong? Please help me. Thanks a lot.
public QueueMonitor() {
initComponents();
//VIDEO
chargerLibrairie();
Canvas c = new Canvas();
panel.add(c);
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
//Create a media player instance
EmbeddedMediaPlayer mediaPlayer = mediaPlayerFactory.newEmbeddedMediaPlayer();
mediaPlayer.setVideoSurface(mediaPlayerFactory.newVideoSurface(c));
mediaPlayer.playMedia("Ospital1.mp4");
mediaPlayer.setRepeat(true);
mediaPlayer.setPlaySubItems(true);
}
public static void chargerLibrairie(){
NativeLibrary.addSearchPath(
RuntimeUtil.getLibVlcLibraryName(), "C:/Program Files/VideoLAN/VLC");
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
LibXUtil.initialise();
}
Also, how can I put some functions like pause, play, lower volume while the program is running? Like how a normal video player is able to do.
Here are some minimal examples of how to get repeat play working with vlcj.
For current versions of vlcj, 4.x and later:
// vlcj 4.x+
public class RepeatPlayer {
public static void main(String[] args) throws Exception {
String mrl = "some-cool-video.mp3";
EmbeddedMediaPlayerComponent mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
JFrame f = new JFrame("Repeat Player");
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
}
});
f.setContentPane(mediaPlayerComponent);
f.setVisible(true);
mediaPlayerComponent.mediaPlayer().controls().setRepeat(true);
mediaPlayerComponent.mediaPlayer().media().play(mrl);
Thread.currentThread().join();
}
}
Since it looks like you're using an ancient version of vlcj, this is how it was done previously:
// vlcj 3.12.1
public class RepeatPlayer {
public static void main(String[] args) throws Exception {
String mrl = "some-cool-video.mp3";
final EmbeddedMediaPlayerComponent mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
JFrame f = new JFrame("Repeat Player");
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
}
});
f.setContentPane(mediaPlayerComponent);
f.setVisible(true);
mediaPlayerComponent.getMediaPlayer().setRepeat(true);
mediaPlayerComponent.getMediaPlayer().playMedia(mrl);
Thread.currentThread().join();
}
}
The code in the original question was therefore broadly correct at least with regards to the repeat-play functionality. The most likely problem with the original code is that the media player was garbage collected due to a failure to hold the object references.
public class Video extends javax.swing.JPanel
{
private EmbeddedMediaPlayerComponent video;
private EmbeddedMediaPlayer mediaPlayer;
public Video()
{
initComponents();
initVideo();
}
private void initVideo()
{
video = new EmbeddedMediaPlayerComponent()
{
#Override
public void finished(MediaPlayer mediaPlayer)
{
super.finished(mediaPlayer);
System.out.println("FINISHED");
new Thread(() -> {
System.gc();
mediaPlayer.controls().setTime(0);
mediaPlayer.controls().play();
}).start();
}
};
mediaPlayer = video.mediaPlayer();
mediaPlayer.input().enableKeyInputHandling(false);
mediaPlayer.input().enableMouseInputHandling(false);
add(video, BorderLayout.CENTER);
}
public void start(String path)
{
mediaPlayer.media().prepare(path);
mediaPlayer.controls().play();
}
public void stop()
{
mediaPlayer.controls().stop();
mediaPlayer.release();
video.release();
}
#SuppressWarnings("unchecked")
private void initComponents()
{
setLayout(new java.awt.BorderLayout());
}
}

Cant append to JTextArea

I'm trying to create a text chat with Java. I have a Server and a Client that connect to each other using Streams, and send data using the objectInputStream and objectOutputStream.
I have GUI's for both the client and the server.
I made these GUI's using intellij's GUI Form.
server GUI form image
The problem I'm having is when I try to display text to the GUI of the server. I can append to the GUi if I call my relayToAll method from the JTextField actionlistener, which then send the message to all the clients and prints it out in the servers GUI.
If i try to call the same method from where I receive the input, then the append to the text area does not work.
Can anyone tell me why its not appending?
Thanks
public class ServerTest {
private JTextField textField1;
private JTextArea textArea1;
private JPanel Panel;
static private ObjectOutputStream objectOutputStream;
static private ObjectInputStream objectInputStream;
static private Socket client;
static private ArrayList<Socket> clients = new ArrayList<Socket>();
static private ArrayList<ObjectOutputStream> objectOutputStreams = new ArrayList<>();
public void relayToAll(String message){
try {
for(int i = 0; i < clients.size(); i++) {
ObjectOutputStream output = objectOutputStreams.get(i);
output.writeObject(message);
output.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
appendTextArea(message);
}
public void appendTextArea(String text){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("This should go to the Server GUI: " + text);
textArea1.append(text + "\n");
}
});
}
public ServerTest() {
textField1.addActionListener(e -> {
System.out.println(e.getActionCommand());
relayToAll(e.getActionCommand());
textField1.setText("");
});
}
public void ReadInput(ObjectInputStream input, int port){
try {
String oldMessage = "";
while (true) {
String message = (String) input.readObject();
if (message != oldMessage){
System.out.println(port + ": " + message);
oldMessage = message;
relayToAll(port + ": " + message);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void IOSetup(){
try {
ServerSocket serverSocket = new ServerSocket( 6969 );
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("server on\n");
for (int i = 0; i < 5; i++){
client = serverSocket.accept();
clients.add(client);
System.out.println("Connection from: "+ client.getPort());
objectOutputStream = new ObjectOutputStream(client.getOutputStream());
objectOutputStreams.add(objectOutputStream);
objectInputStream = new ObjectInputStream(clients.get(i).getInputStream());
executor.submit(() -> {
ReadInput(objectInputStream, client.getPort());
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest();
application.IOSetup();
}
Actually you've got kind of a silly mistake. Please check lines (A) and (B) below:
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel); // *************** (A)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest(); // *************** (B)
application.IOSetup();
}
Do you see a problem? You're creating TWO ServerTest objects, one that has its Panel variable added to the JFrame and that gets displayed, and the other that is set up for IO communication. The ActionListener changes the state of the displayed JTextArea while the IO communications changes the state of a JTextArea that is in the second ServerTest instance, the one not displayed.
One improvement is to create only one instance:
public static void main(String[] args) {
ServerTest application = new ServerTest(); // create one instance
JFrame frame = new JFrame("Server");
// frame.setContentPane(new ServerTest().Panel);
frame.setContentPane(application.Panel); // and use in both places
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
//ServerTest application = new ServerTest();
application.IOSetup(); // and use in both places
}
Other problems:
You've got long-running code long running and blocking in a background thread, and that is potentially dangerous, and the only reason that your GUI is not getting frozen is because you're starting the GUI (incorrectly) on the main thread and off of the Swing event thread. For more on this, you will want to read up on Swing concurrency: Lesson: Concurrency in Swing
You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.

Java Applets and Proxies

Assuming that I use the following code to connect to a SOCKS5 proxy, would connections or packets sent by an applet that I instantiate go through the same proxy?
System.getProperties().setProperty("socksProxySet", "true");
System.getProperties().setProperty("socksProxyHost", "*.*.*.*");
System.getProperties().setProperty("socksProxyPort", "*");
Applet is started using a classloader object from which a newInstance is created.
classLoader = new CustomClassLoader(/* Hashmap of byte arrays */); // Custom classloader that works using byte arrays
Applet applet = (Applet) classLoader.loadClass("class").newInstance();
applet.setStub(stub);
applet.init();
applet.start();
frame.add(applet);
It appears that the answer to this question is yes.
The following code:
public class TestApplet extends Applet {
private String ip;
public void init() {
try {
URL ipCheck = new URL("http://checkip.amazonaws.com");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ipCheck.openStream()));
ip = bufferedReader.readLine();
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop() {
}
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.CYAN);
g.drawString("Current IP: " + ip, 10, 20);
}
}
and
public class Boot {
public static void main(String[] args) {
System.getProperties().setProperty("socksProxySet", "true");
System.getProperties().setProperty("socksProxyHost", "71.9.127.141"); //Credits to HideMyAss.com
System.getProperties().setProperty("socksProxyPort", "28045");//Credits to HideMyAss.com
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
TestApplet testApplet = new TestApplet();
testApplet.init();
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(500, 500);
jFrame.setContentPane(testApplet);
jFrame.setVisible(true);
}
}).start();
}
}
Outputs:
Tyler, if I understand your question correctly - yes. But this comes with a caveat: the System properties that you set will persist only across the current JVM instantiation.
So, if like your example shows you set the properties and execute the Applet on the same JVM you should be fine.

Where can I find the StreamedTextArea() class - is it deprecated?

javac cannot find this class : StreamedTextArea() which I assumed was part of java.awt.*. If I need to write it myself then can anyone offer me some advice. The only references to it online were from ~1999 which inclines me to think it is not a Sun class but one I must write myself. Also in this code (which is from a textbook) they use Frame instead of JFrame. Is this deprecated, how should this application be written nowadays ? Please I have tried finding the answers myself online but to no avail.
The application :
//URLViewer.java
//This is a simple application that provides a window in which you can view the
//contents of a URL.
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class URLViewer extends Frame implements WindowListener, ActionListener {
TextField theURL = new TextField();
Button loadbutton = new Button("load");
StreamedTextArea theDisplay = new StreamedTextArea();
public URLViewer() {
super ("URL Viewer");
}
public void init() {
this.add("North", theURL);
this.add("Center", theDisplay);
Panel south = new Panel();
south.add(loadbutton);
this.add("South", south);
theURL.addActionListener(this);
this.addWindowListener(this);
this.setLocation(50, 50);
this.pack();
this.show();
}
public void actionPerformed (ActionEvent evt) {
try {
URL u = new URL (theURL.getText());
InputStream in = u.openStream();
OutputStream out = theDisplay.getOutputStream();
StreamCopier.copy(in, out);
in.close();
out.close();
} catch (MalformedURLException ex) {theDisplay.setText("Invalid URL");}
catch (IOException ex) {theDisplay.setText("Invalid URL");}
}
public void windowClosing (WindowEvent e) {
this.setVisible(false);
this.dispose();
}
public void windowOpened(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public static void main (String[] args) {
URLViewer me = new URLViewer();
me.init();
}
}
And StreamCopier :
import java.io.*;
public class StreamCopier {
public static void main (String[] args) {
try {
copy (null, null);
} catch (IOException e) {System.err.println(e);}
}
public static void copy (InputStream in, OutputStream out) throws IOException {
//do not allow other threads to read from the input or
//write to the output while copying is taking place.
synchronized (in) {
synchronized (out) {
byte [] buffer = new byte [256];
while (true) {
int bytesRead = in.read(buffer);
if (bytesRead == -1) break;
out.write(buffer, 0, bytesRead);
}
}
}
} //end copy()
}
Here is StreamedTextArea.java. I found it on this page, which also has code that matches your StreamCopier class. This page also contains information on that site.

Redirecting System.out to JTextPane

I have a class (shown below) that extends JPanel and contains a JTextPane. I want to redirect System.out and System.err to my JTextPane. My class does not seem to work. When I run it, it does redirect the system prints, but they do not print to my JTextPane. Please help!
Note: The calls are only redirected when the application launches. But any time after launch, the System.out calls are not redirected to the JTextPane. (ie, if I place a System.out.prinln(); in the class, it will be called, but if it is placed in a actionListener for later use, it does not redirect).
public class OSXConsole extends JPanel {
public static final long serialVersionUID = 21362469L;
private JTextPane textPane;
private PipedOutputStream pipeOut;
private PipedInputStream pipeIn;
public OSXConsole() {
super(new BorderLayout());
textPane = new JTextPane();
this.add(textPane, BorderLayout.CENTER);
redirectSystemStreams();
textPane.setBackground(Color.GRAY);
textPane.setBorder(new EmptyBorder(5, 5, 5, 5));
}
private void updateTextPane(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Document doc = textPane.getDocument();
try {
doc.insertString(doc.getLength(), text, null);
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
textPane.setCaretPosition(doc.getLength() - 1);
}
});
}
private void redirectSystemStreams() {
OutputStream out = new OutputStream() {
#Override
public void write(final int b) throws IOException {
updateTextPane(String.valueOf((char) b));
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextPane(new String(b, off, len));
}
#Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
}
}
Piped streams always confuse me, which is why my Message Console solution doesn't use them. Anyway here is my attempt at a console using piped streams. A couple of differences:
a) it uses a JTextArea because a JTextArea is more efficient than a JTextPane for just displaying text. Of course if you intend to add attributes to the text then you need a text pane.
b) this solution uses Threads. I'm sure I read somewhere that this was necessary to prevent blocking of the output. Anyway it works in my simple test case.
import java.io.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class Console implements Runnable
{
JTextArea displayPane;
BufferedReader reader;
private Console(JTextArea displayPane, PipedOutputStream pos)
{
this.displayPane = displayPane;
try
{
PipedInputStream pis = new PipedInputStream( pos );
reader = new BufferedReader( new InputStreamReader(pis) );
}
catch(IOException e) {}
}
public void run()
{
String line = null;
try
{
while ((line = reader.readLine()) != null)
{
// displayPane.replaceSelection( line + "\n" );
displayPane.append( line + "\n" );
displayPane.setCaretPosition( displayPane.getDocument().getLength() );
}
System.err.println("im here");
}
catch (IOException ioe)
{
JOptionPane.showMessageDialog(null,
"Error redirecting output : "+ioe.getMessage());
}
}
public static void redirectOutput(JTextArea displayPane)
{
Console.redirectOut(displayPane);
Console.redirectErr(displayPane);
}
public static void redirectOut(JTextArea displayPane)
{
PipedOutputStream pos = new PipedOutputStream();
System.setOut( new PrintStream(pos, true) );
Console console = new Console(displayPane, pos);
new Thread(console).start();
}
public static void redirectErr(JTextArea displayPane)
{
PipedOutputStream pos = new PipedOutputStream();
System.setErr( new PrintStream(pos, true) );
Console console = new Console(displayPane, pos);
new Thread(console).start();
}
public static void main(String[] args)
{
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane( textArea );
JFrame frame = new JFrame("Redirect Output");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( scrollPane );
frame.setSize(200, 100);
frame.setVisible(true);
Console.redirectOutput( textArea );
final int i = 0;
Timer timer = new Timer(1000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println( new java.util.Date().toString() );
System.err.println( System.currentTimeMillis() );
}
});
timer.start();
}
}
Message Console class does this for you.
Edit:
Here is a simple test class:
import java.io.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class MessageConsoleTest
{
public static int counter;
public static void main(String[] args)
throws Exception
{
JTextComponent textComponent = new JTextPane();
JScrollPane scrollPane = new JScrollPane( textComponent );
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Message Console");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( scrollPane );
frame.setSize(400, 120);
frame.setVisible(true);
MessageConsole console = new MessageConsole(textComponent);
console.redirectOut();
console.redirectErr(Color.RED, null);
Timer timer = new Timer(1000, new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
System.out.println( new java.util.Date().toString() );
}
});
timer.start();
Thread.sleep(750);
Timer timer2 = new Timer(1000, new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
System.err.println( "Error Message: " + ++counter);
}
});
timer2.start();
}
}
In the following link you can find the MessageConsole class that someone mentioned. I implemented a software and used this solution and it works perfect for me.
I used the Netbeans design tool, so the code regarding the visual appearance of the JTextPane is a bit cumbersome, so I'm not going to place it here.
JTextPane jTextPane = new JTextPane();
MessageConsole console = new MessageConsole(jTextPane);
/*
This parameters are optional, but if you are looking for a solution with JTextPane it is because you need them, at least color.
*/
console.redirectErr(Color.RED, null);
console.redirectOut();
//some event
private void jButton1ActionPerformed(ActionEvent evt) {
/*
In this event I execute a function of my business.
I put it in a thread so that it does not block the graphical interface.
There are many calls to System.out.println() and System.err.println()
*/
BusinessClass bc = new BusinessClass();
Runnable runnable = () -> {
bc.someBusinessFn();
};
thread = new Thread(runnable);
thread.start();
}
//My main method
public static void main(String args[]) {
/* Create and display the GUI */
EventQueue.invokeLater(() -> {
new MyJFrame().setVisible(true);
});
}
Edit
Sorry, I did not realize that in the response similar to this, they had put the link to the MessageConsole class. I didn't see it and I also wanted to show my solution.

Categories