2017-08-24 100 views
0

在我的項目中,我需要通過UDP接收視頻。源IP地址爲224.0.0.21,宿端IP爲169.254.170.141。我通過端口3956接收視頻(這是來自Wireshark的有效信息)。我使用SharpPcap接收UDP流量,但它沒有加入組播的方法。我嘗試從MSDN這個代碼,但它不工作。不能加入組播組c#

 IPAddress multicastaddress = IPAddress.Parse("224.0.0.21"); 
     IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 3956); 
     m_ClientTarget.JoinMulticastGroup(multicastaddress, localAddr); 

在我的電腦中,我有一些網絡適配器,但我使用設備的IP地址,連接到源視頻。源和宿直接連接。當我在wireshark中啓動監視器流量時,我的程序也會收到數據包,但是如果沒有wireshack,它就不能執行它。 我的代碼:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using SharpPcap; 
using SharpPcap.LibPcap; 
using SharpPcap.AirPcap; 
using SharpPcap.WinPcap; 
using System.IO; 
using System.Net.Sockets; 
using System.Net; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 
using System.Threading; 

namespace GVSPCapture 
{ 
    public partial class Form1 : Form 
    { 

     static int frameCounter = 0; 
     static byte[] pixels = new byte[1920 * 1080 * 3]; 
     static IPAddress fpgaAddr = IPAddress.Parse("224.0.0.21"); 
     static IPAddress localAddr = IPAddress.Parse("169.254.170.141"); 
     static MulticastOption mcastOption = new MulticastOption(fpgaAddr, localAddr); 
     private static UdpClient m_ClientTarget = new UdpClient(3956); 
     private static IPAddress m_GrpAddr; 
     const int GroupPort = 3956; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      findDevices(); 
     } 

     public void findDevices() 
     { 
      string ver = SharpPcap.Version.VersionString; 

      var devices = CaptureDeviceList.Instance; 

      foreach (var dev in devices) 
      { 
       lbxDevices.Items.Add(dev.Name + dev.Description); 
      } 

     } 

     private void JoinVideoMulticast() 
     { 

      IPAddress multicastaddress = IPAddress.Parse("224.0.0.21"); 
      IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 3956); 
      m_ClientTarget.JoinMulticastGroup(multicastaddress, IPAddress.Parse("169.254.170.141")); 

