在VS6.0年代,微軟提供了VFW(Video For Window) 這樣強大而方便的庫來可使用視訊捕獲和回放。但是無論是在。NET v1.0還是在.NET v2.0架構中,都沒有提供相應的類庫來可使用視訊捕獲和回放。解決這個問題有很多種方法,比如利用平台叫用P/Invoke對VFW中的功能函數進行封 裝,然後再C#中進行調用。這樣效率很低並且太複雜。還可以利用第三方提供的ActiveX控制項來實現這個功能,這有什麼好處呢?簡單!!!!這也就足夠 了。並且往往第三方提供的控制項功能更強大。但是世界上沒有免費的午餐——這種控制項往往是要收費的。在這裡肯定有的朋友會想到:“不是還可以利用 DX(DirectX)來實現嗎,微軟也提供了Manager DXManaged 程式碼的SDK”。的確,利用DX來實現視頻捕獲和回放是一個很好的方法,無論從效率還是效果來說都是上上之選。不幸的是:微軟雖然提供了D3D、 DirectDraw、DirectSound、DirectPlayer......但是唯獨沒有我們感興趣的,可以實現視頻捕獲的 DirectShow的SDK。據我所知,國外有開源的代碼對DirectShow進行了封裝,我也用過,個人感覺還不錯,有興趣的朋友可以尋找一下這方 面的資料,這裡我就不多說了。
言歸正傳,要利用ActiveX在C#中實現視頻捕獲,先要做好以下準備工作:
首先是要有VS2003或者VS2005的開發環境,這個我就不多說,相信地球人都知道。
其次是要安裝好網路攝影機的驅動程式,也就是說你在QQ或者MSN視訊交談時能看到你自己網路攝影機的映像。
然 後是最重要的了:安裝可使用視訊捕獲的ActiveX控制項!什麼控制項?Pegasus CapturePro。哪裡下載?:http://www.cncode.com/downinfo/3504.html 這個地址應該是可以下載的,我剛剛又測試了一次。但是我不能保證它一直有效。這個控制項是收費的,網上有它的評估版,相信大家也有辦法,實在不行,那麼給我 發Email吧,我來告訴你怎麼辦。安裝時一直"Next"下去後就可以了。
在VS2003中建立一個“
Windows 應用程式”工程,工程建立後,首先要向“工具箱”中添加ActiveX控制項具體方法是在VS2003菜單的“工具”菜單中單擊“添加/移除工具箱項”。在 彈出的對話方塊中選擇“COM 組件”選項卡,在下面的列表框中,將“Pegasus Imaging CapturePRO Control v3.0”前面的複選框選中,然後單擊“確定”返回編譯器編輯介面就可以了。然後將剛剛添加的控制項拖放到表單上調整好大小和位置,在屬性頁面中修改屬性。修 改屬性的方法和普通控制項一樣,至於各個屬性的含義可以參考控制項的協助文檔。控制項所有的方法、屬性和事件在協助文檔中都有詳細的說明。這裡建議修改其 “Name”屬性,方便以後操作,比如將Name屬性改為axCap(以後axCap都表示該控制項)。將axCap的Size屬性改為320,240。因 為很多網路攝影機的預設解析度是320X240。表單布局大概如:
然後再表單上放一個Button控制項,在該控制項的單擊事件中添加以下代碼:
view plaincopy to clipboardprint?
private void butConnect_Click(object sender, System.EventArgs e)
...{
axCap.Connect (0); // 串連到裝置
axCap.Preview = true; // 開始預覽
}
private void butConnect_Click(object sender, System.EventArgs e)
...{
axCap.Connect (0); // 串連到裝置
axCap.Preview = true; // 開始預覽
}
然後編譯工程,允許程式,單擊按鈕應該就可以看到視頻映像了。
到這裡就表示我們的操作成功了,最基本的功能實現了,這裡對上述兩行代碼進行簡單的解釋。第一行axCap.Connect(0)表示將控制項串連到裝置 0。在Windows中,可以同時支援多個視頻裝置,每個裝置都有一個編號。第一個裝置編號0,第二個裝置編號1,依次類推。由於我的電腦上只串連了一個 視頻網路攝影機,所以視頻裝置的編號是0。這裡也就可以看出Connect()函數的參數實際上就是視頻裝置的參數,至於怎樣來確定視頻裝置對於得編號,下面 會有詳細的說明。第二行axCap.Preview = true;表示開啟預覽。Preview屬性為真時表示在控制項上顯示視頻映像,當然要是該屬性為false,我們就看不到視頻了。
下面對一些常用的,比較重要的方法和屬性進行說明:
怎樣確定視頻裝置的編號:首先利用屬性axCap .NumDevices來擷取Windows中可用視頻裝置的數目,然後利用方法axCap .ObtainDeviceName (i)來擷取該裝置的名稱字串。其中參數i同Connect()函數一樣,表示視頻裝置編號。具體的方法和實現過程可以參考以下代碼:
view plaincopy to clipboardprint?
//判斷有沒用可用的擷取裝置
if(axCap .NumDevices <0)
{
//沒有找到可用的視頻裝置則報錯,並退出程式
MessageBox.Show ("沒有發現可用的裝置!","錯誤",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未發現可用視頻裝置");
cobDevice.SelectedIndex =0;
}
else
{
//找到則枚舉所以裝置,並初始化裝置群組合框
try
{
for(int i=0;i<axCap .NumDevices ;i++)
{
cobDevice.Items .Add (axCap .ObtainDeviceName (i));
}
cobDevice.SelectedIndex =0; //設定預設裝置
}
catch
{
MessageBox.Show ("初始化裝置失敗!","錯誤",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未發現可用視頻裝置");
cobDevice.SelectedIndex =0;
}
}
//判斷有沒用可用的擷取裝置
if(axCap .NumDevices <0)
{
//沒有找到可用的視頻裝置則報錯,並退出程式
MessageBox.Show ("沒有發現可用的裝置!","錯誤",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未發現可用視頻裝置");
cobDevice.SelectedIndex =0;
}
else
{
//找到則枚舉所以裝置,並初始化裝置群組合框
try
{
for(int i=0;i<axCap .NumDevices ;i++)
{
cobDevice.Items .Add (axCap .ObtainDeviceName (i));
}
cobDevice.SelectedIndex =0; //設定預設裝置
}
catch
{
MessageBox.Show ("初始化裝置失敗!","錯誤",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未發現可用視頻裝置");
cobDevice.SelectedIndex =0;
}
}
怎樣修改網路攝影機參數:每個網路攝影機都有很多參數,如亮度、對比、灰階等。有的攝像還可能提供很多特效效果,比如像框,黑白等。這些參數和效果都可通過調用底層的視頻裝置屬性對話方塊來修改,具體方法請參考以下代碼:
view plaincopy to clipboardprint?
private void butSet_Click(object sender, System.EventArgs e)
{
//調用DrawShow設定對話方塊
if (axCap .HasFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE ))
{
axCap .ShowFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE, "");
}
}
private void butSet_Click(object sender, System.EventArgs e)
{
//調用DrawShow設定對話方塊
if (axCap .HasFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE ))
{
axCap .ShowFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE, "");
}
}
怎樣錄影:首先要設定錄影檔案,可以通過axCap.StreamFile屬性來設定錄影檔案路徑,該屬性指的是錄影檔案的完整路徑。然後可以設定 Preview = true屬性來開啟預覽。然後調用方法axCap.StartCapture ()來開始錄影。停止錄影很簡單只需要調用函數axCap.EndCapture ()就可以了。可以參考以下代碼:
view plaincopy to clipboardprint?
private void butStartCap_Click(object sender, System.EventArgs e)
...{
if(saveFile.FileName !="") //如果設定了路徑則執行操作 否則報錯
...{
if(radCapFarme.Checked ) //執行幀捕獲操作
...{
if(!flagCapingFarmes) //如果當前沒有執行其它捕獲
...{
if(!axCap.Preview ) //開啟自動預覽
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止預覽";
}
if(chkAutoSave.Checked )
...{
//如果自動儲存為真則設定周期
axCap.Interval =Convert.ToInt32 (txtTime.Text ,10); //先設定自動儲存時間
}
axCap.AutoSave =chkAutoSave.Checked; //處理自動儲存
axCap.AutoIncrement =chkAutoRename.Checked; //處理自動改檔案名稱
axCap.FrameFile =saveFile.FileName ; //設定儲存路徑
butStartCap.Text ="停止捕獲";
flagCapingFarmes=true; //設定工作進行標誌 標誌忙
axCap.CaptureFrame (); //開始捕獲幀
}
else //如果當前進行中其它捕獲工作
...{
axCap.AutoSave =false; //關自動儲存
axCap.Interval =0; //自動儲存周期置0
butStartCap.Text ="開始捕獲";
flagCapingFarmes=false; //置工作空閑標誌
DisConnect(); //中斷連線 關閉捕獲
}
}
else //執行流捕獲
...{
if(!flagCapingStream )
...{
axCap.VideoCompressorIndex =cobVicomp.SelectedIndex ;
axCap.AudioDeviceIndex =comAudioDevice.SelectedIndex ;
axCap.AudioCompressorIndex =comAudioComp.SelectedIndex ;
axCap.StreamFile =saveFile.FileName ;
butStartCap.Text ="停止捕獲";
flagCapingStream=true;
if(!axCap.Preview ) //開啟自動預覽
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止預覽";
}
try
...{
axCap.StartCapture ();
}
catch
...{
MessageBox.Show ("視頻編碼器不可用,請重新串連裝置");
cobVicomp.Items.Clear ();
butStartCap.Text ="開始捕獲";
flagCapingStream=false;
axCap.Preview =false;
mnuDisableLink.Enabled =false;
mnuLink.Enabled =true;
cobColor.Enabled =false;
cobPix.Enabled =false;
cobColor.Text =null;
cobColor.Items.Clear ();
cobPix.Text =null;
cobPix.Items .Clear ();
txtBack.Visible =true;
chkAdvCap.Enabled =false;
butPreview.Enabled =false;
butSet.Enabled =false;
butDeviceSet.Enabled =false;
butVideoFormat.Enabled =false;
butCaptureImg.Enabled =false;
chkData.Enabled =false;
chkTime.Enabled =false;
txtLable.Enabled =false;
butPreview.Text ="開始預覽";
butLink.Text ="串連裝置";
if(chkAdvCap.Checked )
chkAdvCap.CheckState =CheckState.Unchecked ;
visableControl(false,3);
}
}
else
...{
if(axCap.Preview )
...{
axCap.Preview =false;
axCap.Visible =false;
txtBack.Visible =true;
butCaptureImg.Enabled =false;
butPreview.Text ="開始預覽";
}
butStartCap.Text ="開始捕獲";
flagCapingStream=false;
axCap.EndCapture ();
}
}
}
else
...{
MessageBox.Show ("請先設定要儲存的檔案!","錯誤",MessageBoxButtons.OK ,MessageBoxIcon.Error );
}
}
private void butStartCap_Click(object sender, System.EventArgs e)
...{
if(saveFile.FileName !="") //如果設定了路徑則執行操作 否則報錯
...{
if(radCapFarme.Checked ) //執行幀捕獲操作
...{
if(!flagCapingFarmes) //如果當前沒有執行其它捕獲
...{
if(!axCap.Preview ) //開啟自動預覽
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止預覽";
}
if(chkAutoSave.Checked )
...{
//如果自動儲存為真則設定周期
axCap.Interval =Convert.ToInt32 (txtTime.Text ,10); //先設定自動儲存時間
}
axCap.AutoSave =chkAutoSave.Checked; //處理自動儲存
axCap.AutoIncrement =chkAutoRename.Checked; //處理自動改檔案名稱
axCap.FrameFile =saveFile.FileName ; //設定儲存路徑
butStartCap.Text ="停止捕獲";
flagCapingFarmes=true; //設定工作進行標誌 標誌忙
axCap.CaptureFrame (); //開始捕獲幀
}
else //如果當前進行中其它捕獲工作
...{
axCap.AutoSave =false; //關自動儲存
axCap.Interval =0; //自動儲存周期置0
butStartCap.Text ="開始捕獲";
flagCapingFarmes=false; //置工作空閑標誌
DisConnect(); //中斷連線 關閉捕獲
}
}
else //執行流捕獲
...{
if(!flagCapingStream )
...{
axCap.VideoCompressorIndex =cobVicomp.SelectedIndex ;
axCap.AudioDeviceIndex =comAudioDevice.SelectedIndex ;
axCap.AudioCompressorIndex =comAudioComp.SelectedIndex ;
axCap.StreamFile =saveFile.FileName ;
butStartCap.Text ="停止捕獲";
flagCapingStream=true;
if(!axCap.Preview ) //開啟自動預覽
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止預覽";
}
try
...{
axCap.StartCapture ();
}
catch
...{
MessageBox.Show ("視頻編碼器不可用,請重新串連裝置");
cobVicomp.Items.Clear ();
butStartCap.Text ="開始捕獲";
flagCapingStream=false;
axCap.Preview =false;
mnuDisableLink.Enabled =false;
mnuLink.Enabled =true;
cobColor.Enabled =false;
cobPix.Enabled =false;
cobColor.Text =null;
cobColor.Items.Clear ();
cobPix.Text =null;
cobPix.Items .Clear ();
txtBack.Visible =true;
chkAdvCap.Enabled =false;
butPreview.Enabled =false;
butSet.Enabled =false;
butDeviceSet.Enabled =false;
butVideoFormat.Enabled =false;
butCaptureImg.Enabled =false;
chkData.Enabled =false;
chkTime.Enabled =false;
txtLable.Enabled =false;
butPreview.Text ="開始預覽";
butLink.Text ="串連裝置";
if(chkAdvCap.Checked )
chkAdvCap.CheckState =CheckState.Unchecked ;
visableControl(false,3);
}
}
else
...{
if(axCap.Preview )
...{
axCap.Preview =false;
axCap.Visible =false;
txtBack.Visible =true;
butCaptureImg.Enabled =false;
butPreview.Text ="開始預覽";
}
butStartCap.Text ="開始捕獲";
flagCapingStream=false;
axCap.EndCapture ();
}
}
}
else
...{
MessageBox.Show ("請先設定要儲存的檔案!","錯誤",MessageBoxButtons.OK ,MessageBoxIcon.Error );
}
}
Pegasus CapturePRO 控制項是一個功能非常強大的控制項,由於篇幅和時間關係這裡就不一一敘述了,該控制項所有的屬性、方法、事件在它的協助文檔中都有詳細的說明,大家在使用的時候 可以仔細閱讀。我寫了一個比較詳細的Demo程式,該程式使用了絕大多數功能,下面我將軟體的介面和原始碼給出,希望對大家有所協助。