我想學習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# - 請記住這一點!
你看着SlimDX?它還應該提供對DirectShow(Windows多媒體?)的綁定並隱藏大部分COM-uglyness。 – GeirGrusom