This filter can receive IPv4 UDP multicast raw MPEG-TS and RTP encapsulated MPEG-TS streams. It has 3 output pins: video, audio and subtitles. Application can connect subtitle pin directly to video renderer or get for graphical subtitles directly from the filter via IUdpMulticast interface. Application can change audio or subtitle track on the fly. IUdpMulticast interface is used to configure the filter and to get informations about the stream. Inbuilt parser doesn't just parse the MPEG-TS itself, but also elementary streams: MPEG1/2, H264 video and MPEG1/2, AC3, AAC audio streams. These media types are the only ones supported by this filter. Beside basic informations from PAT and PMT tables it can also parse service descriptor from SDT table and delivery system descriptor from NIT table. Filter can also measure bitrate of whole stream and bitrate for packets with the same PID. Playback rates higher than 1x are also supported. Filter can be configured in PLAYBACK or PARSING mode. Playback mode must be used in a player, parsing mode, where only parser is activated, can be used for a channel scanner. Filter can also open and play MPEG-TS files. Manifest file is included with filter, so that application can use registration-free activation of com object and therefore filter doesn't need to be registered with regsrv32.
Download Multicast Udp source filter 0.96.8 (1.6.2018)
Older releases
Download Multicast Udp source filter 0.96.0
Download Multicast Udp source filter 0.95.2
Download Multicast Udp source filter 0.94.9
Download Multicast Udp source filter 0.94.2
Download Multicast Udp source filter 0.94.1
Download Multicast Udp source filter 0.93.3
Download Multicast Udp source filter 0.93.0
regsvr32 "Multicast udp source filter.dll"Add filter to the GraphStudio.
#include <initguid.h> #include <dshow.h> #include "mudpf.h" #include "mudpfifc_i.c" void main(void) { CHAR test_maddress[] = "232.4.1.1"; u_short test_port = 5002; IGraphBuilder *pGraph = NULL; IMediaControl *pControl = NULL; IMediaEvent *pEvent = NULL; IBaseFilter *pMudFilter = NULL; IUdpMulticast *pMudpConf = NULL; ICaptureGraphBuilder2 * pCaptureGraphBuilder = NULL; IBaseFilter* pVmr9Filter = NULL; //VMR9 video renderer // Initialize the COM library. HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { printf("ERROR - Could not initialize COM library"); return; } // Create the filter graph manager and query for interfaces. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph); if (FAILED(hr)) { printf("ERROR - Could not create the Filter Graph Manager."); return; } hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); // Create VMR9 filter hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, reinterpret_cast<void**>(&pVmr9Filter)); if (FAILED(hr)) { printf("ERROR - Could not create VMR-9 Video Renderer."); goto exit; } // Create Udp source filter hr = CoCreateInstance(CLSID_UdpSourceFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void**> (&pMudFilter)); if (FAILED(hr)) { printf("ERROR - Could not create Udp Source Filter."); goto exit; // Goto is used here to simplify this example. } hr = pMudFilter->QueryInterface(IID_IUdpMulticast, reinterpret_cast<void**>(&pMudpConf)); // Configure Udp Source Filter as described in method b. pMudpConf->SetMulticastIp(inet_addr(test_maddress)); pMudpConf->SetPort(test_port); // Use any NIC. For multiple NICs, ipv4 address or index (SetNicIndex) of appropriate one must be set. pMudpConf->SetNicIp(0); // Tell demultiplexer to initially set english audio track if possible. pMudpConf->SetAutoConfPreferredTrack(LANGTRACK_AUDIO, "eng"); // Tell demultiplexer to initially set english subtitle track if possible. pMudpConf->SetAutoConfPreferredTrack(LANGTRACK_SUBTITLE, "eng"); // Tell demultiplexer to initially set MPEG2 audio track if possible. pMudpConf->SetAutoConfPreferredAudioType(AUD_TRCK_MPEG2); // Add Udp Source Filter to the graph. hr = pGraph->AddFilter(pMudFilter, L"UDP MPEG-TS Multicast Receiver"); // Add VMR-9 Video renderer to the graph. hr = pGraph->AddFilter(pVmr9Filter, L"VMR-9"); // Start the parser of Udp Source Filter. // In this example we wait until stream is parsed. This can block up to 6 seconds. // In a real application set wait parameter to FALSE and later handle EC_PARSER_COMPLETE event (in WndProc) ! hr = pMudpConf->ParseStream(TRUE); // Real application can't block here, also check for ERR_RECV_IPAGN_AND_IPV4_BIND_FAILED error. // The Capture Graph Builder 2 is a helper object for building graphs. hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, reinterpret_cast<void**>(&pCaptureGraphBuilder)); if (SUCCEEDED(hr)) hr = pCaptureGraphBuilder->SetFiltergraph(pGraph); else goto exit; //Render video pin hr = pCaptureGraphBuilder->RenderStream(NULL, &MEDIATYPE_Video, pMudFilter, NULL, pVmr9Filter); if (FAILED(hr)) { printf("ERROR - Could not render video pin."); goto exit; } //Render audio pin hr = pCaptureGraphBuilder->RenderStream(NULL, &MEDIATYPE_Audio, pMudFilter, NULL, NULL); if (FAILED(hr)) { printf("ERROR - Could not render audio pin."); goto exit; } //printBasicStreamInfo(pMudpConf); pControl->Run(); if (FAILED(hr)) goto exit; MessageBox(NULL, L"Click me to end playback.", L"DirectShow", MB_OK); exit: if (pCaptureGraphBuilder != NULL) pCaptureGraphBuilder->Release(); if (pMudpConf != NULL) pMudpConf->Release(); if (pMudFilter != NULL) pMudFilter->Release(); if (pVmr9Filter != NULL) pVmr9Filter->Release(); pControl->Release(); pEvent->Release(); pGraph->Release(); CoUninitialize(); }
Print some basic informations about the tracks:
void printBasicStreamInfo(IUdpMulticast *pMudpConf) { interop_piddetails_t p_det; pesaudiodet_t aud_det; pesvideodet_t vid_det; subtitling_t sub_det; int progs; pMudpConf->GetProgCount(&progs); for (int prog = 0; prog < progs; prog++) { printf("Program %d \n", prog); int prog_pids = 0; pMudpConf->GetPidCount(prog, &prog_pids); for (int p = 0; p < prog_pids; p++) { pMudpConf->GetParsedData(prog, p, &p_det); printf(" PID= %d type=%d lang= %s PCR=%d ", p_det.pid, p_det.stream_type, p_det.language, p_det.pcr_pid); switch (p_det.stream_type) { case AUD_TRCK_MPEG1: case AUD_TRCK_MPEG2: case AUD_TRCK_DOLBY: case AUD_TRCK_AAC: pMudpConf->GetAudioInfo(prog, p, &aud_det); printf("Audio: bitrate=%d channels=%d freq=%dHz", aud_det.bitrate, aud_det.channels, aud_det.sampfreq); break; case VID_TRCK_MPEG1: case VID_TRCK_MPEG2: case VID_TRCK_H264: pMudpConf->GetVideoInfo(prog, p, &vid_det); printf("Video: dim=%dx%d AR/PAR x=%d y=%d bitrate=%d profile=%d level=%d fps=%d/%d afd=%d int=%d", vid_det.width, vid_det.height, vid_det.aspect_x, vid_det.aspect_y, vid_det.bitrate, vid_det.profile, vid_det.level, vid_det.timeperfieldNom, vid_det.timeperfieldDenom, vid_det.afd, vid_det.interlaced_indicator); // 0x06 = Private PES case 0x06: if (p_det.subtitling_descriptor_count > 0 && p_det.teletext_descriptor_count == 0) { // Get first subtitling descriptor pMudpConf->GetSubDesc(prog, p, 0, &sub_det); printf("Subtitles: %s", sub_det.language); } break; default: break; } printf("\n"); } printf("\n"); } u_short apid, vpid, spid; pMudpConf->GetVideoPid(&vpid); pMudpConf->GetAudioPid(&apid); pMudpConf->GetSubtitlesPid(&spid); printf("Selected PIDS: %d %d %d",vpid,apid,spid); }Put Multicast udp source filter.sxs.manifest and Multicast udp source filter.dll in the same folder as exe.
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 System.Net; using UdpSourceTSParser; using UdpSourceTSParser.DirectShowLib; using UdpSourceTSParser.MediaFoundation; using UdpSourceTSParser.MediaFoundation.EVR; using UdpSourceTSParser.MediaFoundation.Misc; using System.Runtime.InteropServices; //# Example of a multicast udp MPEG_TS player with EVR renderer without error handling. namespace DirectshowCSharpSample { public partial class Form1 : Form { public const int WM_GRAPHNOTIFY = 0x8000 + 1; IPAddress m_mcast_address = IPAddress.Parse("232.4.1.1"); ushort m_port = 5002; TSParser m_parser = null; // Helper class for nicer presentation of stream informations. IBaseFilter m_UdpSource = null; // UDP source and demultiplexer filter . IUdpMulticast m_IUdpMulticast = null; // Interface exposed by UDP source and demultiplexer filter, // used to configure filter. IFilterGraph2 m_FilterGraph = null; IMediaControl m_mediaCtrl = null; IMediaEventEx m_mediaEvent = null; IBaseFilter m_evr = null; // EVR renderer, used on Vista and later. IMFVideoDisplayControl m_evrdisplayCtrl = null; // EVR display control interface. public Form1() { InitializeComponent(); this.Load += Form1_Load; this.Resize += Form1_Resize; this.FormClosing += Form1_FormClosing; } void Form1_Load(object sender, EventArgs e) { int hr = 0; m_FilterGraph = (IFilterGraph2)new FilterGraph(); // Create Udp source and TS demultiplexer filter. m_UdpSource = (IBaseFilter)new UdpSourceFilter(); // Query UdpMulticast source filter for IUdpMulticast interface. m_IUdpMulticast = (IUdpMulticast)m_UdpSource; // Configure Udp Source Filter. hr = m_IUdpMulticast.SetMulticastIp(BitConverter.ToUInt32(m_mcast_address.GetAddressBytes(), 0)); hr = m_IUdpMulticast.SetPort(m_port); // Use ip address of appropriate NIC in a real application. hr = m_IUdpMulticast.SetNicIp(BitConverter.ToUInt32(IPAddress.Any.GetAddressBytes(), 0)); hr = m_IUdpMulticast.SetAutoConfPreferredTrack((ushort)UdpSourceTSParser.lang_track_enum_t.LANGTRACK_AUDIO, "eng"); hr = m_IUdpMulticast.SetAutoConfPreferredTrack((ushort)UdpSourceTSParser.lang_track_enum_t.LANGTRACK_SUBTITLE, "eng"); hr = m_IUdpMulticast.SetAutoConfPreferredAudioType((ushort)UdpSourceTSParser.audio_track_enum_t.AUD_TRCK_MPEG2); //* In real application you will probably want to configure demultiplexer manually and not base on preffered types and languages. // m_IUdpMulticast.SetDemultiplexerFlags(UdpSourceTSParser.TSParser.DEMUX_FLAGS_MANUAL_CONFIG); // Create helper object . m_parser = new TSParser(m_IUdpMulticast); // Add the the filter. hr = m_FilterGraph.AddFilter(m_UdpSource, "Udp Source and TS Parser Filter (MulticastTV)"); m_mediaEvent = (IMediaEventEx)m_FilterGraph; m_mediaEvent.SetNotifyWindow(this.Handle, WM_GRAPHNOTIFY, IntPtr.Zero); m_mediaCtrl = (IMediaControl)m_FilterGraph; hr = m_IUdpMulticast.ParseStream(false); // Check for ERR_RECV_IPAGN_AND_IPV4_BIND_FAILED error. // Configure and add EVR video renderer. This won't work on Win xp. m_evr = (IBaseFilter)new EnhancedVideoRenderer(); configureEVR(); hr = m_FilterGraph.AddFilter(m_evr, "EVR"); } void Form1_Resize(object sender, EventArgs e) { if (m_evrdisplayCtrl != null) { MFVideoNormalizedRect src = new MFVideoNormalizedRect(0, 0, 1, 1); MFRect clientrect = UdpSourceTSParser.MediaFoundation.Misc.MFRect.FromRectangle(this.ClientRectangle); m_evrdisplayCtrl.SetVideoPosition(src, clientrect); } } protected override void WndProc(ref Message m) { if (m.Msg == WM_GRAPHNOTIFY) handleGraphEvents(); base.WndProc(ref m); } void handleGraphEvents() { int hr; IntPtr p1, p2; EventCode ec; while ((hr = m_mediaEvent.GetEvent(out ec, out p1, out p2, 0)) >= 0) { hr = m_mediaEvent.FreeEventParams(ec, p1, p2); if ((int)ec == TSParser.EC_PARSER_COMPLETE) { // Because DEMUX_FLAGS_MANUAL_CONFIG was not set here, // all you need to do is to construct video, audio and subtitle chain. constructChain(); } } } // Must be called when parser completes. void constructChain() { int hr; // Load parsing results from the filter into the list (parser.ProgrameList) ! m_parser.GetInfo(); if (m_parser.ProgrameList.Count == 0) return; // Print some info in the title bar. if (m_parser.ProgrameList[0].Video.Count > 0) this.Text += " Vid: PID=" + m_parser.ProgrameList[0].Video[0].PID + " " + m_parser.ProgrameList[0].Video[0].Width.ToString() + "X" + m_parser.ProgrameList[0].Video[0].Height.ToString(); if (m_parser.ProgrameList[0].Audio.Count > 0) this.Text += " Aud: Count=" + m_parser.ProgrameList[0].Audio.Count + " PID= " + m_parser.selectedAudioPID; //* In real application you will examine ProgrameList and configure demultiplexer here: //m_IUdpMulticast.ConfigureDemultiplexer(m_parser.ProgrameList[0].Video[0].PID, m_parser.ProgrameList[0].Audio[0].PID, 0); // ICaptureGraphBuild2 interface to construct filter chain. ICaptureGraphBuilder2 gbuild2 = null; gbuild2 = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); hr = gbuild2.SetFiltergraph(m_FilterGraph); if (m_parser.ProgrameList[0].Video.Count > 0) hr = gbuild2.RenderStream(null, MediaType.Video, m_UdpSource, null, m_evr); // Video chain if (m_parser.ProgrameList[0].Audio.Count > 0) hr = gbuild2.RenderStream(null, MediaType.Audio, m_UdpSource, null, null); // Audio chain // Run the graph hr = m_mediaCtrl.Run(); Marshal.ReleaseComObject(gbuild2); } void configureEVR() { object o; IMFGetService pGetService = null; pGetService = (IMFGetService)m_evr; pGetService.GetService(MFServices.MR_VIDEO_RENDER_SERVICE, typeof(IMFVideoDisplayControl).GUID, out o); try { m_evrdisplayCtrl = (IMFVideoDisplayControl)o; } catch { Marshal.ReleaseComObject(o); m_evrdisplayCtrl = null; throw; } m_evrdisplayCtrl.SetVideoWindow(this.Handle); // Parent window m_evrdisplayCtrl.SetAspectRatioMode(MFVideoAspectRatioMode.PreservePicture);// Aspect ratio Rectangle r = this.ClientRectangle; // Position MFRect rc = new MFRect(r.Left, r.Top, r.Right, r.Bottom); m_evrdisplayCtrl.SetVideoPosition(null, rc); } void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (m_IUdpMulticast != null) Marshal.ReleaseComObject(m_IUdpMulticast); if (m_evrdisplayCtrl != null) { Marshal.ReleaseComObject(m_evrdisplayCtrl); m_evrdisplayCtrl = null; } if (m_evr != null) Marshal.ReleaseComObject(m_evr); if (m_mediaEvent != null) Marshal.ReleaseComObject(m_mediaEvent); if (m_mediaCtrl != null) Marshal.ReleaseComObject(m_mediaCtrl); if (m_FilterGraph != null) Marshal.ReleaseComObject(m_FilterGraph); } } }
Example of audio track change on the fly in a c++ application.
HRESULT changeAudio(u_short pid) { //If format is exactly the same, we can only change PID in demultiplexer. IPin* demuxAudio_OutPin; hr = pMudFilter->FindPin(L"Audio", &demuxAudio_OutPin); FAIL_RET(hr); // Block flow from pins. IPinFlowControl* fc=NULL; hr = demuxAudio_OutPin->QueryInterface(IID_IPinFlowControl, reinterpret_cast<void**>(&fc)); if (hr != S_OK) { demuxAudio_OutPin->Release(); return hr; } fc->Block(AM_PIN_FLOW_CONTROL_BLOCK, NULL); IPin* decAudio_InPin=NULL; hr = demuxAudio_OutPin->ConnectedTo(&decAudio_InPin); if (hr != S_OK) goto clean; PIN_INFO PinInfo; hr = decAudio_InPin->QueryPinInfo(&PinInfo); IBaseFilter* decAudio_filter = NULL; decAudio_filter = PinInfo.pFilter; IGraphConfig* conf=NULL; hr = g_pGraph->QueryInterface(IID_IGraphConfig, reinterpret_cast<void**>(&conf)); if (hr != S_OK) goto clean; HRESULT aud_act = pMudpConf->SetAudioPid(pid); switch (aud_act) { case AUDIO_PID_CHANGE_NO_CHANGES_NEEDED: // Just unblock the flow fc->Block(0, NULL); break; case AUDIO_PID_CHANGE_FORMAT_CHANGE_NEEDED: case AUDIO_PID_CHANGE_RECONNECTION_NEEDED: hr = g_pGraph->Disconnect(demuxAudio_OutPin); hr = conf->Reconnect(demuxAudio_OutPin, decAudio_InPin, NULL, decAudio_filter, NULL, AM_GRAPH_CONFIG_RECONNECT_DIRECTCONNECT); fc->Block(0, NULL); break; } clean: if (conf != NULL) conf->Release(); if (decAudio_InPin != NULL) decAudio_InPin->Release(); fc->Release(); demuxAudio_OutPin->Release(); return hr; }
Example of audio track change on the fly in a c# application.
private void changeAudioTrack(ushort track) { IPin demuxaudioout = null; m_UdpSource.FindPin("Audio", out demuxaudioout); IPinFlowControl fc = (IPinFlowControl)demuxaudioout; // Block flow from pins fc.Block(AMPinFlowControl.Block, IntPtr.Zero); // Change PID and get result; TSParser.AudioPidChangeResult changeResult = (TSParser.AudioPidChangeResult)m_IUdpMulticast.SetAudioPid(m_parser.ProgrameList[m_selected_tracks.ProgramIndex].Audio[track].PID); m_selected_tracks.AudioIndex = track; switch (changeResult) { case TSParser.AudioPidChangeResult.NoChange : // Unblock pin output. fc.Block(AMPinFlowControl.None, IntPtr.Zero); break; case TSParser.AudioPidChangeResult.FormatChange: case TSParser.AudioPidChangeResult.ReconnectionNeeded: m_FilterGraph.Disconnect(demuxaudioout); IPin ffaudioin = null; m_ffAudio.FindPin("In", out ffaudioin); IGraphConfig conf = (IGraphConfig)m_FilterGraph; conf.Reconnect(demuxaudioout, ffaudioin, null, m_ffAudio, IntPtr.Zero, AMGraphConfigReconnect.DirectConnect); // Unblock pin output. fc.Block(AMPinFlowControl.None, IntPtr.Zero); Marshal.ReleaseComObject(ffaudioin); break; } Marshal.ReleaseComObject(fc); Marshal.ReleaseComObject(demuxaudioout); }
Create new Console Application, right click on References, add UdpSourceTSParser.dll and Multicast udp source filter.sxs.manifest.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Net; using System.Threading; using UdpSourceTSParser; using UdpSourceTSParser.DirectShowLib; //# Example of a channel scanner without error handling. namespace ScannerCsharpSample { class Program { static IPAddress start_address ; static IPAddress stop_address; static ushort port; static IBaseFilter UdpSource = null; // UDP source and demultiplexer filter . static IUdpMulticast IUdpConf = null; // Interface exposed by UDP source and demultiplexer filter, used to configure filter. static TSParser parser =null; // Helper class. static IFilterGraph2 FilterGraph; static ManualResetEvent exitEvent; // Event for graceful exit on Ctrl-c. static ManualResetEvent finishedEvent; static void Main(string[] args) { int hr; DateTime ip_scan_start; int timeout = 2000; // Wait maximum of 2 seconds for each multicast ip address. start_address = IPAddress.Parse("232.4.1.0"); stop_address = IPAddress.Parse("232.4.4.255"); port = 5002; FilterGraph = (IFilterGraph2)new FilterGraph(); IMediaEvent mediaEvent = (IMediaEvent)FilterGraph; IntPtr hEvent; // Handle to a manual-reset event that remains signaled while the queue contains event notifications. mediaEvent.GetEventHandle(out hEvent); ManualResetEvent mre = new ManualResetEvent(false); mre.SafeWaitHandle = new Microsoft.Win32.SafeHandles.SafeWaitHandle(hEvent, true); IntPtr p1, p2; EventCode ec; Console.CancelKeyPress += new ConsoleCancelEventHandler(exitHandler); Console.WriteLine("Press Ctrl-C to exit."); exitEvent = new ManualResetEvent(false); finishedEvent = new ManualResetEvent(false); IPAddress ip = start_address; while ( (ip = incrementIpAddress(ip, stop_address)) != IPAddress.None) { startScanner(ip, port); Console.Write(ip.ToString() + " : "); ip_scan_start = DateTime.Now; while (DateTime.Now.Subtract(ip_scan_start).TotalMilliseconds < timeout) { // Wait for events, but don't block indefently. mre.WaitOne(100, true); // Read events: for (hr = mediaEvent.GetEvent(out ec, out p1, out p2, 0); hr >= 0; hr = mediaEvent.GetEvent(out ec, out p1, out p2, 0)) { if ((int)ec == TSParser.EC_PARSER_STARTED) { // Scanner is activated and is waiting for multicast traffic. } else if ((int)ec == TSParser.EC_MSG_ParserRecvdFirstSample) { // Parser received first sample. Console.Write("Receiving... "); } else if ((int)ec == TSParser.EC_PARSER_COMPLETE) { // Parser has found all the BASIC data neccessary for creating directshow graph. // Load parsing results from the filter into the list (parser.ProgrameList) ! parser.GetInfo(); // Print some info and stop scanning. printSomeInfo(); ip_scan_start = DateTime.MinValue; //This will exit the loop after all events are read. // Don't break here if you want to be sure to get other data like service list or NIT table. } else if ((int)ec == TSParser.EC_MSG_SERVICE_LIST_RECEIVED) { // Parser received service list. List<ServiceDescriptorTriplet> sdesc= parser.GetServiceDescriptor(); if (sdesc.Count > 0) Console.Write("Name: " +sdesc[0].ServiceName+" "); } else { // Don't process other messages. // To see list of all messages, look at TSParser class ! } hr = mediaEvent.FreeEventParams(ec, p1, p2); } } stopScanner(); Console.WriteLine(); if (exitEvent.WaitOne(0)) break; } mre.Close(); Marshal.ReleaseComObject(mediaEvent); Marshal.ReleaseComObject(FilterGraph); finishedEvent.Set(); } static void startScanner(IPAddress ip, ushort port) { int hr; UdpSource = (IBaseFilter)new UdpSourceFilter(); IUdpConf = (IUdpMulticast)UdpSource; parser = new TSParser(IUdpConf); IUdpConf.SetMulticastIp(BitConverter.ToUInt32(ip.GetAddressBytes(), 0)); IUdpConf.SetPort(port); IUdpConf.SetNicIp(0); IUdpConf.SetMode(TSParser.PARSING_MODE); // Parsing mode must be set. FilterGraph.AddFilter(UdpSource, "Udp Source and TS Parser Filter (MulticastTV)"); hr = IUdpConf.ParseStream(false); // Check for ERR_RECV_IPAGN_AND_IPV4_BIND_FAILED error. } static void stopScanner() { parser.ProgrameList.Clear(); FilterGraph.RemoveFilter(UdpSource); Marshal.ReleaseComObject(IUdpConf); Marshal.ReleaseComObject(UdpSource); } static void printSomeInfo() { // Print some audio and video informations from the first program. if (parser.ProgrameList.Count == 0) return; if(parser.ProgrameList[0].Video.Count>0) Console.Write("Vid: PID="+parser.ProgrameList[0].Video[0].PID + " typ="+ parser.ProgrameList[0].Video[0].Type + " dim="+parser.ProgrameList[0].Video[0].Width+"x"+parser.ProgrameList[0].Video[0].Height+" "); if (parser.ProgrameList[0].Audio.Count > 0) Console.Write("Aud: PID=" + parser.ProgrameList[0].Audio[0].PID + " typ=" + parser.ProgrameList[0].Audio[0].Type + " chn=" + parser.ProgrameList[0].Audio[0].NumberOfChannels + " brt=" + parser.ProgrameList[0].Audio[0].Bitrate + " lng=" + parser.ProgrameList[0].Audio[0].Language +" "); } static IPAddress incrementIpAddress(IPAddress ip, IPAddress max_ip) { var bytes = ip.GetAddressBytes(); Array.Reverse(bytes); UInt32 ip_uint = BitConverter.ToUInt32(bytes, 0); ip_uint += 1; var bytesinc = BitConverter.GetBytes(ip_uint); Array.Reverse(bytesinc); IPAddress newip = new IPAddress(bytesinc); if (newip.Equals(max_ip)) return IPAddress.None; else return newip; } protected static void exitHandler(object sender, ConsoleCancelEventArgs args) { Console.WriteLine("Caught Ctrl-C..."); exitEvent.Set(); finishedEvent.WaitOne(2500); } } }