2013-12-22 201 views
0

我使用UDP進行視頻流傳輸,但由於幀大小超過了udp max的大小,我必須將它分成主要數組並且發送幾個數據包。沒關係,但是它是udp,所以數組通常不按照客戶端的順序(例如:第一幀的第一段,第二幀的第三段等等)。我可以對段進行編碼,但是經常會以錯誤幀(第一幀的第一段,第二幀的第二段,第二幀的第三段)接收段。 發送:UDP視頻流C#

while(true){ 
int c = CvInvoke.cvWaitKey(33); 
if (c == 27) 
break; 
    Byte[] byteData1 = rgb32Image.Bytes; 
    Byte[] byte1 = new Byte[65000]; 
    Byte[] byte2 = new Byte[65000]; 
    Byte[] byte3 = new Byte[65000]; 
    Byte[] byte4 = new Byte[65000]; 
    byte1[0] = 1; 
    byte2[0] = 2; 
    byte3[0] = 3; 
    byte4[0] = 4; 
    System.Buffer.BlockCopy(byteData1, 0, byte1, 1, 64999); 
    obj.socket.Send(byte1, byte1.Length); 
    System.Buffer.BlockCopy(byteData1, 64999, byte2, 1, 64999); 
    obj.socket.Send(byte2, byte2.Length); 
    System.Buffer.BlockCopy(byteData1, 64999 * 2, byte3, 1, 64999); 
    obj.socket.Send(byte3, byte3.Length); 
    System.Buffer.BlockCopy(byteData1, 64999 * 3, byte4, 1, byteData1.Length - (3 * 64999); 
    obj.socket.Send(byte4, byte4.Length); 
} 

接收:

VideoReceive(IAsyncResult ar) 
{ 
StateObject stateobj = (StateObject)ar.AsyncState; 
UdpClient client = stateobj.workSocket; 
IPEndPoint senderIPEndPoint = new IPEndPoint(IPAddress.Any, 0); 
Byte[] byte1 = client.EndReceive(ar, ref senderIPEndPoint); 
Byte[] byte2 = client.Receive(ref senderIPEndPoint); 
Byte[] byte3 = client.Receive(ref senderIPEndPoint); 
Byte[] byte4 = client.Receive(ref senderIPEndPoint); 
switch (byte1[0]) 
{ 
case 1: 
System.Buffer.BlockCopy(byte1, 1, buffer, 0, 64999); 
break; 
case 2: 
System.Buffer.BlockCopy(byte1, 1, buffer, 64999, 64999); 
break; 
case 3: 
System.Buffer.BlockCopy(byte1, 1, buffer, 64999 * 2, 64999); 
break; 
case 4: 
System.Buffer.BlockCopy(byte1, 1, buffer, 64999 * 3, 64999); 
break; 
} 
switch (byte2[0]) 
{ 
case 1: 
System.Buffer.BlockCopy(byte2, 1, buffer, 0, 64999); 
break; 
case 2: 
System.Buffer.BlockCopy(byte2, 1, buffer, 64999, 64999); 
break; 
case 3: 
System.Buffer.BlockCopy(byte2, 1, buffer, 64999 * 2, 64999); 
break; 
case 4: 
System.Buffer.BlockCopy(byte2, 1, buffer, 64999 * 3, 64999); 
break; 
} 
switch (byte3[0]) 
{ 
case 1: 
System.Buffer.BlockCopy(byte3, 1, buffer, 0, 64999); 
break; 
case 2: 
System.Buffer.BlockCopy(byte3, 1, buffer, 64999, 64999); 
break; 
case 3: 
System.Buffer.BlockCopy(byte3, 1, buffer, 64999 * 2, 64999); 
break; 
case 4: 
System.Buffer.BlockCopy(byte3, 1, buffer, 64999 * 3, 64999); 
break; 
} 
switch (byte4[0]) 
{ 
case 1: 
System.Buffer.BlockCopy(byte4, 1, buffer, 0, 64999); 
break; 
case 2: 
System.Buffer.BlockCopy(byte4, 1, buffer, 64999, 64999); 
break; 
case 3: 
System.Buffer.BlockCopy(byte4, 1, buffer, 64999 * 2, 64999); 
break; 
case 4: 
System.Buffer.BlockCopy(byte4, 1, buffer, 64999 * 3, 64999); 
break; 
} 

stateobj.workSocket.BeginReceive(new System.AsyncCallback(VideoReceive), stateobj); 
mask2.Bytes = buffer; 
pictureBox1.BeginInvoke(new MethodInvoker(() => { pictureBox1.Image = mask2.ToBitmap(); })); 

} 

所以,我怎麼能視頻流通過UDP套接字(不帶任何附加庫)? P.S.你可以用代碼或算法來回答。

+0

序列號和大量的緩衝。視頻流!=平凡。 –

+0

@MartinJames所以我問如何做到這一點 –

回答

1

前段時間我做了這個確切的事情,我的解決方案是將圖像分成列併發送每一個。起初我擔心會有過多的幀撕裂,但是高fps相機和流式傳輸效果很好。

發信人:

if(imageAvailable) { 
    try { 
     image = //get image (I am using a BufferedImage image) 
       // here I sent the image size through a tcp connection 
     ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 
     DataOutputStream stream = new DataOutputStream(byteStream); 
     for(int a = 0; a < image.getWidth(); a++) { 
      stream.writeInt(a); 
      for(int b = 0; b < image.getHeight(); b++) { 
       int rgb = image.getRGB(a, b); 
       byte red = (byte) ((rgb >> 16) & 0x000000FF); 
       byte green = (byte) ((rgb >> 8) & 0x000000FF); 
       byte blue = (byte) ((rgb) & 0x000000FF); 
       stream.writeByte(red); 
       stream.writeByte(green); 
       stream.writeByte(blue); 
      } 
       DatagramPacket packet = new DatagramPacket(byteStream.toByteArray(), 0, 
             byteStream.toByteArray().length, dsAddresses); //dsAddresses is the ip of the client. 
       udpSocket.send(packet); 
     } 
     byteStream = new ByteArrayOutputStream(); 
     stream = new DataOutputStream(byteStream); 
    } 

接收機:

public class DataReceiver implements Runnable { 
     private DatagramSocket socket; 
     byte [][][] packets; 
     public DataReceiver(DatagramSocket socket) { 
      this.socket = socket; 
      packets = new byte[640][480][3]; 
     } 

     @Override 
     public void run() { 
     while(true) { 
       DatagramPacket packet = new DatagramPacket(new byte[1444], 1444); 
       try { 
        socket.receive(packet); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
       try{ 
       byte[] data = packet.getData(); 
       DataInputStream inputStream = new DataInputStream(new   
               ByteArrayInputStream(data)); 
       int colum = inputStream.readInt(); 
       for (int a = 0; a < packets[0].length; a++){ 
        packets[colum][a][0] = inputStream.readByte(); 
        packets[colum][a][1] = inputStream.readByte() ; 
        packets[colum][a][2] = inputStream.readByte(); 
       } 
       }catch(Exception e){ 
        e.printStackTrace(); 
       } 

     } 
     } 
    public byte[][][] getData(){ 
     return packets; 
    } 
} 

基本上在分組中發送的每一列,並且一旦該分組被接收的寫它的數據的數組。當其渲染幀的時間抓取數據的副本。

+0

謝謝!現在我沒有PC了,所以當我檢查代碼 –

+0

時,我會批准你的回答,但是你有很多丟包(只有480的約95),所以我有條紋圖像。你有這樣的事嗎? 可能需要更改套接字的某些設置嗎? –

+0

隨着那幾個包的到來,我不確定你能做什麼,你是在局域網還是在互聯網上工作? – Gibby