1

SDPファイルを読み込んで、ビデオストリームをh.264にエンコードし、オーディオストリームをaacにエンコードしたいと思います。次に、それらのストリームをaviストリームに多重化し、次にファイルに多重化します。事前にSDPファイルの内容がわからないので、playbin2を使うのが一番簡単なようです。

だから、私はこのようなことをすることができると思いました:

                             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

ただし、パイプラインを再生状態にすることはできません。

コードは次のとおりです。

            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;

RawToAviMuxerを

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;
    }
}

デバッガーをステップスルーしましたが、すべてのリンクが成功しています。

アップデート

さて、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

私はまだそれを一時停止から抜け出すことができません。

私はWindowsビルドを使用しているので、何か問題があるのではないかと心配しています。

また、メッセージハンドラーをバスに接続して、何が起こっているのかを把握することもできません。これは本当に迷惑になり始めています。

しかし、私はこれを見つけました

udpsrc要素を介してストリームを直接取得し、事前にフォーマットが何であるかを知っている場合、rtph264depay要素だけでは機能しません。パイプラインにはh264parse要素が必要です。これが、uridecodebinが機能しない理由かもしれません。

解決 した私は次のことをすることになった:

            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;

パイプラインを再生するには、すべてのストリームにパーサーが必要です。したがって、着信h264ストリームの場合は、rtph264depayを使用する必要があります。h264parse。さらに、タイミングを正しくするには、NALUとバイトストリームが一致している必要があります。

また、ファイルを使用できるようにするには、パイプラインを破棄する前にEOSをダウンストリームに送信する必要があります。

                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();              
4

1 に答える 1

1

はい、これは機能しません。これがあなたがそれをする方法です。Playbin2はモジュラーコンポーネントであり、uridecodebinとplaysinkbinで構成されています。uridecodebinを使用し、メディアファイルuriを設定し、pad-addedのシグナルハンドラーを追加し、新しく作成されたパッドをrawtoavimuxコンポーネントのシンクパッドに接続するだけです。

rawtoavimuxの代替案の1つは、encodebinを使用することです。uridecodebinを使用する!encodebinは、1つ以上のストリームの形式がすでに正しい形式である場合に、デコードと再エンコードを回避するスマートトランスコーディングを行う可能性があります。

于 2012-04-09T08:17:41.390 に答える