static ExampleVolume() { Caps audioCaps = Caps.FromString("audio/x-raw, format=(string) S16LE, rate=(int) [1, MAX], channels=(int) 2, layout=(string) interleaved"); __srcTemplate = new PadTemplate("src", PadDirection.Src, PadPresence.Always, audioCaps); __sinkTemplate = new PadTemplate("sink", PadDirection.Sink, PadPresence.Always, audioCaps); }
static void Init(GType gType, Type type) { var ptr = gType.GetClassPtr(); gst_element_class_set_metadata(ptr, LONGNAME, CLASSIFICATION, DESCRIPTION, AUTHOR); PadTemplate srcTmpl = new PadTemplate("src", PadDirection.Src, PadPresence.Always, Caps.NewAny()); PadTemplate sinkTmpl = new PadTemplate("sink", PadDirection.Sink, PadPresence.Always, Caps.NewAny()); gst_element_class_add_pad_template(ptr, srcTmpl.OwnedHandle); gst_element_class_add_pad_template(ptr, sinkTmpl.OwnedHandle); }
static void PadAddedCb(object o, PadAddedArgs args) { if (_linked) { return; } var src = (Element)o; var pad = args.NewPad; using (var caps = pad.CurrentCaps) { var s = caps.GetStructure(0); var name = s.Name; if (!name.StartsWith("video/x-raw")) { return; } using (var sinkPad = _conv.GetStaticPad("sink")) { if (pad.Link(sinkPad) != PadLinkReturn.Ok) { "Failed to link dbin with conb".PrintErr(); _loop.Quit(); return; } } PadTemplate templ = _tee.GetPadTemplate("src_%u"); Pad teePad = _tee.RequestPad(templ); var queue = ElementFactory.Make("queue"); var sink = ElementFactory.Make("fakesink"); sink["sync"] = true; _pipeline.Add(queue, sink); Element.Link(queue, sink); using (var sinkPad = queue.GetStaticPad("sink")) { teePad.Link(sinkPad); } GLib.Timeout.AddSeconds(3, TickCb); _linked = true; } }
static bool TickCb() { if (_sinks.Count == 0 || random.Next() % 2 == 0) { SinkStruct sink = new SinkStruct(); PadTemplate templ = _tee.GetPadTemplate("src_%u"); Console.Write("Add ... "); sink.teePad = _tee.RequestPad(templ); sink.queue = ElementFactory.Make("queue"); sink.conv = ElementFactory.Make("videoconvert"); sink.sink = ElementFactory.Make("autovideosink"); sink.removing = 0; _pipeline.Add(sink.queue, sink.conv, sink.sink); if (!Element.Link(sink.queue, sink.conv, sink.sink)) { "Cannot link elements".PrintErr(); return(false); } sink.queue.SyncStateWithParent(); sink.conv.SyncStateWithParent(); sink.sink.SyncStateWithParent(); using (var sinkPad = sink.queue.GetStaticPad("sink")) { sink.teePad.Link(sinkPad); } Console.WriteLine("added"); _sinks.AddLast(sink); } else { Console.Write("remove ... "); var sink = _sinks.Last.Value; _sinks.RemoveLast(); sink.teePad.AddProbe(PadProbeType.Idle, GetUnlinkCb(sink)); } return(true); }
// Test Server: // gst-launch-1.0 videotestsrc ! openh264enc ! h264parse ! rtph264pay ! udpsink host=127.0.0.1 port=5555 // Client stream with recording and showing: // gst-launch-1.0 -vvv -e udpsrc caps=\"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264\" port=5555 ! // rtph264depay ! h264parse ! tee name=videoTee videoTee. ! queue ! mp4mux ! filesink location=test.mp4 videoTee. ! queue ! avdec_h264 ! d3dvideosink /// <summary> /// A window that is separate from the main UI and plays a GStreamer RTP feed. /// </summary> /// <param name="Port"> The port that the RTP stream is sending data to. </param> /// <param name="BufferSizeMs"> The time in milliseconds of buffering of the feed. </param> public RTPVideoWindow(int Port, string StreamName, string RecordingPath, int BufferSizeMs = 200) { DataContext = this; this.Port = Port; this.StreamName = StreamName; this.BufferSizeMs = BufferSizeMs; this.RecordingPath = RecordingPath; Pipeline = new Pipeline(); Window window = GetWindow(this); WindowInteropHelper wih = new WindowInteropHelper(this); wih.EnsureHandle(); // Generate Window Handle if current HWND is NULL (always occurs because background window) VideoOverlayAdapter overlay = new VideoOverlayAdapter(VideoSink.Handle); overlay.WindowHandle = wih.Handle; // Allow forwarding of EOS to all elements in the pipeline for shutdown Pipeline["message-forward"] = true; UDP["port"] = Port; UDP["caps"] = Caps; JitterBuffer["latency"] = BufferSizeMs; FileSink["location"] = RecordingPath + GetRecordingFilename(); Filter["caps"] = FilterCaps; Pipeline.Add(UDP, JitterBuffer, Depay, Parse, Tee, Q1, Filter, Mux, FileSink, Q2, Dec, VideoSink); if (!Element.Link(UDP, JitterBuffer, Depay, Parse, Tee)) { Console.WriteLine("Failed To Link UDP, JitterBufferm, Depay, Parser, Tee"); } //if(!Parse.Link(Tee)) { Console.WriteLine("Failed To Link Parser to Tee"); } if (!Element.Link(Q1, Filter, Mux, FileSink)) { Console.WriteLine("Failed To Link Queue1, Mux, FileSink"); } if (!Element.Link(Q2, Dec, VideoSink)) { Console.WriteLine("Failed To Link Queue2, Decoder, VideoSink"); } PadTemplate TeeSrcPadTemplate = Tee.GetPadTemplate("src_%u"); Pad TeeQ1Pad = Tee.RequestPad(TeeSrcPadTemplate); Pad Q1Pad = Q1.GetStaticPad("sink"); Pad TeeQ2Pad = Tee.RequestPad(TeeSrcPadTemplate); Pad Q2Pad = Q2.GetStaticPad("sink"); if (TeeQ1Pad.Link(Q1Pad) != PadLinkReturn.Ok) { Console.WriteLine("Failed To Link Tee to Queue1"); } if (TeeQ2Pad.Link(Q2Pad) != PadLinkReturn.Ok) { Console.WriteLine("Failed To Link Tee to Queue2"); } Q1Pad.Unref(); Q2Pad.Unref(); Pipeline.SetState(State.Null); Closing += OnCloseEvent; InitializeComponent(); }