// prepare to send texture void CreateSendInstance() { if (!initialized) { return; } Monitor.Enter(sendInstanceLock); { // reset flag instanceCreated = false; // .Net interop doesn't handle UTF-8 strings, so do it manually // These must be freed later IntPtr sourceNamePtr = UTF.StringToUtf8(FInSourceName[0]); IntPtr groupsNamePtr = IntPtr.Zero; // Create an NDI source description using sourceNamePtr and it's clocked to the video. NDIlib.send_create_t createDesc = new NDIlib.send_create_t() { p_ndi_name = sourceNamePtr, p_groups = groupsNamePtr, clock_video = true, clock_audio = false }; // destroy if exists if (sendInstancePtr != IntPtr.Zero) { NDIlib.send_destroy(sendInstancePtr); sendInstancePtr = IntPtr.Zero; } // We create the NDI sender 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) { FLogger.Log(LogType.Error, "Failed to create send instance"); return; } else { FLogger.Log(LogType.Message, "Successed to create send instance"); instanceCreated = true; } // unlock Monitor.Exit(sendInstanceLock); } }
void Start() { var name = Marshal.StringToHGlobalAnsi("Test Server"); var sendOptions = new NDIlib.send_create_t { p_ndi_name = name }; _sendInstance = NDIlib.send_create(ref sendOptions); Marshal.FreeHGlobal(name); }
private void InitializeNdi() { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { return; } Monitor.Enter(sendInstanceLock); { // we need a name if (String.IsNullOrEmpty(NdiName)) { return; } // re-initialize? if (sendInstancePtr != IntPtr.Zero) { NDIlib.send_destroy(sendInstancePtr); sendInstancePtr = IntPtr.Zero; } // .Net interop doesn't handle UTF-8 strings, so do it manually // These must be freed later IntPtr sourceNamePtr = UTF.StringToUtf8(NdiName); IntPtr groupsNamePtr = IntPtr.Zero; // build a comma separated list of groups? if (NdiGroups.Count > 0) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < NdiGroups.Count(); i++) { sb.Append(NdiGroups[i]); if (i < NdiGroups.Count - 1) { sb.Append(','); } } groupsNamePtr = UTF.StringToUtf8(sb.ToString()); } // Create an NDI source description using sourceNamePtr and it's clocked to the video. NDIlib.send_create_t createDesc = new NDIlib.send_create_t() { p_ndi_name = sourceNamePtr, p_groups = groupsNamePtr, clock_video = NdiClockToVideo, clock_audio = false }; // We create the NDI finder instance sendInstancePtr = NDIlib.send_create(ref createDesc); // free the strings we allocated Marshal.FreeHGlobal(sourceNamePtr); Marshal.FreeHGlobal(groupsNamePtr); // unlock Monitor.Exit(sendInstanceLock); } }
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); } }
public void OnImportsSatisfied() { frameNumber = 0; // .Net interop doesn't handle UTF-8 strings, so do it manually // These must be freed later sourceNamePtr = UTF.StringToUtf8("VVVV.NDI.SendTest"); groupsNamePtr = IntPtr.Zero; // Not required, but "correct". (see the SDK documentation) if (!NDIlib.initialize()) { // Cannot run NDI. Most likely because the CPU is not sufficient (see SDK documentation). // you can check this directly with a call to NDIlib_is_supported_CPU() FLogger.Log(LogType.Error, "Cannot run NDI"); return; } else { FLogger.Log(LogType.Message, "NDI initialized"); } // Create an NDI source description using sourceNamePtr and it's clocked to the video. NDIlib.send_create_t createDesc = new NDIlib.send_create_t() { p_ndi_name = sourceNamePtr, p_groups = groupsNamePtr, clock_video = true, clock_audio = false }; // We create the NDI finder 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) { FLogger.Log(LogType.Error, "Failed to create send instance"); //Console.WriteLine("Failed to create send instance"); return; } else { FLogger.Log(LogType.Message, "Successed to create send instance"); } // define our bitmap properties int xres = 1920; int yres = 1080; int stride = (xres * 32 /*BGRA bpp*/ + 7) / 8; int bufferSize = yres * stride; // allocate some memory for a video buffer bufferPtr = Marshal.AllocHGlobal((int)bufferSize); // We are going to create a 1920x1080 progressive frame at 29.97Hz. videoFrame = new NDIlib.video_frame_v2_t() { // Resolution xres = xres, yres = yres, // Use BGRA video FourCC = NDIlib.FourCC_type_e.FourCC_type_BGRA, // The frame-eate frame_rate_N = 120000, //30000, frame_rate_D = 1000, //1001, // The aspect ratio (16:9) picture_aspect_ratio = (16.0f / 9.0f), // This is a progressive frame frame_format_type = NDIlib.frame_format_type_e.frame_format_type_progressive, // Timecode. timecode = NDIlib.send_timecode_synthesize, // The video memory used for this frame p_data = bufferPtr, // The line to line stride of this image line_stride_in_bytes = stride, // no metadata p_metadata = IntPtr.Zero, // only valid on received frames timestamp = 0//NDIlib.recv_timestamp_undefined }; // get a compatible bitmap and graphics context bmp = new Bitmap((int)xres, (int)yres, (int)stride, System.Drawing.Imaging.PixelFormat.Format32bppPArgb, bufferPtr); graphics = Graphics.FromImage(bmp); graphics.SmoothingMode = SmoothingMode.AntiAlias; // We'll use these later inside the loop textFormat = new StringFormat(); textFormat.Alignment = StringAlignment.Center; textFormat.LineAlignment = StringAlignment.Center; fontFamily = new FontFamily("Arial"); outlinePen = new Pen(Color.Black, 2.0f); thinOutlinePen = new Pen(Color.Black, 1.0f); }