0

Im trying to build an camera application for my pets with Sockets. My App works, but its extreeeemly slow, low FPS and low resolution. I already threaded everything i could but its still really laggy. Is there a more efficient way of transmitting video than Sockets? Things like YouTube work like a charm. How do they do that?

Here is my Cam-Server Code

public static void main(String[] args) throws IOException {
    cam = Webcam.getDefault();

    //cam.setCustomViewSizes(new Dimension(1080, 2340));
    cam.setViewSize(WebcamResolution.QVGA.getSize());


    cam.open();

    new Thread(() -> {
        try {
            camThread();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).start();

    ServerSocket server = new ServerSocket(8886);

    while (true) {
        Socket client = server.accept();

        new Thread(() -> {
            handleConnection(client);
        }).start();
    }
}

public static void compressThread(byte[] input) throws IOException {

    img = Compressor.compress(input);

}

public static void camThread() throws IOException {
    while (true) {
        BufferedImage bufferedImage = cam.getImage();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", baos);

        new Thread(() -> {
            try {
                compressThread(baos.toByteArray());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

public static void handleConnection(Socket client) {
    try {
        OutputStream os = client.getOutputStream();
        InputStream is = client.getInputStream();

        while (client.isConnected()) {

            os.write(img);
            os.flush();

            while (is.available() == 0);
            is.read();

        }
    } catch (IOException ioe) {
        System.out.println(ioe.getMessage());
        try {
            client.close();
        }
        catch (Exception e) {e.printStackTrace();}

    }
}

And my App-Client

while (client.isConnected) {
        while (`is`.available() == 0);

        val baos = ByteArrayOutputStream()

        var bytePre = 11111
        while (`is`.available() != 0) {
            val data = `is`.read()
            baos.write(data)
            if (data == -39) if (bytePre == -1) break
            bytePre = data
        }


        Thread {
            val bytes = baos.toByteArray()

            val bm = BitmapFactory.decodeByteArray(Compressor.decompress(bytes), 0, bytes.size)

            runOnUiThread { video.setImageBitmap(bm) }
        }.start()

        val os = client.getOutputStream()
        os.write(0)
        os.flush()



    }

    runOnUiThread { Toast.makeText(this, "Verbindung wurde geschlossen", Toast.LENGTH_LONG).show() }
Liquid
  • 15
  • 1
  • 5
  • `Socket.isConnected()` doesn't do what you think it does. In particular, it tells you nothing about whether the socket is *currently* "connected". Also, threads don't magically make everything faster. Creating, running, and disposing threads to perform tasks in a tight loop can involve significant overhead. Consider a thread pool or perhaps long-lived threads. This code appears to have no synchronization access of shared object `img`. `camThread()` may spawn two or more threads running compressThread concurrently, each trying to write to `img`. `handleConnection()` also access `img` unsafely. – President James K. Polk Oct 10 '20 at 04:07

1 Answers1

0

You should not read byte-wise and I suppose the busy loop to wait for incoming bytes could use a Thread.sleep(10) to reduce the stress on your CPU.

Try to use the result of is.available() in your read().

See this answer here for an implementation that you could use:

How to read all of Inputstream in Server Socket JAVA

thst
  • 4,592
  • 1
  • 26
  • 40