      while (true) 
      { } 

     } 

     private void startCapture(ICaptureDevice dev) 
     { 
      if (!dev.Started) 
      { 
       dev.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); 
       int readTimeoutMilliseconds = 1000; 
       if (dev is AirPcapDevice) 
       { 
        // NOTE: AirPcap devices cannot disable local capture 
        var airPcap = dev as AirPcapDevice; 
        airPcap.Open(SharpPcap.WinPcap.OpenFlags.DataTransferUdp, readTimeoutMilliseconds); 
       } 
       else if (dev is WinPcapDevice) 
       { 
        var winPcap = dev as WinPcapDevice; 

        winPcap.Open(SharpPcap.WinPcap.OpenFlags.DataTransferUdp | SharpPcap.WinPcap.OpenFlags.NoCaptureLocal, readTimeoutMilliseconds); 
       } 
       else if (dev is LibPcapLiveDevice) 
       { 
        var livePcapDevice = dev as LibPcapLiveDevice; 
        livePcapDevice.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds); 
       } 
       else 
       { 
        throw new System.InvalidOperationException("unknown device type of " + dev.GetType().ToString()); 
       } 

       dev.StartCapture(); 

       Thread recvThread = new Thread(JoinVideoMulticast); 
       recvThread.Start(); 

      } 
     } 

     delegate void SetTextCallback(string text); 

     private void SetText(string text) 
     { 
      // InvokeRequired required compares the thread ID of the 
      // calling thread to the thread ID of the creating thread. 
      // If these threads are different, it returns true. 
      if (this.tbxCnt.InvokeRequired) 
      { 
       SetTextCallback d = new SetTextCallback(SetText); 
       this.Invoke(d, new object[] { text }); 
      } 
      else 
      { 
       this.tbxCnt.Text = text; 
      } 
     } 

     private void device_OnPacketArrival(object sender, CaptureEventArgs e) 
     { 
      var time = e.Packet.Timeval.Date; 
      var len = e.Packet.Data.Length; 
      if (len == 572) 
      { 
       var tmp = e.Packet.Data; 
       int packet_id = tmp[47] << 16 | tmp[48] << 8 | tmp[49]; 
       int startPos = (packet_id - 1) * 522; 
       for (int i = 50; i < tmp.Length; i+=3) 
       { 
        pixels[startPos + i + 0 - 50] = tmp[i]; 
        pixels[startPos + i + 1 - 50] = tmp[i]; 
        pixels[startPos + i + 2 - 50] = tmp[i]; 
       } 
      } 
      if (len == 60) 
      { 
       var im = CopyDataToBitmap(pixels); 
       pictbFrame.Image = im; 
       frameCounter += 1; 
       SetText(frameCounter.ToString()); 
      } 
     } 

     public Bitmap CopyDataToBitmap(byte[] data) 
     { 
      GCHandle pinned = GCHandle.Alloc(data, GCHandleType.Pinned); 
      IntPtr ptr = pinned.AddrOfPinnedObject(); 
      BitmapData dt = new BitmapData(); 
      dt.Scan0 = ptr; 
      dt.Stride = 5760; 
      dt.Width = 1920; 
      dt.Height = 1080; 
      dt.PixelFormat = PixelFormat.Format24bppRgb; 
      Bitmap btm = new Bitmap(1920, 1080, 5760, PixelFormat.Format24bppRgb, dt.Scan0); 
      return btm; 
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      int devNum = lbxDevices.SelectedIndex; 
      if (devNum > 0) 
      { 
       var device = CaptureDeviceList.Instance[devNum]; 
       startCapture(device); 
      } 
     } 

     private void btnStop_Click(object sender, EventArgs e) 
     { 
      int devNum = lbxDevices.SelectedIndex; 
      if (devNum > 0) 
      { 
       var device = CaptureDeviceList.Instance[devNum]; 
       if (device.Started) 
       { 
        device.StopCapture(); 
        device.Close(); 
       } 
      } 
      m_ClientTarget.DropMulticastGroup(fpgaAddr); 
     } 
    } 
} 
+0

一個問題是,是,是保留給路由器功能的多播地址,你不應該試圖加入它擺在首位的PC上。 –

+0

@RonMaupin加入多播地址有什麼不好? –

+0

當多播組被保留用於不同的目的時,這是不好的。該多播組不應該用於視頻。有一個多播地址塊('239.0.0.0-239.255.255.255'組織本地範圍)爲這種類型保留。這就像試圖將屬於Google的IP地址用於您自己的目的。 IANA維護_ [IPv4多播地址空間註冊表](https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml)_,其方式與維護單播地址分配的方式相同。 –

回答

0

我測試的代碼與ffmpeg的

ffmpeg.exe -i aa.mp4 -f MPEG UDP://224.0.0.21:3956

int PORT = 3956; 
string MULTICAST_IP = "224.0.0.21"; 


UdpClient udpClient = new UdpClient(PORT); 
udpClient.JoinMulticastGroup(IPAddress.Parse(MULTICAST_IP)); 

var from = new IPEndPoint(0, 0); 
var recvBuffer = udpClient.Receive(ref from); 
0

沒有看到你的代碼(我假設你所展示的代碼段不止),這很難幫助你。 爲客戶接收多播數據報的基本設置會是這樣的未經檢驗的片段:

UdpClient mClient = new UdpClient(3956, AddressFamily.InterNetwork); 
IPAdress groupAddress = IPAddress.Parse("224.0.0.21); 
mClient.JoinMulticastGroup(groupAddress); 

之後,你使用mClient.Receive接收()...

或許這可以幫助?或者MSDN上的文檔(https://msdn.microsoft.com/en-us/library/ekd1t784(v=vs.110).aspx)。

C.