利用Visual C#開發一個媒體播放器

來源:互聯網
上載者:User
                                     

摘要:瞭解如何在 Microsoft Visual C# .NET 中使用 DirectShow 控制項,如何開發一個媒體播放器。按照本文介紹的操作步驟,您可以建立一個簡單 Visual C# 應用程式,用來播放數字音頻和視頻。

   簡介

  Microsoft Visual C# 是世界上最流行的程式設計語言,利用 Visual C# 的最新版本 Visual C# .NET,您能夠快速、有效地開發基於 Windows 表單的應用程式,還可以為嵌入了 Microsoft Windows Media? Player 9 Series ActiveX 控制項的應用程式添加新鮮、有趣而又非常實用的功能。

  DirectShow 控制項是一個標準的 ActiveX 控制項,提供了大量的功能。DirectShow控制項提供的功能包括:

  · 數位媒體檔案和流媒體的進階播放功能。     

  · 使用播放清單的功能。
  · 播放 DVD 和 CD 的功能。
  · 訪問 Windows Media Player 中的 Media Library(媒體庫)。
  · 處理中繼資料的功能。
  · 支援字幕。
  · 支援多種語言的音頻。
  · 控制網路連通性和訪問相關統計資訊的功能。

  下面我們來看看構造這個媒體播放器要達到什麼樣的目標,確定了目標也就確定了代碼量和程式的複雜程度。本文的媒體播放器要達到如下目標:

  · 是一個菜單驅動的簡單AWT應用。
  · 包含一個[檔案] 功能表,檔案菜單包含三個功能表項目:
  · “開啟”,用來開啟媒體檔案。
  · “迴圈”,是播放一次(預設),還是重複播放。
  · “退出”,退出程式。
  · 可以在多種平台上運行。
  · 核心功能通過JMF(Java Media Framework)API實現。

  按照本文介紹的步驟,您將建立一個基於 Windows 表單的基本應用程式,並在其中嵌入 Player 控制項。您建立的應用程式範例具有如下特點:

  · 建立 DirectShow 控制項的一個執行個體。
  · 利用 Windows Media Player 主要 Interop 組件提供元件物件模型 (COM) 互通性。
  · 允許使用者開啟並播放 Windows Media 檔案,尤其是副檔名為 .wma 或 .wmv 的檔案。
  · 建立供使用者播放、暫停和停止數位媒體內容的傳輸控制按鈕。
  · 顯示當前數位媒體檔案的標題。
  · 示範如何使用 Player 物件模型,包括使用屬性、方法和事件的樣本。

  我的這個程式僅僅只是告訴大家如何用DirectShow 在C#中做一個播放機,

  在這個程式中我們經要解決的一些小問題:

  1.如何從你的磁碟上開啟媒體檔案

  2.如何讓工具條上的按鈕起用和禁用

  3.如何設定狀態列的顯示文字

  4.如何控制時間 

  5.如何使用時間控制項的事件
 
  6.如何用DirectShow來播放媒體檔案

  7.如何確定播放狀態等等...

  顯示了您將要建立的應用程式,其中現正播放名為“Melow”的數字音頻檔案,同時呈現了視覺效果。


圖 1
  · 本文假設您已經具備一定的 Visual C# 和 Visual Studio.NET 整合式開發環境知識。

