1

私は Directshow.NET を使用するアプリケーションに取り組んでおり、GraphEd.exeをいじって、必要な正確なルートを把握することにしました。

GraphEd グラフ

私が欲しいものの最も単純なバージョンは、上の画像にあります(「test.mpeg」は「ファイルライター」フィルターです)。

確かに、GraphEd で簡単に見えることは、コーディングほど簡単ではありません。数秒後、私は directshow が理解できないものであることに気付きました。これが私のC#コードの試みです:

int hr;

IBaseFilter cameraStream = null;
IBaseFilter mpegEncoder = null;
IBaseFilter fileWriter = null;
ICaptureGraphBuilder2 capGraph = null;

filterGraph = (IFilterGraph2)new FilterGraph();
try
{
    capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
    hr = capGraph.SetFiltergraph(filterGraph);
    Marshal.ThrowExceptionForHR(hr);

    hr = filterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out cameraStream);
    Marshal.ThrowExceptionForHR(hr);

    IPin cameraData = null;
    hr = capGraph.FindPin(cameraStream, PinDirection.Output, PinCategory.Capture, MediaType.Video, true, 0, out cameraData );
    //hr = cameraStream.FindPin("Capture", out cameraData);
    Marshal.ThrowExceptionForHR(hr);

    mpegEncoder = (IBaseFilter)new MJPGEnc();
    hr = filterGraph.AddFilter(mpegEncoder, "mpeg encoder");
    //hr = filterGraph.FindFilterByName("Microsoft MPEG-2 Video Encoder", out mpegEncoder);
    Marshal.ThrowExceptionForHR(hr);

    IPin mpegInput = null;
    //hr = mpegEncoder.FindPin("Input0", out mpegInput);
    hr = capGraph.FindPin(mpegEncoder, PinDirection.Input, null, null, true, 0, out mpegInput);
    Marshal.ThrowExceptionForHR(hr);

    filterGraph.Connect(cameraData, mpegInput);

    IPin mpegOutput = null;
    //hr = mpegEncoder.FindPin("Output", out mpegOutput);
    hr = capGraph.FindPin(mpegEncoder, PinDirection.Output, null, null, true, 0, out mpegOutput);
    Marshal.ThrowExceptionForHR(hr);

    //hr = filterGraph.FindFilterByName("File writer", out fileWriter);
    fileWriter = (IBaseFilter)new FileWriter();
    IFileSinkFilter test = fileWriter as IFileSinkFilter2;
    AMMediaType mtype = new AMMediaType();
    mtype.majorType = MediaType.Video;
    mtype.subType = MediaSubType.RGB24;
    mtype.formatPtr = IntPtr.Zero;
    test.SetFileName(videoPath, mtype );

    IPin fwriterIn = null;
    //hr = fileWriter.FindPin("in", out fwriterIn);
    hr = capGraph.FindPin(fileWriter, PinDirection.Input, null, null, true, 0, out fwriterIn);
    Marshal.ThrowExceptionForHR(hr);

    filterGraph.Connect(mpegOutput, fwriterIn);

    hr = capGraph.RenderStream(null, null, cameraStream, null, fileWriter); // *** Breaks on this line! ***
    Marshal.ThrowExceptionForHR(hr);

    mediaControl = filterGraph as IMediaControl;

}
finally
{
    if (cameraStream != null)
    {
        Marshal.ReleaseComObject(cameraStream);
        cameraStream = null;
    }
    if (mpegEncoder != null)
    {
        Marshal.ReleaseComObject(mpegEncoder);
        mpegEncoder = null;
    }
    if (fileWriter != null)
    {
        Marshal.ReleaseComObject(fileWriter);
        fileWriter = null;
    }
    if (capGraph != null)
    {
        Marshal.ReleaseComObject(capGraph);
        capGraph = null;
    }
}

(プログラミング ロジックに関する限り) 自分のコードがいかにばかげているかを書いて見た後、助けが必要だと気づきました。

どなたか、私が巨大な初心者であるかのように説明してくれる構造化された directshow チュートリアルに誘導してもらえますか、またはウェブカメラからファイルへの記録を処理する何らかの C# ライブラリにリンクしてもらえますか? 私は一般的にwin32プログラマーではないので、痛みを和らげるものは何でも良いはずです:)

また、機能しているように見えるカメラ デバイスの列挙コードがあります。

private void rescan_camera()
{
    comboBox1.Items.Clear();

    DsDevice[] cameraDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

    for(int i=0; i < cameraDevices.Length; i++) {
        comboBox1.Items.Add(cameraDevices[i].Name);
    }
    if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0;
}

DsDevice からモニカー データを取得できます。これは、記録する場所を directshow フィルター グラフに伝える重要な部分であることはわかっていますが、それは私の知識の範囲です。

編集:コードを更新し、改行の正確な場所を示します。

4

1 に答える 1

0

コメントを繰り返すには: だから、ファイル出力を変更することになりました: setFileName のメディア タイプを設定するのではなく、null に変更しました。今ではすべて問題ありません:)

于 2012-10-22T17:36:17.123 に答える