2011-10-29 158 views
2

我想學習C#淨。因爲我已經知道面向對象的PHP一些Java和C++(我從來沒有真正使用過,因爲手動內存處理) 我在想我會從一些有用的東西開始,而不是另一本充滿人工問題的書。我正在考慮簡單的房屋監測。
我做一些谷歌搜索和抓取DirectShowNET。編譯它當然我在win7 64b。 編譯CaptureWMV示例,查看代碼並嘗試將音頻捕獲添加到它12小時,但是當我嘗試使用不是僅視頻編解碼器時,它總是暗戀。 我搜索了一個可以工作的例子,但找不到任何東西(僅限音頻 - 是的,只有視頻 - 是的,但兩者都無處) 這裏是我稍作修改的代碼。我肯定會做一些愚蠢的事情,但如果有人指出我正確的方向,我會很高興。如何使用DirectShow NET捕捉音頻和視頻?

採取仔細看註釋代碼附近

(...)AddSourceFilterForMoniker(devAudio.Mon(...)

這是錯誤的,我知道,但如何做到這一點嗎?

using System; 
using System.Runtime.InteropServices; 
using DirectShowLib; 

namespace AsfFilter 
{ 
    internal class Capture: IDisposable 
    { 
     #region Member variables 

     /// <summary> graph builder interface. </summary> 
     private IFilterGraph2 m_FilterGraph = null; 
     IMediaControl m_mediaCtrl = null; 
     /// <summary> Set by async routine when it captures an image </summary> 
     private bool m_bRunning = false; 
#if DEBUG 
     DsROTEntry m_rot = null; 
#endif 

     #endregion 

     /// <summary> release everything. </summary> 
     public void Dispose() 
     { 
      GC.SuppressFinalize(this); 
      CloseInterfaces(); 
     } 

     ~Capture() 
     { 
      Dispose(); 
     } 

     /// <summary> 
     /// Create capture object 
     /// </summary> 
     /// <param name="iDeviceNum">Zero based index of capture device</param> 
     /// <param name="szFileName">Output ASF file name</param> 
     public Capture(int iDeviceNum, int iAudioNum,string szOutputFileName) 
     { 
      DsDevice [] capDevices; 
      DsDevice [] audioCapDevices; 

      // Get the collection of video devices 
      capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice); 
      audioCapDevices = DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDevice); 
      if (iDeviceNum + 1 > capDevices.Length) 
      { 
       throw new Exception("No video capture devices found at that index!"); 
      } 
      if (iAudioNum + 1 > audioCapDevices.Length) 
      { 
       throw new Exception("No audio capture devices found at that index!"); 
      } 
      try 
      { 
       // Set up the capture graph 
       SetupGraph(capDevices[iDeviceNum], audioCapDevices[iDeviceNum], szOutputFileName); 
       m_bRunning = false; 
      } 
      catch 
      { 
       Dispose(); 
       throw; 
      } 
     } 

     // Start the capture graph 
     public void Start() 
     { 
      if (!m_bRunning) 
      { 
       int hr = m_mediaCtrl.Run(); 
       Marshal.ThrowExceptionForHR(hr); 
       m_bRunning = true; 
      } 
     } 

     // Pause the capture graph. 
     // Running the graph takes up a lot of resources. Pause it when it 
     // isn't needed. 
     public void Pause() 
     { 
      if (m_bRunning) 
      { 
       IMediaControl mediaCtrl = m_FilterGraph as IMediaControl; 
       int hr = mediaCtrl.Pause(); 
       Marshal.ThrowExceptionForHR(hr); 
       m_bRunning = false; 
      } 
     } 

     /// <summary> build the capture graph. </summary> 
     private void SetupGraph(DsDevice dev, DsDevice devAudio, string szOutputFileName) 
     { 
      int hr; 
      IBaseFilter capFilter = null; 
      IBaseFilter asfWriter = null; 
      IBaseFilter audFilter = null; 
      ICaptureGraphBuilder2 capGraph = null; 

      // Get the graphbuilder object 
      m_FilterGraph = (IFilterGraph2)new FilterGraph(); 
#if DEBUG 
      m_rot = new DsROTEntry(m_FilterGraph); 
#endif 
      try 
      { 
       // Get the ICaptureGraphBuilder2 
       capGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); 

       // Start building the graph 
       hr = capGraph.SetFiltergraph(m_FilterGraph); 
       Marshal.ThrowExceptionForHR(hr); 

       // Add the capture device to the graph 
       //hr = m_FilterGraph.AddSourceFilterForMoniker(devAudio.Mon, null, devAudio.Name, out capFilter); 
       //Marshal.ThrowExceptionForHR(hr); 
       hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); 
       Marshal.ThrowExceptionForHR(hr); 
       asfWriter = ConfigAsf(capGraph, szOutputFileName); 
       hr = capGraph.RenderStream(null, null, capFilter, null, asfWriter); 
       Marshal.ThrowExceptionForHR(hr); 
       m_mediaCtrl = m_FilterGraph as IMediaControl; 
      } 
      finally 
      { 
       if (capFilter != null) 
       { 
        Marshal.ReleaseComObject(capFilter); 
        capFilter = null; 
       } 
       if (asfWriter != null) 
       { 
        Marshal.ReleaseComObject(asfWriter); 
        asfWriter = null; 
       } 
       if (capGraph != null) 
       { 
        Marshal.ReleaseComObject(capGraph); 
        capGraph = null; 
       } 
      } 
     } 

     private IBaseFilter ConfigAsf(ICaptureGraphBuilder2 capGraph, string szOutputFileName) 
     { 
      IFileSinkFilter pTmpSink = null; 
      IBaseFilter asfWriter = null; 
      int hr = capGraph.SetOutputFileName(MediaSubType.Asf, szOutputFileName, out asfWriter, out pTmpSink); 
      Marshal.ThrowExceptionForHR(hr); 

      try 
      { 
       IConfigAsfWriter lConfig = asfWriter as IConfigAsfWriter; 

       // Windows Media Video 8 for Dial-up Modem (No audio, 56 Kbps) 
       // READ THE README for info about using guids 
       //WMProfile_V80_56VideoOnly 
       Guid cat = new Guid(0x6e2a6955, 0x81df, 0x4943, 0xba, 0x50, 0x68, 0xa9, 0x86, 0xa7, 0x8, 0xf6); 
       //WMProfile_V80_BESTVBRVideo 
       Guid bat = new Guid(0x48439ba, 0x309c, 0x440e, 0x9c, 0xb4, 0x3d, 0xcc, 0xa3, 0x75, 0x64, 0x23); 
       //WMProfile_V80_288VideoOnly 
       Guid vot = new Guid(0x8c45b4c7, 0x4aeb, 0x4f78, 0xa5, 0xec, 0x88, 0x42, 0xb, 0x9d, 0xad, 0xef); 
       //WMProfile_V80_56Video 
       Guid vau = new Guid(0x254E8A96, 0x2612, 0x405C, 0x80, 0x39, 0xf0, 0xBF, 0x72, 0x5C, 0xED, 0x7D); 
       //WMProfile_V80_288MonoAudio 
       Guid aon = new Guid(0x7ea3126d, 0xe1ba, 0x4716, 0x89, 0xaf, 0xf6, 0x5c, 0xee, 0xc, 0xc, 0x67); 

       hr = lConfig.ConfigureFilterUsingProfileGuid(cat); 
       //hr = lConfig.ConfigureFilterUsingProfileGuid(W288Video); 
       Marshal.ThrowExceptionForHR(hr); 
      } 
      finally 
      { 
       Marshal.ReleaseComObject(pTmpSink); 
      } 
      return asfWriter; 
     } 

     /// <summary> Shut down capture </summary> 
     private void CloseInterfaces() 
     { 
      int hr; 

      try 
      { 
       if(m_mediaCtrl != null) 
       { 
        // Stop the graph 
        hr = m_mediaCtrl.Stop(); 
        m_bRunning = false; 
       } 
      } 
      catch {} 
#if DEBUG 
      // Remove graph from the ROT 
      if (m_rot != null) 
      { 
       m_rot.Dispose(); 
       m_rot = null; 
      } 
#endif 
      if (m_FilterGraph != null) 
      { 
       Marshal.ReleaseComObject(m_FilterGraph); 
       m_FilterGraph = null; 
      } 
     } 
    } 
} 