準備工作

  在開始建立應用程式之前,您需要安裝必要的軟體並註冊主要 Interop 組件 (QuartzTypeLib)。

  這裡簡單介紹DirectShow 介面:

  播放視屏和音效檔我們要用到DiectX為我們提供的DirectShow組件.使用這個介面可以讓你方便的播放那些共用的影像和音效檔.你要做的僅僅只是安裝DirectShow介面和使用它的功能函數和配置正確的介面參數而已.

  不幸的是.NET並不正式支援DirectX.是的也許你聽說DirectX9支援是嗎?是的,不過在最終版敲定的那一天還沒來,我們都得不到最好的效果.但無論如何我們還是要用的不是嗎?要不這篇文章得作廢了.是的,也許你用過VB,對了,就是它,我們正是要用到那個.

  開始項目

  在安裝必要軟體並註冊 QuartzTypeLib之後,您就可以啟動 Visual C#,開始為應用程式範例建立項目。下面我將給大家介紹這一過程的操作步驟。

  建立項目

  按以下步驟建立一個空的項目:

  1. 啟動 Visual Studio .NET,然後單擊 New Project(建立項目)。

  2. 在 Visual C# Projects(Visual C# 項目)檔案夾中單擊 Windows Application(Windows 應用程式),鍵入新項目的名稱(最好為 DirectShow),然後單擊 OK(確定)。

  Visual C# 使用預設的 Windows 表單“Form1”建立一個新的項目。

  3. 這個名稱並沒有特別的意義或用處,所以請在 Properties(屬性)視窗中將表單名稱更改為 frmPlayMedia,將表單文本更改為“媒體播放器”。

  在項目中添加對 DirectShow的引用

  按照以下步驟在項目中添加一個對 DirectShow的引用:

  1. 開啟 Visual Studio 工具箱,然後單擊 Components(組件)顯示該面板。

  2. 右擊面板,然後單擊 Customize Toolbox(自訂工具箱),顯示對話方塊。

  3. 在 COM Components(COM 組件)選項卡上,選中 Interop.QuartzTypeLib.dll。(如果 Interop.QuartzTypeLib.dll 由於某種原因未列出,則單擊 Browse [瀏覽] 並尋找名為 QuartzTypeLib.dll的檔案。)

  4. 單擊 OK(確定)關閉對話方塊。


圖 2
  要在代碼中使用 DirectShow,您需要添加一行代碼,以引用 DirectShow命名空間。在表單代碼視窗的頂部,將以下代碼添加到所有聲明語句之前:

using QuartzTypeLib;
  using語句必須在所有 Options 語句(本項目中並未使用)之後,並且在所有其他代碼之前。添加該語句後。

開發應用程式

  建立通過 PIA 與 Framework 串連的 Player 控制項執行個體之後,您可以向表單中添加所需的其他元素,並編寫完成實際操作的代碼。
添加 Windows 表單控制項

  1. 在 View(視圖)菜單中,單擊 Designer(設計器),或者單擊 Solution Explorer(方案總管)中的 View Designer(視圖設計器)按鈕,切換到表單設計器。

  2. 在表單上增加檔案、播放、資訊等菜單。

  3. 在工具箱的 Windows Forms(Windows 表單)面板中,為您的表單添加一個工具列、一個狀態列和圖片imageList。

  4. 在 Properties(屬性)視窗中,將工具列的名稱更改為 toolBar1,將在Buttons上增加4個按鈕。狀態列的名稱更改為 statusBar1,並分別增加三個Panel。

  5. 在工具箱的面板中,為您的表單添加一個面版panel1。

  6. 增加一個定時器timer1。

  7. 調整控制項在表單中的相片順序,使之符合您的需要而且方便使用者使用。為 Visual Studio Designer(設計器)中完成後的表單布局。


圖 3
  編寫代碼

  如何開啟你想要媒體檔案?

  第一步是編寫在 frmPlayMedia中開啟 Windows Media 檔案的代碼。要自動切換到 Code(代碼)視圖並編輯開啟菜單的 Click 事件處理常式 (menuItem2_Click) 的代碼,請雙擊表單上的“工具列”按鈕。將以下代碼添加到事件處理常式中:

  還記得嗎"檔案 -> 開啟..." 是的幾乎每個使用windows的人都會這樣操作.如何??

  很簡單看看下面的代碼:

OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Media Files|*.mpg;*.avi;*.wma;*.mov;*.wav;*.mp2;*.mp3|All Files|*.*";
if (DialogResult.OK == openFileDialog.ShowDialog())
{
….
}
  看吧很簡單是嗎?記得寫一個函數把它放進去。當你點擊OK按鈕的時候,DirectShow介面就會得到你想要播放的檔案。解釋了它是如何工作的。

  DirectShow為多媒體流回放提供最基本的服務,這些多媒體流可以是本地檔案,還可以是伺服器傳輸過來的。特別的,DirectShow可以可使用視訊回放,支援以不同的檔案和流格式壓縮視頻內容,包括Windows Media、MPEG、AVI和WAV。

  在DirectShow的核心處,服務是組件的模組化集合,稱為過濾器,可以根據媒體類型排列成過濾器圖。過濾器可以操作資料流,如讀入、分析、解碼、格式化或渲染。

  過濾器以樹型進行排列,這棵樹稱為過濾器樹,通過過濾器樹管理器(Filter Graph Manager,簡稱FGM)進行管理。使用FGM應用程式可以通過使用Microsoft Windows Media Player控制項間接控制過濾器樹,還可以通過調用COM介面方法直接控制。DirectShow過濾器樹(參閱圖1)由從源到目標渲染器的有向過濾器序列組成,所有這些通過輸入和輸出過濾器引腳串連。過濾器引腳協商它們將支援哪些媒體類型。FGM控制樹過濾器之間的多媒體資料流。因為DirectShow有一個靈活的、可重配置的過濾器樹體繫結構,因此DirectShow可以使用同樣的軟體成分支援多種媒體類型的回放和分流。開發人員還可以通過編寫自己的過濾器擴充DirectShow多媒體支援。

  過濾器

  過濾器是註冊的DirectShow類,它執行許多媒體資訊處理任務。這些任務包括:

   獲得源資訊(例如,獲得媒體流)
   分析(例如,在流上執行包讀入、分離和格式化)
   轉換(例如,解碼WMA和MPEG-4音頻和視頻流)
   渲染(例如,在適當的時候產生音頻PCM或者視頻RGB/YUV輸出,將資料傳給DirectSound和DirectDraw)

  過濾器使用幾種類型的介面,例如引腳、計數器、傳送器和時鐘介面,來執行它們的任務。過濾器實現和開放了許多介面。FGM可以使用這些介面建立、串連和控制樹。過濾器經常實現包含下列方法的IBaseFilter介面:

   運行、停止和暫停過濾器狀態。
   恢複過濾器和廠商資訊。
   得到和設定參考時鐘。
   恢複過濾器狀態資訊。
   枚舉過濾器引線。
   重建過濾器樹時定位引腳

  使用者單擊“開啟”時,這段代碼將顯示一個對話方塊,供使用者在電腦上瀏覽並選擇要播放的 .wma 或 .wmv 檔案。使用者選擇檔案(並單擊“確定”)時,代碼將 Player 的 URL 屬性設定為使用者選擇的檔案。由於 Player 的 autoStart 屬性在預設情況下設定為 True,所以 Player 立即開啟並播放使用者選擇的數位媒體檔案。

  接下來,添加播放/暫停按鈕的代碼。在代碼視窗中,在停止、暫停菜單中單擊,然後,在方法名稱列表中單擊 Click。將以下代碼添加到 Visual C# 為您建立的Click 事件處理常式中:

  看看下面的代碼是如何?的:

CleanUp();
m_objFilterGraph = new FilgraphManager();
m_objFilterGraph.RenderFile(openFileDialog.FileName);
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
try
{
 m_objVideoWindow = m_objFilterGraph as IVideoWindow;
 m_objVideoWindow.Owner = (int) panel1.Handle;
 m_objVideoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
 m_objVideoWindow.SetWindowPosition(panel1.ClientRectangle.Left,
 panel1.ClientRectangle.Top,
 panel1.ClientRectangle.Width,
 panel1.ClientRectangle.Height);
}
catch (Exception ex)
{
 m_objVideoWindow = null;
}
m_objMediaEvent = m_objFilterGraph as IMediaEvent;
m_objMediaEventEx = m_objFilterGraph as IMediaEventEx;
m_objMediaEventEx.SetNotifyWindow((int) this.Handle, WM_GRAPHNOTIFY, 0);
m_objMediaPosition = m_objFilterGraph as IMediaPosition;
m_objMediaControl = m_objFilterGraph as IMediaControl;

//

如何來播放,暫停,停止?
簡單這些函數看字面也知道.
//

m_objMediaControl.Run();//播放
m_objMediaControl.Pause();//暫停
m_objMediaControl.Stop();//停止

// 這段代碼非常簡單。當使用者單擊播放/暫停按鈕時,代碼將檢查 Player 的 playState 屬性。如果 Player 現正播放數位媒體檔案,代碼就會暫停檔案的播放; 如果 Player 已經暫停或停止,代碼就再次啟動 Player 播放檔案。
OK,在來看我們是如何控制時間進度的?
//

private void timer1_Tick(object sender, System.EventArgs e)
{
 if (m_CurrentStatus == MediaStatus.Running)
 {
  UpdateStatusBar();
 }
}
  看見上面那個 UpdateStatusBar();這裡是讓它沒100ms更新一次狀態列.

  代碼如下:

