// This will reenable routing if previous cleared. // Should not be needed otherwise since FromSource changes will automatically update. public void UpdateRouting() { // never started before? if (_routingInstancePtr == IntPtr.Zero) { CreateRouting(); return; } // Sanity if (_selectedSource == null || String.IsNullOrEmpty(_selectedSource.Name)) { Clear(); return; } // a source_t to describe the source to connect to. NDIlib.source_t source_t = new NDIlib.source_t() { p_ndi_name = UTF.StringToUtf8(_selectedSource.Name) }; if (!NDIlib.routing_change(_routingInstancePtr, ref source_t)) { // free the memory we allocated with StringToUtf8 Marshal.FreeHGlobal(source_t.p_ndi_name); throw new InvalidOperationException("Failed to change routing."); } // free the memory we allocated with StringToUtf8 Marshal.FreeHGlobal(source_t.p_ndi_name); }
// This will start recording.If the recorder was already recording then the message is ignored.A filename is passed in as a ‘hint’.Since the recorder might // already be recording(or might not allow complete flexibility over its filename), the filename might or might not be used.If the filename is empty, or // not present, a name will be chosen automatically. public bool RecordingStart(String filenameHint = "") { if (!_canRecord || _recvInstancePtr == IntPtr.Zero) { return(false); } bool retVal = false; if (String.IsNullOrEmpty(filenameHint)) { retVal = NDIlib.recv_recording_start(_recvInstancePtr, IntPtr.Zero); } else { // convert to an unmanaged UTF8 IntPtr IntPtr fileNamePtr = UTF.StringToUtf8(filenameHint); retVal = NDIlib.recv_recording_start(_recvInstancePtr, IntPtr.Zero); // don't forget to free it Marshal.FreeHGlobal(fileNamePtr); } return(retVal); }
private void CreateRouting() { if (_routingInstancePtr != IntPtr.Zero) { NDIlib.routing_destroy(_routingInstancePtr); _routingInstancePtr = IntPtr.Zero; } // Sanity check if (_selectedSource == null || String.IsNullOrEmpty(_selectedSource.Name)) { return; } // .Net interop doesn't handle UTF-8 strings, so do it manually // These must be freed later IntPtr sourceNamePtr = UTF.StringToUtf8(_routingName); IntPtr groupsNamePtr = IntPtr.Zero; // make a flat list of groups if needed if (_groups != null) { StringBuilder flatGroups = new StringBuilder(); foreach (String group in _groups) { flatGroups.Append(group); if (group != _groups.Last()) { flatGroups.Append(','); } } groupsNamePtr = UTF.StringToUtf8(flatGroups.ToString()); } // Create an NDI routing description NDIlib.routing_create_t createDesc = new NDIlib.routing_create_t() { p_ndi_name = sourceNamePtr, p_groups = groupsNamePtr }; // create the NDI routing instance _routingInstancePtr = NDIlib.routing_create(ref createDesc); // free the strings we allocated Marshal.FreeHGlobal(sourceNamePtr); Marshal.FreeHGlobal(groupsNamePtr); // did it succeed? if (_routingInstancePtr == IntPtr.Zero) { throw new InvalidOperationException("Failed to create routing instance."); } // update in case we have enough info to start routing UpdateRouting(); }
public Finder(bool showLocalSources = false, String[] groups = null, String[] extraIps = null) { if (!NDIlib.initialize()) { if (!NDIlib.is_supported_CPU()) { throw new InvalidOperationException("CPU incompatible with NDI."); } else { throw new InvalidOperationException("Unable to initialize NDI."); } } //BindingOperations.EnableCollectionSynchronization(_sourceList, _sourceLock); IntPtr groupsNamePtr = IntPtr.Zero; // make a flat list of groups if needed if (groups != null) { StringBuilder flatGroups = new StringBuilder(); foreach (String group in groups) { flatGroups.Append(group); if (group != groups.Last()) { flatGroups.Append(','); } } groupsNamePtr = UTF.StringToUtf8(flatGroups.ToString()); } // This is also optional. // The list of additional IP addresses that exist that we should query for // sources on. For instance, if you want to find the sources on a remote machine // that is not on your local sub-net then you can put a comma seperated list of // those IP addresses here and those sources will be available locally even though // they are not mDNS discoverable. An example might be "12.0.0.8,13.0.12.8". // When none is specified (IntPtr.Zero) the registry is used. // Create a UTF-8 buffer from our string // Must use Marshal.FreeHGlobal() after use! // IntPtr extraIpsPtr = NDI.Common.StringToUtf8("12.0.0.8,13.0.12.8") IntPtr extraIpsPtr = IntPtr.Zero; // make a flat list of ip addresses as comma separated strings if (extraIps != null) { StringBuilder flatIps = new StringBuilder(); foreach (String ipStr in extraIps) { flatIps.Append(ipStr); if (ipStr != groups.Last()) { flatIps.Append(','); } } extraIpsPtr = UTF.StringToUtf8(flatIps.ToString()); } // how we want our find to operate NDIlib.find_create_t findDesc = new NDIlib.find_create_t() { p_groups = groupsNamePtr, show_local_sources = showLocalSources, p_extra_ips = extraIpsPtr }; // create our find instance _findInstancePtr = NDIlib.find_create_v2(ref findDesc); // free our UTF-8 buffer if we created one if (groupsNamePtr != IntPtr.Zero) { Marshal.FreeHGlobal(groupsNamePtr); } if (extraIpsPtr != IntPtr.Zero) { Marshal.FreeHGlobal(extraIpsPtr); } // start up a thread to update on _findThread = new Thread(FindThreadProc) { IsBackground = true, Name = "NdiFindThread" }; _findThread.Start(); }
public Sender(String sourceName, bool clockVideo = true, bool clockAudio = false, String[] groups = null, String failoverName = null) { if (String.IsNullOrEmpty(sourceName)) { throw new ArgumentException("sourceName can not be null or empty.", sourceName); } if (!NDIlib.initialize()) { if (!NDIlib.is_supported_CPU()) { throw new InvalidOperationException("CPU incompatible with NDI."); } else { throw new InvalidOperationException("Unable to initialize NDI."); } } // .Net interop doesn't handle UTF-8 strings, so do it manually // These must be freed later IntPtr sourceNamePtr = UTF.StringToUtf8(sourceName); IntPtr groupsNamePtr = IntPtr.Zero; // make a flat list of groups if needed if (groups != null) { StringBuilder flatGroups = new StringBuilder(); foreach (String group in groups) { flatGroups.Append(group); if (group != groups.Last()) { flatGroups.Append(','); } } groupsNamePtr = UTF.StringToUtf8(flatGroups.ToString()); } // Create an NDI source description NDIlib.send_create_t createDesc = new NDIlib.send_create_t() { p_ndi_name = sourceNamePtr, p_groups = groupsNamePtr, clock_video = clockVideo, clock_audio = clockAudio }; // create the NDI send instance _sendInstancePtr = NDIlib.send_create(ref createDesc); // free the strings we allocated Marshal.FreeHGlobal(sourceNamePtr); Marshal.FreeHGlobal(groupsNamePtr); // did it succeed? if (_sendInstancePtr == IntPtr.Zero) { throw new InvalidOperationException("Failed to create send instance."); } if (!String.IsNullOrEmpty(failoverName)) { // .Net interop doesn't handle UTF-8 strings, so do it manually // These must be freed later IntPtr failoverNamePtr = UTF.StringToUtf8(failoverName); NDIlib.source_t failoverDesc = new NDIlib.source_t() { p_ndi_name = failoverNamePtr, p_url_address = IntPtr.Zero }; NDIlib.send_set_failover(_sendInstancePtr, ref failoverDesc); // free the strings we allocated Marshal.FreeHGlobal(failoverNamePtr); } }
/// <summary> /// connect to an NDI source in our Dictionary by name /// </summary> /// <param name="source"></param> /// <param name="colorFormat"></param> /// <param name="bandwidth"></param> /// <param name="allowVideoFields"></param> public void Connect(Source source, NDIlib.recv_color_format_e colorFormat = NDIlib.recv_color_format_e.recv_color_format_BGRX_BGRA, NDIlib.recv_bandwidth_e bandwidth = NDIlib.recv_bandwidth_e.recv_bandwidth_highest, bool allowVideoFields = false) { //if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) // return; if (String.IsNullOrEmpty(ReceiverName)) { throw new ArgumentException("sourceName can not be null or empty.", ReceiverName); } // just in case we're already connected Disconnect(); // Sanity if (source == null || String.IsNullOrEmpty(source.Name)) { return; } // a source_t to describe the source to connect to. NDIlib.source_t source_t = new NDIlib.source_t() { p_ndi_name = UTF.StringToUtf8(source.Name) }; // make a description of the receiver we want NDIlib.recv_create_v3_t recvDescription = new NDIlib.recv_create_v3_t() { // the source we selected source_to_connect_to = source_t, // we want BGRA frames for this example color_format = colorFormat, // we want full quality - for small previews or limited bandwidth, choose lowest bandwidth = bandwidth, // let NDIlib deinterlace for us if needed allow_video_fields = allowVideoFields, // The name of the NDI receiver to create. This is a NULL terminated UTF8 string and should be // the name of receive channel that you have. This is in many ways symettric with the name of // senders, so this might be "Channel 1" on your system. p_ndi_recv_name = UTF.StringToUtf8(ReceiverName) }; // create a new instance connected to this source _recvInstancePtr = NDIlib.recv_create_v3(ref recvDescription); // free the memory we allocated with StringToUtf8 Marshal.FreeHGlobal(source_t.p_ndi_name); Marshal.FreeHGlobal(recvDescription.p_ndi_recv_name = UTF.StringToUtf8(ReceiverName)); // did it work? System.Diagnostics.Debug.Assert(_recvInstancePtr != IntPtr.Zero, "Failed to create NDI receive instance."); if (_recvInstancePtr != IntPtr.Zero) { // We are now going to mark this source as being on program output for tally purposes (but not on preview) SetTallyIndicators(true, false); // start up a thread to receive on _receiveThread = new Thread(ReceiveThreadProc) { IsBackground = true, Name = "NdiExampleReceiveThread" }; _receiveThread.Start(); } }