2017-04-07 12 views
0

私の悪い英語を読んで、申し訳ありません。TCPウェブカメラのストリーミング

私はOpenCVでウェブカメラストリーミングに取り組んでいます。 私の最終的な目標はSkypeのようなアプリケーションを作ることです。 私は最初に基本的な1:1 TCPモデルを試しています。

TCP 1:1モデルについて
接続後、クライアントはリアルタイムWebカメラフレームを送信し、サーバーは受信してjpanelに表示します。

これまで画像を受信して​​jpanelに表示しました。
私は連続したフレームを受信しようとしています。
最初は、サーバーサイドソケットは、クライアントからの入力が完了するまで待機するように見えました。つまり、リアルタイムフレームが連続して送信されるため停止しませんでした。
私は止められないのを待つことから脱出するためにフレームを送る前にすべてのフレームサイズを送った。
しかし、うまくいきません。クライアントはフレームを送信し続けますが、サーバーはそれをうまく受信しません。
例えば、クライアントは約25Kバイトサイズのフレームを送信する場合、サーバは読み取り専用1あたり1〜3バイトを受信して​​も、バッファサイズは512

あるClientThread.java

package client; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.Socket; 

import javax.imageio.ImageIO; 

import video.VideoCap; 

public class ClientThread extends Thread 
{ 

    String serverIp; 
    int  serverPort; 
    Socket socket; 
    VideoCap videoCap; 

    public ClientThread(Socket socket, String serverIp, int serverPort, VideoCap videoCap) 
    { 
     this.socket = socket; 
     this.serverIp = serverIp; 
     this.serverPort = serverPort; 
     this.videoCap = videoCap; 
    } 

