/// <summary> /// Used to connect a C# delegate to AppSrc's need-data action signal /// </summary> /// <param name="appsrc">AppSrc instance whose need-data signal needs to be changed</param> /// <param name="callback">need-data C# callback, might be called in a separate thread!</param> /// <returns></returns> public static bool AppSrcConnect(AppSrc appsrc, GStreamer.NeedDataDelegate callback) { if (appsrc == AppSrc.Zero) { return(false); } return(GsignalNativeMethods.g_signal_connect_data(appsrc, "need-data", callback, GPointer.Zero, GPointer.Zero, ConnectFlags.G_CONNECT_NONE) > 0); }
internal static extern ulong g_signal_connect_data(GPointer instance, string detailed_signal, GStreamer.NeedDataDelegate c_handler, GPointer data, GPointer destroy_data, GSignal.ConnectFlags connect_flags);
/// <summary> /// Attempts to construct a GStreamer pipeline that streams an ARGB C# byte array /// encoded with JPEG and multiplexed into HTTP multi part frames. /// THROWS if it cannot construct the pipeline. /// Receiver can be (in case of UDP transport): /// gst-launch-1.0 udpsrc address=<host> port=<port> ! decodebin ! autovideosink /// </summary> /// <param name="width">width of the input image buffer</param> /// <param name="height">height of the input image buffer</param> /// <param name="netopts">network options to launch the ByteStreamer instance with</param> public ByteStreamer(int width, int height, NetworkOptions netopts = null) { Disposed = false; if (!GStreamer.IsInitialized && !GStreamer.Initialize()) { throw new ExternalException("Unable to initialize GStreamer."); } if (netopts == null) { netopts = new NetworkOptions(); } string appsrc_name = "AppSrc"; string appsrc_sink = string.Empty; string appsrc_opts = "is-live=true do-timestamp=true"; string appsrc_caps = string.Format("video/x-raw,format=ARGB,framerate=0/1,width={0},height={1}", width, height); if (netopts.StreamType == TransportType.Udp) { appsrc_sink = string.Format("udpsink host={0} port={1}", netopts.Address, netopts.Port); } else if (netopts.StreamType == TransportType.Tcp) { appsrc_sink = string.Format("tcpserversink host={0} port={1}", netopts.Address, netopts.Port); } else if (netopts.StreamType == TransportType.All) { appsrc_sink = string.Format("tee name=t ! queue ! tcpserversink host={0} port={1} t. ! queue ! udpsink host={0} port={1}", netopts.Address, netopts.Port); } string[] pipeline_elements = new string[] { string.Format("appsrc name=\"{0}\" caps=\"{1}\" {2}", appsrc_name, appsrc_caps, appsrc_opts), "videoconvert", "video/x-raw,format=I420", "jpegenc quality=75", appsrc_sink }; string pipeline_description = string.Join(" ! ", pipeline_elements); m_Pipeline = GStreamer.ParseLaunch(pipeline_description); if (m_Pipeline == IntPtr.Zero) { throw new ExternalException("Unable to launch the pipeline."); } m_AppSrc = GStreamer.BinGetByName(m_Pipeline, appsrc_name); if (m_AppSrc == IntPtr.Zero) { throw new ExternalException("Unable to obtain pipeline's AppSrc."); } var need_data_cb = new GStreamer.NeedDataDelegate((appsrc, size, data) => { NeedData = true; }); m_NeedDataCallbackHandle = GCHandle.Alloc(need_data_cb, GCHandleType.Pinned); if (!GSignal.AppSrcConnect(m_AppSrc, need_data_cb)) { throw new ExternalException("Failed to connect the need-data action signal."); } if (GStreamer.ElementSetState(m_Pipeline, GStreamer.State.GST_STATE_PLAYING) == GStreamer.StateChangeReturn.GST_STATE_CHANGE_FAILURE) { throw new ExternalException("Pipeline state change failed."); } }