private void UpdateStatusBar()
{
 switch (m_CurrentStatus)
 {
  case MediaStatus.None : statusBarPanel1.Text = "Stopped"; break;
  case MediaStatus.Paused : statusBarPanel1.Text = "Paused "; break;
  case MediaStatus.Running: statusBarPanel1.Text = "Running"; break;
  case MediaStatus.Stopped: statusBarPanel1.Text = "Stopped"; break;
 }
 if (m_objMediaPosition != null)
 {
  int s = (int) m_objMediaPosition.Duration;
  int h = s / 3600;
  int m = (s - (h * 3600)) / 60;
  s = s - (h * 3600 + m * 60);
  statusBarPanel2.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
  s = (int) m_objMediaPosition.CurrentPosition;
  h = s / 3600;
  m = (s - (h * 3600)) / 60;
  s = s - (h * 3600 + m * 60);
  statusBarPanel3.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
 }
 else
 {
  statusBarPanel2.Text = "00:00:00";
  statusBarPanel3.Text = "00:00:00";
 }
}
  還有一個問題程式怎麼能夠知道它播放完了?

  這會有點麻煩了,想想看有什麼辦法呢?對了,windows是訊息驅動的。那找找看有什麼訊息。有的就EC_COMPLETE。還記得"WndProc" 它嗎?是的,我的老朋友,這次我們必須要改寫它來捕獲EC_COMPLETE訊息。這個訊息是DirectShow通知父表單,播放結束了。

protected override void WndProc(ref Message m)
{
 if (m.Msg == WM_GRAPHNOTIFY)
 {
  int lEventCode;
  int lParam1, lParam2;
  while (true)
  {
   try
   {
    m_objMediaEventEx.GetEvent(out lEventCode,out lParam1,out lParam2,0);
    m_objMediaEventEx.FreeEventParams(lEventCode, lParam1, lParam2);
    if (lEventCode == EC_COMPLETE)
    {
     m_objMediaControl.Stop();
     m_objMediaPosition.CurrentPosition = 0;
     m_CurrentStatus = MediaStatus.Stopped;
     UpdateStatusBar();
     UpdateToolBar();
    }
   }
   catch (Exception)
   {
    break;
   }
  }
 }
 base.WndProc(ref m);
}
  只要播放狀態改變,上述代碼就會運行。如果 Player 現正播放(使用者開啟檔案時就處於播放狀態,因為 autoStart 設定為 True),代碼將啟用播放/暫停按鈕和停止按鈕,以便使用者執行操作。之後,代碼將播放/暫停按鈕的文字更改為“暫停”,這樣使用者就可以使用該按鈕暫停播放過程。最後,代碼檢索當前數位媒體檔案的標題,並更新標題標籤的文字以顯示標題。

  如果 Player 被暫停(使用者單擊了播放/暫停按鈕),代碼會將播放/暫停按鈕的文字更改為“播放”,以提示使用者使用該按鈕可以恢複播放。

  如果 Player 被停止(使用者單擊了停止按鈕),代碼將禁用停止按鈕(因 Player 已經停止工作)並將播放/暫停按鈕的文字恢複為預設值“播放”。

  一切都結束了,現在要做的事就是做些來找一部影片來享受一下自己的成果了.

  編寫完樣本項目的代碼之後,您可以產生並運行解決方案。

  產生解決方案

  在 Build(產生)菜單中單擊 Build Solution(產生解決方案)。Visual Studio 開始編譯並產生項目。如果鍵入內容全部正確,產生過程將順利完成,不會出現任何錯誤。如果產生報告錯誤,則請檢查您的代碼並糾正錯誤。

  使用應用程式範例

  要在調試器中運行項目,請按鍵盤上的 F5 鍵。如果出現“查看產生的程式碼”主題中介紹的未處理的異常,則應該停止偵錯工作階段,刪除或注釋掉產生代碼中的相應行,然後再按 F5 鍵。

  您可以單擊“開啟”尋找 .wma 或 .wmv 檔案(究竟選擇何種檔案,取決於您在“開啟”對話方塊中選擇的檔案類型)。選擇某個檔案並單擊“確定”之後,“開啟”對話方塊關閉,開始播放數位媒體檔案,傳輸控制按鈕的狀態也隨之改變。這時您就可以利用傳輸控制按鈕來暫停、重新開始或完全停止播放。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.