2

Directshow.Net を使用してウェブカメラでビデオを録画したい.i は ASFWriter を使用してビデオを録画できますが、録画と一緒に LAN 内の PC にビデオをストリーミングしたい..私はこれを試しました..

ビデオを記録するために開発したプロジェクトを実行します これがコードです

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DirectShowLib;
using DirectShowLib.DMO;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.IO;

namespace Cam_Recording_V1_directshow.net_
{
public partial class Form1 : Form
{
    string captureDeviceName = string.Empty;
    IFilterGraph2 Graph = null;
    IMediaControl m_mediaCtrl = null;
    public List<DsDevice> AvailableVideoInputDevices { get; private set; }
    IAMVideoProcAmp vpa;
    [DllImport("olepro32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    private static extern int OleCreatePropertyFrame(IntPtr hwndOwner, int x, int y,
        string lpszCaption, int cObjects,
        [In, MarshalAs(UnmanagedType.Interface)] ref object ppUnk,
        int cPages, IntPtr pPageClsID, int lcid, int dwReserved, IntPtr pvReserved);
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        IBaseFilter capFilter = null;
        IBaseFilter asfWriter = null;
        IFileSinkFilter pTmpSink = null;
        ICaptureGraphBuilder2 captureGraph = null;
        object o;

        //
        //Get list of video devices
        //
        AvailableVideoInputDevices = new List<DsDevice>();
        DsDevice[] videoInputDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
        AvailableVideoInputDevices.AddRange(videoInputDevices);
        if (AvailableVideoInputDevices.Count > 0)
        {
            //
            //init capture graph
            //
            Graph = (IFilterGraph2)new FilterGraph();
            captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();

            //
            //sets filter object from graph
            //
            captureGraph.SetFiltergraph(Graph);
            //
            //which device will use graph setting
            //
            Graph.AddSourceFilterForMoniker(AvailableVideoInputDevices.First().Mon, null, AvailableVideoInputDevices.First().Name, out capFilter);
            captureDeviceName = AvailableVideoInputDevices.First().Name;
            #region WMV
            //
            //sets output file name,and file type
            //
            captureGraph.SetOutputFileName(MediaSubType.Asf, /*DateTime.Now.Ticks.ToString()  +".wmv"*/ "test.wmv", out asfWriter, out pTmpSink);
            //
            //configure which video setting is used by graph
            //                
            IConfigAsfWriter lConfig = asfWriter as IConfigAsfWriter;
            Guid cat = new Guid("8C45B4C7-4AEB-4f78-A5EC-88420B9DADEF");
            lConfig.ConfigureFilterUsingProfileGuid(cat);
            #endregion                      
            captureGraph.RenderStream(PinCategory.Preview, MediaType.Video, capFilter, null, null);

            captureGraph.RenderStream(PinCategory.Capture, MediaType.Video, capFilter, null, asfWriter);
            m_mediaCtrl = Graph as IMediaControl;
            m_mediaCtrl.Run();
        }
        else
        {
            MessageBox.Show("Video Capture Device Not Found!!");
            button1.Visible = false;
        }
    }

これにより、ビデオの録画が開始されます。その後、「Release」フォルダーからこのプロジェクト exe を実行すると、「media run failed」のようなエラーが発生します。

さて、私の質問は、レコーディングとライブ ストリーミングを同時に行うことは可能ですか?

はいの場合は、これを案内してください..また、この投稿についても案内してください

4

1 に答える 1

1

手動でグラフを作成する必要があると思います。グラフは次の図のようになります。GraphEdt を使用してグラフをテストできます。これは、Guid と PinNames の取得にも役立ちます。

VideoSource -> SmartTee -> StreamingFilter
                        -> CaptureFilter

DirectShowLib は、グラフを作成するために必要なすべての関数を提供します。

例で行ったようにフィルターを作成できます。SmartTee フィルターは直接作成できます。

graph.Connect() メソッドを使用してフィルターを接続する必要があります。これを使用すると、SmartTee フィルターを使用して次のグラフを作成できます。SmartTee フィルターはシステムで使用可能で、キャプチャ用とプレビュー用の 2 つの出力ピンを提供する必要があります。ストリーミングには preveiw ピンを、キャプチャ フィルタにはキャプチャ ピンを使用する必要があります。

次の関数を使用して、connect メソッドに必要な Pin を取得できます。

    public IPin GetPin(IBaseFilter filter, string pinname)
    {
        IEnumPins epins;
        int hr = filter.EnumPins(out epins);
        if(hr < 0)
            return null;
        IntPtr fetched = Marshal.AllocCoTaskMem(4);
        IPin[] pins = new IPin[1];
        epins.Reset();
        while (epins.Next(1, pins, fetched) == 0)
        {
            PinInfo pinfo;
            pins[0].QueryPinInfo(out pinfo);
            bool found = (pinfo.name == pinname);
            DsUtils.FreePinInfo(pinfo);
            if (found)
                return pins[0];
        }
        return null;
    }

最後に、グラフを開始する必要があり、うまくいけばすべてがうまくいきます。エラー処理のためにメソッドを呼び出すたびに、hr コードを確認することが重要です。

于 2012-06-28T21:25:15.833 に答える