Capture and re-stream live video with java - java

I need to implement a solution in Java that connects to a CCTV server via TCP Socket, takes a live stream video from it and then takes that stream and outputs it to a spring boot endpoint (RTSP or other protocol) so that it can be shown in a web player.
The problem I have is that I do not quite know how to achieve that, maybe some can help. So far, I've got the following piece of code:
try (Socket socket = new Socket(hostname, port)) {
DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Login command
outToServer.writeBytes(login);
// Start LIVE video
outToServer.writeBytes(live);
ByteArrayOutputStream outStreamObj;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] byteChunk = new byte[1024];
InputStream input = socket.getInputStream();
int c = input.read(byteChunk);
while (c != -1) {
buffer.write(byteChunk, 0, c);
c = input.read(byteChunk); // If placed in its own loop, it will read forever (or until the stream stops) so it will never exit
BufferedImage image = ImageIO.read(new ByteArrayInputStream(buffer.toByteArray()));
// create the object of ByteArrayOutputStream class
outStreamObj = new ByteArrayOutputStream();
// write the image into the object of ByteArrayOutputStream class
ImageIO.write(image, "jpg", outStreamObj);
// create the byte array from image
byte[] byteArray = outStreamObj.toByteArray();
// create the object of ByteArrayInputStream class
// and initialized it with the byte array.
ByteArrayInputStream inStreambj = new ByteArrayInputStream(byteArray);
// read image from byte array
BufferedImage newImage = ImageIO.read(inStreambj);
// write output image
ImageIO.write(newImage, "jpg", new File("outputImage.jpg"));
System.out.println("Image generated from the byte array.");
}
} catch (UnknownHostException ex) {
...
} catch (IOException ex) {
...
}
So far, it works until BufferedImage image = ImageIO.read(new ByteArrayInputStream(buffer.toByteArray()));, where image is null. I am not even sure if this is correct. I wouldn't really want to save the image on disk any way, but for now it's okay i guess.
Basically, how it should work as follows:
User visits a web page (Angular)
The web player loads with a live stream url to the spring boot backend
The spring boot backend connect further to the CCTV server via TCP (not possible via RTSP or other protocol) and sends the live command via the socket
Within the same socket session the server starts pushing the live stream bytes
The spring boot app takes these bytes and sends them further to the browser.
Any suggestions?

Related

Inconsistent byte array read when sent from PC to PC and from PC to Android

I have a Server application on my PC which reads a jpg file and sends it through a socket to the android device. The problem is that when android device receives a byte array, it can't be converted to bitmap. I created a PC application to receive that same array and the data received is different than on the android even though I am using the same code to receive it.
Hence my assumption is that I somehow need to read it differently on android.
PC Java Server
ServerSocket serverSocket = new ServerSocket(PORT);
Socket clientSocket = serverSocket.accept();
BufferedImage image = ImageIO.read(new File("D:\\test1\\test.jpg"));
ByteArrayOutputStream byteArrayoutputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", byteArrayoutputStream);
OutputStream outputStream = clientSocket.getOutputStream();
byte[] size = ByteBuffer.allocate(4).putInt(byteArrayoutputStream.size()).array();
outputStream.write(size);
outputStream.write(byteArrayoutputStream.toByteArray());
outputStream.flush();
Thread.sleep((long)5000);
clientSocket.close();
Android receiver
DataInputStream inputStream = new DataInputStream(serverSocket.getInputStream());
byte[] sizeAr = new byte[4];
inputStream.read(sizeAr);
int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();
byte[] imageAr = new byte[size];
inputStream.read(imageAr);
System.out.println(imageAr.toString());
bMap = BitmapFactory.decodeByteArray(imageAr, 0, imageAr.length);//this returns null
You probably are not receiving the whole thing,
Instead:
inputStream.read(imageAr);
try:
inputStream.read(imageAr, 0, size);
the second form will wait until size bytes are received.
ADDED
Also do the same on the first read()
instead: inputStream.read(sizeAr); try inputStream.read(sizeAr, 0, 4);
Also get and check inputStream.read() return values, it says how many bytes were really read.

Android Java: Receive Image over Socket