我不想爲此使用C++代碼,因爲內存管理和DirectShowNet文檔非常簡約,而且我也無法真正理解「pin's」背後的想法 也許我必須完全放棄使用ICaptureGraphBuilder2並嘗試去做它很難。

這是我第一次遇到C# - 請記住這一點!

+1

你看着SlimDX?它還應該提供對DirectShow(Windows多媒體?)的綁定並隱藏大部分COM-uglyness。 – GeirGrusom

回答

-1

試試這個。您可以在sourceFilt和aufilter添加到graphbuilder,通過使用graphbuilder.addFilter(aufilter,"Name Here") graphbuilder.addFilter(sourceFilt,"Name Here"),並且忘記提及sourceFilt和aufilter是IBaseFilter

Dim classEnum As IEnumMoniker = Nothing 
Dim moniker As IMoniker() = New IMoniker(0) {} 
Dim devEnum As ICreateDevEnum = CType(New CreateDevEnum, ICreateDevEnum) 
hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, classEnum, 0) 
Marshal.ReleaseComObject(devEnum) 
If classEnum.Next(moniker.Length, moniker, IntPtr.Zero) = 0 Then 
    Dim iid As Guid = GetType(IBaseFilter).GUID 
    moniker(0).BindToObject(Nothing, Nothing, iid, source) 
End If 
sourceFilt = CType(source, IBaseFilter) 

Dim classEnum2 As IEnumMoniker = Nothing 
Dim moniker2 As IMoniker() = New IMoniker(0) {} 
Dim devEnum2 As ICreateDevEnum = CType(New CreateDevEnum, ICreateDevEnum) 
hr = devEnum2.CreateClassEnumerator(FilterCategory.AudioInputDevice, classEnum2, 0) 
Marshal.ReleaseComObject(devEnum2) 
If classEnum2.Next(moniker2.Length, moniker2, IntPtr.Zero) = 0 Then 
    Dim iid As Guid = GetType(IBaseFilter).GUID 
    moniker2(0).BindToObject(Nothing, Nothing, iid, sobject) 
End If 
aufilter = CType(sobject, IBaseFilter) 
+0

在回覆「這是我第一次遇到C#」時,你會拋出一些與VB.NET代碼無關的暗示嘗試一下嗎? –

+0

這就是你所提供的幫助! : - / – tommed