    public void run() 
    { 
     while (ClientUI.calling) 
     { 
      try 
      { 
       InputStream in = socket.getInputStream(); 
       DataInputStream dis = new DataInputStream(in); 
       OutputStream out = socket.getOutputStream(); 
       DataOutputStream dos = new DataOutputStream(out); 

       // receive 
       int bufSize = dis.readInt(); 
       while (ClientUI.calling) 
       { 
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
        ImageIO.write(videoCap.getOneFrame(), "jpg", baos); 
        InputStream inputImage = new ByteArrayInputStream(baos.toByteArray()); 

        // frame size 
        dos.writeInt(baos.size()); 
        out(inputImage, baos, bufSize); 
        Thread.sleep(5000); 
       } 

      } 
      catch (IOException | InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    } 

    void out(InputStream in, OutputStream out, int bufSize) 
    { 
     long size = 0; 
     try 
     { 
      byte[] buf = new byte[bufSize]; 
      int n; 
      while ((n = in.read(buf)) > 0) 
      { 
       out.write(buf, 0, n); 
       size += n; 
       System.out.println("size: " + size); 
      } 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 

     finally 
     { 
      System.out.println(getClass().getName() + " :: out >>> sent size: " + size); 
     } 
    } 
} 

ServerThread.java

package server; 

import java.awt.image.BufferedImage; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 

import javax.imageio.ImageIO; 
import javax.swing.JPanel; 

public class ServerThread extends Thread 
{ 
    ServerSocket serverSocket; 
    Socket  socket; 
    JPanel  panel; 
    byte[]  buf; 

    public ServerThread(ServerSocket serverSocket, JPanel panel, int bufSize) 
    { 
     this.serverSocket = serverSocket; 
     this.panel = panel; 
     buf = new byte[bufSize]; 
    } 

    public void run() 
    { 
     try 
     { 
      System.out.println("waiting for client"); 
      socket = serverSocket.accept(); 
      System.out.println("client accepted"); 
      InputStream in = socket.getInputStream(); 
      DataInputStream dis = new DataInputStream(in); 
      OutputStream out = socket.getOutputStream(); 
      DataOutputStream dos = new DataOutputStream(out); 
      dos.writeInt(buf.length); 

      while (ServerUI.calling) 
      { 
       int frameSize = dis.readInt(); 
       ByteArrayOutputStream outImage = new ByteArrayOutputStream(); 
       long size = 0; 
       int n; 

       while (frameSize >= size) 
       { 
        n = dis.read(buf); 
        if (n == -1) 
         break; 
        outImage.write(buf, 0, n); 
        size += n; 
        System.out.println(n); 

       } 

       InputStream inputImage = new ByteArrayInputStream(outImage.toByteArray()); 
       BufferedImage bufferedImage = ImageIO.read(inputImage); 
       panel.getGraphics().drawImage(bufferedImage, 0, 0, null); 
      } 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

} 
+0

なぜクライアントにBUFSIZEを送信するサーバ? –

+0

@SteveSmithバッファのサイズが同じであれば、データの送受信量は同じになると思いました。 – Bana

答えて

0

DataOutput/InputStreamをObjectOutput/InputStreamに変更しました。 なぜうまくいかなかったのか分かりませんが、これはシリアライズの問題が原因だと思います。バイトはシリアライズする必要はありませんので、私は正確にはわかりません。

私は何らかの作業コードを提供します。 AudioServerのために私は2つのスレッドに分けたので、前のコードと以下のコードはかなり異なっています。

VideoServerThread.java

import java.awt.image.BufferedImage; 
import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.ObjectInputStream; 
import java.io.Serializable; 
import java.net.ServerSocket; 
import java.net.Socket; 
import javax.imageio.ImageIO; 
import javax.swing.JPanel; 

public class VideoServerThread extends Thread 
{ 
    private ServerSocket serverSocket; 
    int     videoServerPort; 
    private Socket  socket; 
    private JPanel  panel; 
    private boolean  calling; 

    public VideoServerThread(ServerSocket serverSocket, int videoServerPort, JPanel panel, boolean calling) 
    { 
     this.serverSocket = serverSocket; 
     this.videoServerPort = videoServerPort; 
     this.panel = panel; 
     this.calling = calling; 
    } 

    @Override 
    public void run() 
    { 
     System.out.println("Video Server opened!"); 
     try 
     { 
      serverSocket = new ServerSocket(videoServerPort); 
      socket = serverSocket.accept(); 
      InputStream in = socket.getInputStream(); 
      ObjectInputStream ois = new ObjectInputStream(in); 
      BufferedImage bufferedImage; 
      InputStream inputImage; 
      Frame f; 
      while (calling) 
      { 
       f = (Frame) ois.readObject(); 
       inputImage = new ByteArrayInputStream(f.bytes); 
       bufferedImage = ImageIO.read(inputImage); 
       panel.getGraphics().drawImage(bufferedImage, 0, 0, panel.getWidth(), panel.getHeight(), null); 
       panel.getGraphics().drawImage(bufferedImage, 0, 0, null); 
       bufferedImage.flush(); 
       inputImage.close(); 
       f = null; 
      } 

     } 

     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (ClassNotFoundException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    class Frame implements Serializable 
    { 
     public byte[] bytes; 
     public Frame(byte[] bytes) 
     { 
      this.bytes = bytes; 
     } 

     public int size() 
     { 
      return bytes.length; 
     } 
    } 
} 

VideoClientThread.java

import java.awt.image.BufferedImage; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 
import javax.imageio.ImageIO; 
import common.Frame; 
import video.VideoCap; 

public class VideoClientThread extends Thread 
{ 
    private final String formatType = "jpg"; 
    private VideoCap  videoCap; 
    private Socket  socket; 
    private String  ip; 
    private int   port; 
    private boolean  calling; 

    public VideoClientThread(VideoCap videoCap, Socket socket, String ip, int port, boolean calling) 
    { 
     this.videoCap = videoCap; 
     this.socket = socket; 
     this.ip = ip; 
     this.port = port; 
     this.calling = calling; 
    } 

    public void run() 
    { 
     try 
     { 
      socket = new Socket(ip, port); 
      socket.setSoTimeout(5000); 
      ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 
      Frame f; 
      BufferedImage bufferedImage; 
      while (calling) 
      { 
       ByteArrayOutputStream fbaos = new ByteArrayOutputStream(); 
       bufferedImage = videoCap.getOneFrame(); 
       ImageIO.write(bufferedImage, formatType, fbaos); 
       f = new Frame(fbaos.toByteArray()); 
       oos.writeObject(f); 
       oos.flush(); 
       bufferedImage.flush(); 
       // Thread.sleep(33); 
      } 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
     // catch (InterruptedException e) 
     // { 
     // e.printStackTrace(); 
     // } 
    } 
} 
関連する問題