i have a communication App over sockets.
The Client sends an Image to the server:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
OutputStream os;
try {
os = MyClient.socket.getOutputStream();
os.write(byteArray,0,byteArray.length);
os.flush();
On the server side i want to receive the Image, but at the moments it just shows many different characters. If the Client just sends a text i receive it with:
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String text = input.readLine();
But how can i "decode" the byte[] on the Server Side?
Analogously to how you sent that image. Simply use an InputStream object like this:
InputStream stream = socket.getInputStream();
byte[] data = new byte[MAX_SIZE];
int count = stream.read(data);
Both objects (sending and receiving) are compatible this way, you just have to know the byte array size, it has to be the same on both places.

Send image from android part and receive it from pc, but the image is corrupted

I'm trying to send an jpeg image from my android phone through socket and from the PC part, get the sent data and store it in an jpg file.
I'm pretty sure that I configured the socket correctly, as I can download data (binary file) from PC to android and save it correctly.
I can also read the stream which is sent from android to PC. The packet length and header information are exactly what I expect.
The problem is in reading image data. I'm getting same size for image data but when I save it to .jpg file, it is corrupted and I can not view it.
Here is my Android code that tries to send image file after sending header information:
try{
//packagesize is header information which is sent in advance
index.putInt(packagesize);
byte c[]= {index.get(3),index.get(2),index.get(1),index.get(0)};
InputStream jpgimage = new FileInputStream(fileimage);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
int writeBytes = 0,len = 0;
byte buffer[] = new byte[1024];
while((len = jpgimage.read(buffer,0,buffer.length))!=-1)
{
writeBytes+=len;
dataOutputStream.write(buffer,0,len);
}
dataOutputStream.flush();
jpgimage.close();
dataInputStream.close();
dataOutputStream.close();
...
...
...
}
catch statements here
This is the receiving code in the PC part:
// after reading header information I try to read image data
char *buff = malloc(sizeof(char) * jpeg_length);
unsigned int byteCount = 0;
unsigned int byteCount = 0;
do
{
int ret = recv(socket, buff+readBytes, jpeg_length-readBytes, 0);
if (ret <= 0)
{
fprintf(stderr,"Error receiving jpeg file.\n");
fclose( output );
return 106;
}
readBytes += ret;
fwrite(buff, sizeof(char), readBytes, output);
}
while (readBytes < jpeg_length);
fclose( output );
I also have to mention that the receiving part is working fine when I send image data with PC client application which is pure C++.
Is there any idea about what is the problem and why I get corrupted image sending from android device?
Appreciate it.
Edited
I add this the to android application for testing if the sending bytes can form a good image or not? I saved the image and it was OK.
int writeBytes = 0,len = 0;
byte buffer[] = new byte[1024];
// Here I save all sending bytes to an image called test.jpg
String path = "sdcard/download/images/test.jpg";
FileOutputStream stream = new FileOutputStream(path);
while((len = jpgimage.read(buffer,0,buffer.length))!=-1)
{
writeBytes+=len;
stream.write(buffer);
dataOutputStream.write(buffer,0,len);
dataOutputStream.flush();
}
stream.flush();
dataOutputStream.flush();
jpgimage.close();
dataInputStream.close();
dataOutputStream.close();
I think you should use Bitmap class to convert you image to ByteBuffer and then send it across and on the other end convert ByteBuffer to image.
On Sender Side
Bitmap bitmap = BitmapFactory.decodeFile("ImageD2.jpg");
int bytes = bitmap.getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
byte[] array = buffer.array();
Now you can send byte[] as normal data.
On receiving side
receive the array normally and convert it back to Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(array , 0, array .length);
for more information you can read following questions
Converting bitmap to byteArray android
How to convert byte array to Bitmap
I found the solution for that. The problem was from Android side. So I did the following changes:
I changed DataOutputStream and DataInputStream to BufferedOutputStream and BufferedInputStream respectively :
try{
//packagesize is header information which is sent in advance
index.putInt(packagesize);
byte c[]= {index.get(3),index.get(2),index.get(1),index.get(0)};
InputStream jpgimage = new FileInputStream(fileimage);
dataOutputStream = new BufferedOutputStream(socket.getOutputStream());
dataInputStream = new BufferedInputStream(socket.getInputStream());
int writeBytes = 0,len = 0;
byte buffer[] = new byte[1024];
while((len = jpgimage.read(buffer,0,buffer.length))!=-1)
{
writeBytes+=len;
dataOutputStream.write(buffer,0,len);
}
dataOutputStream.flush();
jpgimage.close();
dataInputStream.close();
dataOutputStream.close();
...
...
...
}
catch statements here

Displaying an image from an InputStream

I am able to send strings from my Android mobile phone to my computer, and vice versa. However, I want to send an image from my computer and display it to the mobile phone. In my case, the computer is the server and the mobile phone is the client.
This is part of my code on the server side:
socket = serverSocket.accept();
dataOutputStream = new DataOutputStream(socket.getOutputStream());
captureScreen("C:\\Users\\HP\\Desktop\\capture.png");
File f = new File("C:\\Users\\HP\\Desktop\\capture.png");
byte [] buffer = new byte[(int)f.length()];
dataOutputStream.write(buffer,0,buffer.length);
dataOutputStream.flush();
Note that captureScreen() is a method that successfully takes a screenshot of the server and save it as a .PNG image in the above path.
Now, on the client side which is the Android mobile phone, if I have an ImageView control, how to read the image sent from the computer as an InputStream and display it on the ImageView?
Furthermore, did I write successfully the image to the dataOutputStream? I would be glad if any one helps me !
You can call the setImageBitmap(Bitmap bm) of your ImageView.
http://developer.android.com/reference/android/widget/ImageView.html
How you get the image data to your client: it depends on the solution you have chosen, but technically you can use the same libraries that you would use for pure Java.
You can use android.graphics.BitmapFactory to create the Bitmap from your stream.
http://developer.android.com/reference/android/graphics/BitmapFactory.html
Bitmap bitmap1 = BitmapFactory.decodeStream(inputStream);
Bitmap bitmap2 = BitmapFactory.decodeFile(filename);
what is this ?
byte [] buffer = new byte[(int)f.length()];
dataOutputStream.write(buffer,0,buffer.length);
You just declared size of a buffer byte array , but it`s empty!
You should to convert your file to byte and than transfer it to OutputStream , smth like this:
byte[] buffer = System.IO.File.ReadAllBytes("C:\\Users\\HP\\Desktop\\capture.png");
(code for c#)
And than you will send it like you did:
dataOutputStream.write(buffer,0,buffer.length);
dataOutputStream.flush();
try this for file receiving :
public void fileReceived(InputStream is)
throws FileNotFoundException, IOException {
Log.i("IMSERVICE", "FILERECCC-1");
if (is!= null) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream("/sdcard/chats/gas1.jpg/");
bos = new BufferedOutputStream(fos);
byte[] aByte = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(aByte)) != -1) {
bos.write(aByte, 0, bytesRead);
}
bos.flush();
bos.close();
Log.i("IMSERVICE", "FILERECCC-2");
} catch (IOException ex) {
// Do exception handling
}
}
}
}
So you`ll got new file in your sd-card on Android.

Get InputStream From a Socket

I want to stream and audio with SIP Connection in java application(SE).I connected with the server and got 200 OK messages.I want to receive data sent by the server. I created a SOCKET and got an InputStream. Here is how I do it. 123.456.789.1 is the my ip address and 1234 is which my application listening port.
Socket socket=new Socket("123.456.789.1",1234);
InputStream in=socket.getInputStream();
System.out.println("inputSream available :"+in.available());
But in.available() is always 0 .
But if I get the Object content=response.getContent();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(content);
byte[] contentBytes = bos.toByteArray();
the lenght of contenBytes equals to the response content length.But when I try to get inputStream and Play ,like following
InputStream pp=new ByteArrayInputStream(b);
AudioStream as = new AudioStream(pp);
AudioData data = as.getData();
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
An Exception throws;java.io.IOException: could not create audio stream from input stream
Then I tried to read the inputstream in.read() then when read some bytes,and IOException was thrown.
Q1. How can I solve and get InputStream from the socket?
Q2. how to get an inputStream to play the audio?
or let me know where the problem is and how to solve it.
UPDATED: Thank you all who showed a fault in.availabe();
Then I changed the code.
ByteArrayOutputStream ou=new ByteArrayOutputStream();
int i=0;
System.out.println("Before while");
while((i=in.read())!=-1){
ou.write(i);
System.out.println("Wrote :"+i);
}
Unfortunately the application doesn't go further.That means only Before while is printed.Application just shows running(I use netbeans IDE).I don't why.Any clarification?
When you use getContent you get some kind of object wrapping the content. Then using an ObjectOutputStream you write the Java representation of that object, not the actual bytes of the original data.
You should be able to do
AudioStream as = new AudioStream(in);
AudioData data = as.getData();
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
or if you do want to buffer the data
int chunkSize;
byte[] chunk = new byte[2048];
ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
while ( ( chunkSize = in.read(chunk) ) != -1) {
outBuffer.write(chunk, 0, chunkSize);
}
ByteArrayInputStream inBuffer = new ByteArrayInputStream(outBuffer.toByteArray());
AudioStream as = new AudioStream(inBuffer);
AudioData data = as.getData();
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
available() show how many bytes can be guaranteed read before blocking. It might always return 0.
available() is the number of bytes which can be read with out performing a blocking call to the OS. If you want to know how much data is available you should try to read it and see how much you get.

Categories