Ich möchte in einer SDP-Datei lesen und den Video-Stream in H.264 und den Audio-Stream in AAC zu kodieren. Dann möchte ich diese Streams in einen AVI-Stream und dann in eine Datei multiplexen. Ich kenne den Inhalt der SDP-Datei nicht im Voraus, daher scheint es am einfachsten zu sein, playbin2 zu verwenden.Gstreamer: Verknüpfen Sie ein Bin mit zwei Senken zu playbin2
Also, ich dachte, dass ich etwas tun könnte:
RawToAviMux Bin
______________________________________
----- |ghostpad----x264enc
/ | \
playbin2------ | avimux--filesink
\ | /
-------| ghostpad----ffenc_aac
|_______________________________________
setting playbin2's videosink to an instance of RawToAviMux
and playbin2's audiosink to the same instance of RawToAviMux
Allerdings kann ich nicht die Pipeline in das Spiel Zustand erhalten. Hier
ist der Code:
recorder = new Gst.BasePlugins.PlayBin2();
recorder.PlayFlags &= ~((Gst.BasePlugins.PlayBin2.PlayFlagsType)(1 << 2));
recorder.Bus.AddSignalWatch();
recorder.Bus.EnableSyncMessageEmission();
RawToAviMuxer aviMuxer = new RawToAviMuxer(fileName);
recorder.VideoSink = aviMuxer;
recorder.AudioSink = aviMuxer;
recorder.SetState(Gst.State.Ready);
recorder.Uri = @"file:///" + filePath.Replace('\\', '/');
recorder.SetState(Gst.State.Paused);
recorder.SetState(Gst.State.Playing);
Gst.State currentState;
Gst.State playingState = Gst.State.Playing;
Gst.StateChangeReturn stateReturn = recorder.GetState(out currentState, out playingState, Gst.Clock.Second);
if (stateReturn != Gst.StateChangeReturn.Failure)
return true;
return false;
Mit RawToAviMuxer als
public class RawToAviMuxer : Gst.Bin
{
bool test = false;
public RawToAviMuxer(string outputFileName)
: base("rawToAviMux")
{
Gst.Element x264Enc = Gst.ElementFactory.Make("x264enc");
Gst.Element ffenc_aac = Gst.ElementFactory.Make("ffenc_aac");
x264Enc["bframes"] = (uint)0;
x264Enc["b-adapt"] = false;
x264Enc["bitrate"] = (uint)1024;
x264Enc["tune"] = 0x4;
x264Enc["speed-preset"] = 3;
x264Enc["sliced-threads"] = false;
x264Enc["profile"] = 0;
x264Enc["key-int-max"] = (uint)30;
Gst.GhostPad videoToX264Pad = new Gst.GhostPad("video_sink", x264Enc.GetStaticPad("sink"));
Gst.GhostPad audioToAACPad = new Gst.GhostPad("audio_sink", ffenc_aac.GetStaticPad("sink"));
test = this.AddPad(videoToX264Pad);
test = this.AddPad(audioToAACPad);
Gst.Element aviMux = Gst.ElementFactory.Make("avimux");
Gst.Element fileSink = Gst.ElementFactory.Make("filesink");
test = this.Add(new Gst.Element[]{x264Enc, ffenc_aac, aviMux, fileSink});
test = x264Enc.Link(aviMux);
test = ffenc_aac.Link(aviMux);
test = aviMux.Link(fileSink);
fileSink["location"] = outputFileName;
}
}
Ich habe in den Debugger und alle Links sind trat durch erfolgreich.
Update
Ok, also habe ich versucht, die folgende Pipeline mit Gst.Parse.Launch:
uridecodebin uri=file:///C:/Users/Jonathan/AppData/Local/Temp/192.168.0.215_5000.sdp !
x264enc byte-stream=true bframes=0 b-adapt=0 tune=0x4 speed-preset=3 sliced-threads=false
profile=0 ! mux. ffenc_aac ! mux. avimux name=mux ! filesink location=C:\Users\Jonathan\Desktop\test.avi
Ich kann es immer noch nicht pausiert raus aus.
Ich benutze die Windows-Build, also mache ich mir Sorgen, vielleicht ist da etwas nicht in Ordnung?
Ich kann auch keinen Message-Handler an den Bus anschließen, so dass ich herausfinden kann, was los ist, was wirklich nervig wird.
Ich habe gerade dies jedoch zu finden,
Wenn ich direkt die Ströme über ein udpsrc Element greifen, zu wissen, was die Formate der Zeit voraus sind, ist es nicht nur mit einem rtph264depay Element funktioniert. In der Pipeline muss ein harliches Element vorhanden sein. Dies könnte der Grund sein, dass Uridecodebin für mich nicht funktioniert?
gelöst landete ich Sie folgendermaßen vorgehen:
if (!gst_is_init)
{
Gst.Application.Init();
gst_is_init = true;
}
if(recorder != null)
{
recorder.SetState(Gst.State.Null);
recorder.Dispose();
}
string videoDepay, audioDepay, strExtension, strMuxer;
GetGstElements(stream.VideoCaps, out videoDepay, out strMuxer, out strExtension);
GetGstElements(stream.AudioCaps, out audioDepay, out strMuxer, out strExtension);
fileName = Path.ChangeExtension(fileName, strExtension);
//recorder = new Gst.Pipeline("recordingPipe");
string pipeString = String.Format("udpsrc port={0} ! {1} {2} ! {3} ! queue ! mux. udpsrc port={4} ! {1} {5} ! {6} ! mux. {7} name=mux ! filesink location={8}",
portToUse, "application/x-rtp,", stream.VideoCaps, videoDepay, (portToUse + 2), stream.AudioCaps, audioDepay, strMuxer, fileName.Replace("\\", "\\\\"));
recorder = (Gst.Pipeline)Gst.Parse.Launch(pipeString);
recordingFileName = fileName;
recorder.SetState(Gst.State.Ready);
recorder.SetState(Gst.State.Paused);
recorder.SetState(Gst.State.Playing);
Gst.State currentState;
Gst.StateChangeReturn stateReturn = recorder.GetState(out currentState, Gst.Clock.Second);
if (stateReturn != Gst.StateChangeReturn.Failure)
return true;
return false;
Sie haben einen Parser für alle Ströme haben, für die Pipeline zu spielen zu gehen. Also, im Falle eines eingehenden h264-Streams, müsste ich rtph264depay verwenden! h264parse. Außerdem müssen NALU und Byte-Stream übereinstimmen, damit das Timing richtig ist.
Damit die Datei verwendet werden kann, müssen Sie vor dem Entsorgen der Pipeline einen EOS Downstream senden.
recorder.SendEvent(Gst.Event.NewEos());
System.Threading.Thread.Sleep(100);
recorder.SetState(Gst.State.Paused);
recorder.SetState(Gst.State.Ready);
recorder.SetState(Gst.State.Null);
recorder.Dispose();
Ok, ich sehe den Uridecodebin Weg, es jetzt zu tun, danke! Allerdings kann ich den Encoder in gst-inspect nicht finden. –
Es ist etwas neu. Ein paar Abweichungen können Sie neuere Gtreamer-Versionen (z. B. die Gstreamer-Entwickler-PPA auf Ubuntu) bekommen. – ensonic
Nun, diese spezielle Komponente verwendet die Windows-Builds. Ich glaube nicht, dass sie es schon haben. Jedenfalls muss ich es bis dahin umcodieren. Vielen Dank! –