// 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); } }
// connect to an NDI source in our Dictionary by name public void Connect(Source source) { // just in case we're already connected // _delegateUpdateDynImage = UpdateDynImage; 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 = NDIlib.recv_color_format_e.recv_color_format_BGRX_BGRA, // we want full quality - for small previews or limited bandwidth, choose lowest bandwidth = NDIlib.recv_bandwidth_e.recv_bandwidth_highest, // let NDIlib deinterlace for us if needed allow_video_fields = false }; // 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); // 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); _source = source; // start up a thread to receive on _receiveThread = new Thread(ReceiveThreadProc) { IsBackground = true, Name = "NdiReceiveThread" }; _receiveThread.Start(); } }
// connect to an NDI source in our Dictionary by name void Connect(Source source) { if (FInReceiverName.SliceCount == 0 || String.IsNullOrEmpty(FInReceiverName[0])) { FLogger.Log(LogType.Error, "receiverName can not be null or empty."); } // 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 = NDIlib.recv_color_format_e.recv_color_format_BGRX_BGRA, color_format = (NDIlib.recv_color_format_e)Enum.ToObject(typeof(NDIlib.recv_color_format_e), (int)FInColorFormat[0]), // we want full quality - for small previews or limited bandwidth, choose lowest //bandwidth = NDIlib.recv_bandwidth_e.recv_bandwidth_highest, bandwidth = (NDIlib.recv_bandwidth_e)Enum.ToObject(typeof(NDIlib.recv_bandwidth_e), (int)FInBandwidth[0]), // let NDIlib deinterlace for us if needed allow_video_fields = false, // 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(FInReceiverName[0]) }; // 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); // did it work? //System.Diagnostics.Debug.Assert(_recvInstancePtr != IntPtr.Zero, "Failed to create NDI receive instance."); if (_recvInstancePtr == IntPtr.Zero) { FLogger.Log(LogType.Warning, "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 = "NDIReceiveThread" }; _receiveThread.Start(); } }
// connect to an NDI source in our Dictionary by name private void Connect(Source source) { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { return; } if (String.IsNullOrEmpty(ReceiverName)) { throw new ArgumentException("sourceName can not be null or empty.", ReceiverName); } using (var volOut = new WasapiOut(NAudio.CoreAudioApi.AudioClientShareMode.Shared, 50)) _volume = volOut.Volume; // just in case we're already connected Disconnect(); // before we are connected, we need to set up our image // it's bad practice to do this in the constructor if (Child == null) { Child = VideoSurface; } // 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 = NDIlib.recv_color_format_e.recv_color_format_BGRX_BGRA, // we want full quality - for small previews or limited bandwidth, choose lowest bandwidth = _lowBandwidth ? NDIlib.recv_bandwidth_e.recv_bandwidth_lowest : NDIlib.recv_bandwidth_e.recv_bandwidth_highest, // let NDIlib deinterlace for us if needed allow_video_fields = false, // 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); // 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(); } }
// connect to an NDI source in our Dictionary by name private void Connect(Source source) { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { return; } // just in case we're already connected Disconnect(); // before we are connected, we need to set up our image // it's bad practice to do this in the constructor if (Child == null) { Child = VideoSurface; } // Sanity if (source == null || (String.IsNullOrEmpty(source.Name) && String.IsNullOrEmpty(source.IpAddress))) { return; } // a source_t to describe the source to connect to. NDIlib.source_t source_t = new NDIlib.source_t() { p_ip_address = UTF.StringToUtf8(source.IpAddress), p_ndi_name = UTF.StringToUtf8(source.Name) }; // make a description of the receiver we want NDIlib.recv_create_t recvDescription = new NDIlib.recv_create_t() { // the source we selected source_to_connect_to = source_t, // we want BGRA frames for this example color_format = NDIlib.recv_color_format_e.recv_color_format_BGRX_BGRA, // we want full quality - for small previews or limited bandwidth, choose lowest bandwidth = NDIlib.recv_bandwidth_e.recv_bandwidth_highest, // let NDIlib deinterlace for us if needed allow_video_fields = false }; // create a new instance connected to this source _recvInstancePtr = NDIlib.recv_create_v2(ref recvDescription); // free the memory we allocated with StringToUtf8 Marshal.FreeHGlobal(source_t.p_ip_address); Marshal.FreeHGlobal(source_t.p_ndi_name); // 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(); } }
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 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); }