程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 數字媒體: 使用WPF向控件和三維表面添加視頻

數字媒體: 使用WPF向控件和三維表面添加視頻

編輯:關於.NET

本文討論:

Windows Presentation Foundation 數字媒體基礎知識

使用 MediaElement 和 MediaPlayer

WPF 控件中嵌入的視頻

將視頻映射到三維表面上

本文使用了以下 技術:

.NET Framework 3.0

當 Windows Presentation Foundation (WPF) 開始風靡整個 Adobe Flash 社區時,我最初則表示出懷疑的態度。Microsoft 引入了一項有競爭力的技術,這使得眾多 Flash 開發人員(包括我自己在內)為了支持我們鐘愛的平台而對該公司進行了猛烈的抨擊。之後我收到 了一封電子郵件,說 Microsoft 派出了一名技術宣傳師到舊金山的 Frog Design 工作室演示 Windows® Presentation Foundation,當時我認為這將是一個極好的機會來向所有人展示為何 Flash 在各方面都更勝一籌。

在 Karsten Januszewski 的演示過程中,他向我們展示了時下著名的 North Face 演示 (channel9.msdn.com/Showpost.aspx?postid=116327),它的特色之處在於將高質量的 Windows Media® Video (WMV) 剪輯映射在一個三維旋轉式場景中的彎曲三維網格對象上。該演示是由 Fluid (另一個位於舊金山的互動工作室)和 Microsoft Windows Presentation Foundation 團隊成員聯合制 作的。眼前發生的事實驅走了我的偏見。這種形式的演示是很難借助或根本無法借助 Flash 或任何其他 相關平台完成的。

演示會後不久,我放棄了自己的成見,並下載了 Microsoft® .NET Framework 3.0 運行時,由此開始了我作為 Windows Presentation Foundation 互動設計師的職業生涯 。 從那時起,Flash 與 Windows Presentation Foundation 孰是孰非的爭論就幾乎煙消雲散了,原因是 這兩項技術真正競爭的領域並不多。而這種爭論可能會在 Microsoft 用於傳送跨平台網頁(包括圖形、 視頻、動畫和音頻)的最新解決方案發布之際再度成為眾人討論的焦點。這一即將發布的版本代號為 “WPF/E”,您可以從“WPF/E”開發人員中心獲得該版本的預覽,網址為 msdn2.microsoft.com/bb187358.aspx。

能夠將視頻映射到三維表面的功能的確足以引起互動設計 師的注意。但是在將音頻和視頻集成到 Windows Presentation Foundation 時,我們能夠實現的功能遠 不止此,這一功能只能算是皮毛而已。本文將幫助您熟悉和了解 Windows Presentation Foundation 媒 體集成的最新發展,並為您將媒體文件和感興趣的可選圖像添加到自己的應用程序提供必需的知識。

技術概覽

目前有兩種最常用的方法可以將數字媒體文件添加到 Win32® 應用程序中: 使用 DirectShow® API 或嵌入 Windows Media Player ActiveX® 控件。借助 DirectShow,開 發人員可以最大限度地控制媒體的集成,但這種做法與僅嵌入 Windows Media Player ActiveX 控件相比 要復雜得多。

對於需要對媒體顯示和管理進行細致控制的 Windows Presentation Foundation 應 用程序來說,使用 DirectShow 仍然是一個可行的選擇。您也可以將現有的 Win32 應用程序移植到 Windows Presentation Foundation 和 .NET Framework 3.0,這時就可以在 Windows Presentation Foundation 應用程序中實現 DirectShow 了。

雖然在 Windows Presentation Foundation 中您 依然可以使用 Windows Media Player ActiveX 控件播放媒體,但新的 MediaElement 控件卻是更加明智 的選擇。使用該控件您可以完成基本相同的操作,稍後您將對此有所了解;但不同之處在於它能夠與 Windows Presentation Foundation 更好地集成。特別地是,它允許您使用阿爾法混合 (alpha- blending) 技術合成媒體,並呈現在三維表面上。

音頻和視頻都能與 Windows Presentation Foundation 集成,這為開發人員提供了多種可選方案,這些方案的復雜程度及其對媒體文件的控制方式 都是各不相同的。但無論采用哪種控件或類,後台發生的操作都是大致相同的。大致的思路是這樣的,當 應用程序被要求在 Windows Presentation Foundation 中播放媒體文件時,會在後台啟動 Windows Media Player 運行時播放該文件。Windows Presentation Foundation 實際上使用的是 Windows Media Player,而並不帶有自己的媒體呈現引擎,這一點可以說是瑕瑜互見,長短並存的。Windows Media Player 的 Piggybacking 與使用 ActiveX 控件有些類似。

由於 Windows Media Player 負責 Windows Presentation Foundation 媒體播放,因此可以很容易判 斷哪些媒體格式能夠與 Windows Presentation Foundation 兼容。基本上來說,最終用戶使用現有 Windows Media Player 安裝程序可以播放的任何一種格式都可以用 Windows Presentation Foundation 應用程序播放。要添加對其他媒體類型的支持,用戶需要安裝新的視頻編解碼器。

注意,由於必 須運行 Windows Media Player 運行時才能播放媒體文件,因此當運行時在後台加載時,初次播放媒體會 出現延遲。這使得精確控制媒體變得很困難,尤其是在 Windows Presentation Foundation 中嘗試同步 音頻或視頻與動畫或其他事件,以及執行其他類似操作時。解決該問題的一種方法是,預加載媒體文件並 保持其暫停狀態,直到您准備就緒可以播放這些文件為止。另一種方法是使用動畫引擎中的滑移,您可以 借此創造其他依賴 MediaElement 的動畫,這樣一來,至少所有的延遲都是相同的。這雖然不是最佳的工 作流程,但 Windows Presentation Foundation 媒體團隊正在為下一版本的解決方案忙碌著。幸運的是 ,對於音頻播放,我們還可以選擇 System.Media.SoundPlayer 類,它允許對 WAV 文件進行簡單的播放 ,而無需 Windows Media Player。本文稍後將介紹如何使用上述 System.Media.SoundPlayer 類。

使用 MediaElement 控件

到目前為止,將媒體添加到 Windows Presentation Foundation 應用程序最簡便的方法就是使用新提供的 MediaElement 控件。與 Windows Presentation Foundation 中其他所有控件一樣,該控件可以使用 XAML 進行添加或使用 C#/Visual Basic®在代碼隱藏文件中 添加。MediaElement 使您可以對媒體文件執行基本的播放和控制操作,並能夠運行於以下兩種模式之一 :獨立模式或時鐘模式。

獨立模式是默認模式,其工作方式與傳統媒體播放器非常相似:

  <MediaElement Source="myMedia.wmv" Width="320" 
   Height="240" LoadedBehavior="Manual" />

您要設置好 Source 屬性(為指向某一媒體文件的 URI)。媒體文件加載時執行何種操作取決於 LoadedBehavior 屬 性。該屬性必須設置為 MediaState 枚舉中的某個值:Close、Manual、Pause、Play 或 Stop。為了使用 MediaElement 控件的 Play、Pause 或 Stop 方法控制媒體的播放,LoadedBehavior 屬性必須設置為 Manual。

圖 1 顯示了一個簡易媒體播放器的示例,該播放器使用運行於獨立模式的 MediaElement 控件。圖 2 顯示了用於實現該控件的 XAML 和 C# 代碼。

Figure 2 實現 MediaElement 控件

XAML

XAML
<Window x:Class="VideoProject.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="VideoProject" Height="800" Width="600">
<Grid>
  <StackPanel HorizontalAlignment="Center" 

VerticalAlignment="Center">
    <MediaElement Name="myMedia" Source="myMedia.wmv"
      LoadedBehavior="Manual" Width="320" Height="240" 

/>
    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
      <Button Content="Play" Margin="0,0,10,0"
        Padding="5" Click="mediaPlay" />
      <Button Content="Pause" Margin="0,0,10,0"
        Padding="5" Click="mediaPause" />
      <Button x:Name="muteButt" Content="Mute"
        Padding="5" Click="mediaMute" />
    </StackPanel>
  </StackPanel>
</Grid>
</Window>

C#

C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace VideoProject
{
  public partial class Window1 : System.Windows.Window
  {
    public Window1()
    {
      InitializeComponent();
      myMedia.Volume = 100;
      myMedia.Play();
    }
    void mediaPlay(Object sender, EventArgs e)
    {
      myMedia.Play();
    }
    void mediaPause(Object sender, EventArgs e)
    {
      myMedia.Pause();
    }
    void mediaMute(Object sender, EventArgs e)
    {
      if (myMedia.Volume == 100)
      {
        myMedia.Volume = 0;
        muteButt.Content = "Listen";
      }
      else
      {
        myMedia.Volume = 100;
        muteButt.Content = "Mute";
      }
    }
  }
}

圖 1 簡易 MediaElement 控件

以時鐘模式運行 MediaElement 控件,就可以使用功能強大的 Windows Presentation Foundation 動畫引擎來控制媒體的播放。要啟用時鐘模式,可以選擇將 MediaElement 定為 MediaTimeline 的一部分,也可以選擇從某一 MediaTimeline 顯式創建一個 MediaClock,並將其分配給 MediaElement(盡管不建議使用該方法)。這種方法聽起來可能難以理解, 但實際上是說您可以將 MediaElement 附加到某個 Storyboard 並使用 Windows Presentation Foundation 動畫引擎動態顯示其位置。這樣就可以實現媒體播放與您應用程序中其他動畫之間的同步。

下面給出一個 XAML 代碼的示例,在時鐘模式下使用 Storyboard 播放媒體時需要該代碼:

<MediaElement Name="myMedia" Width="320" 

Height="240" />
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
 <EventTrigger.Actions>
  <BeginStoryboard>
   <Storyboard Storyboard.TargetName="myMedia">
    <MediaTimeline Source="myMedia.wmv" 
     BeginTime="00:00:00" Duration="00:05:00" />
   </Storyboard>
  </BeginStoryboard>
 </EventTrigger.Actions>  
</EventTrigger>
</Grid.Triggers>

注意,媒體文件的源要在 MediaTimeline 設置,而並非在 MediaElement 中。MediaTimeline 通過 Storyboard.TargetName 附加屬性來確定目標 MediaElement 控 件。如果您不熟悉 Windows Presentation Foundation 動畫引擎,可能不太好理解時鐘模式。因此您需 要在勇於嘗試這一功能前先習慣 Windows Presentation Foundation 動畫的基本功能。

設置好 MediaElement 並配置其模式後,就可以對許多屬性進行讀寫操作,以進一步增強媒體播放的體驗。您只 需使用某個有效的 TimeSpan 對象來設置 Position 屬性,即可獲取或設置媒體文件的位置。通過讀取 BufferingProgress 和 DownloadProgress 屬性可以向用戶顯示緩沖和播放進度。對於音頻控件,可以設 置 Balance 和 Volume 屬性,以自定義或動態模擬媒體的音軌。現在考慮一下,如果這些值被數據綁定 到幾個滑塊,會發生什麼事情?您可以讓用戶完全控制媒體的聽覺體驗!

MediaElement 還可以觸 發許多非常實用的事件。使用 MediaOpened 和 MediaEnded,您可以根據媒體是已經開始還是結束來很方 便地觸發應用程序的其他部分。緩沖操作期間,當視頻出現靜止時,BufferingStarted 和 BufferingEnded 事件讓您能夠將反饋顯示給用戶。如果與 BufferingProgress 屬性聯合使用,就可以將 緩沖百分比顯示給用戶,這與使用 Windows Media Player 查看流視頻時的情景十分相似。

根據 自身的經驗,以及 Windows Presentation Foundation 媒體團隊的交談對此的肯定,我建議您,除非時 鐘模式是絕對必要的,否則通常應在獨立模式下使用 MediaElement 控件。標准的媒體播放和控制不需要 涉及 Storyboard 或 MediaTimeline。MediaElement 應該是媒體集成的默認選擇,因為它可以通過 XAML 進行添加,這樣媒體就可以交給設計師來實現,開發人員則可以獲得解放並投入到其他工作中。

使用 MediaPlayer 類

如果 MediaElement 控件無法為您的應用程序提供足夠的播放功能和控制, 您可以考慮下一個選擇,使用位於 System.Windows.Media 命名空間的 MediaPlayer 類。由於該類並不 是 Windows Presentation Foundation 控件元素,因此要實現 MediaPlayer,唯一的方法就是使用 C# 或 Visual Basic 在代碼隱藏文件中創建它。下面這個簡單的示例說明了如何使用 C# 來實現一個 MediaPlayer:

MediaPlayer mp = new MediaPlayer();
Try {
  mp.Open(new Uri("myMedia.wmv"));
}
catch(Exception ex) {
  MessageBox.Show(ex.Message);
}

MediaPlayer 類的可用屬性和方法與 MediaElement 控件有著驚人的類似。這不僅僅是一種巧 合。從本質上看,MediaElement 是對 MediaPlayer 類的高級封裝。使用 MediaPlayer 時有一點需要特 別注意,即它不提供任何直觀的視覺化呈現,也無法直接添加到視覺樹。要播放視頻,您需要將 MediaPlayer 繪制在可視表面之上,然後再將該表面添加到視覺樹。這使得 MediaPlayer 成為播放音頻 的較佳選擇,因為很顯然這樣做不需要視覺化的呈現。對於標准的視頻播放,MediaElement 控件則是一 個更好的選擇,因為它繼承自 UIElement 類,所以可以被直接添加到應用程序中的視覺樹。

和 MediaElement 控件一樣,MediaPlayer 實例既可以運行於獨立模式,也可以運行於時鐘模式。作 為播放控件來說,MediaPlayer 本質上也與 MediaElement 控件極其相似。那麼 MediaPlayer 到底有何 不同之處呢?嗯,其中一點不同就是 MediaPlayer 並不涉及 LoadedBehavior 或 UnloadedBehavior 屬 性,因為這些屬性是 MediaElement 控件獨有的。如果您計劃使用 VideoDrawing 類將媒體繪制到三維表 面上,就必須使用 MediaPlayer,因為 VideoDrawing 的 Player 屬性並不接受 MediaElement 控件作為 其值。(別著急,稍後我會為您講解如何將視頻繪制到三維表面和其他表面。)

另一個優點(也 可能成為缺點,這取決於您的具體情況)是,由於 MediaPlayer 並不是通過 XAML 來實現的,因此未加 入到視覺樹中。如果您的媒體文件不需要視覺化呈現,那麼不屬於視覺樹也是有一定好處的。另外二者在 加載媒體文件到應用程序的方式上也存在一些區別。在 MediaElement 控件中,您要設置其 Source 屬性 ,但在使用 MediaPlayer 類時,您調用的是 Open 方法並傳入一個有效的 Uri 對象。

因此,如 果應用程序不要求使用 XAML 實現媒體文件,或媒體文件具有自動的視覺化呈現,那麼 Media Player 可 能是您的最佳選項,因為它可以提供 MediaElement 控件的所有功能,同時沒有令人頭疼的額外開銷。

在 WPF 控件內部嵌入視頻

由於 MediaElement 控件繼承自 System.Windows.UIElement 類,因此可以被放置在任何其他 UIElement 能夠放置的位置。這種示例很多,例如在一個 Button 控件 內部嵌入一個 MediaElement 控件,就創建了一個視頻按鈕。您可以使用以下 XAML 代碼來實現此目的:

 <Button Name="myVideoButton" Click="playVideo"
     Width="320" Height="240">
   <MediaElement Name="myVid" Source="myMedia.wmv"
     LoadedBehavior="Manual" Width="320"
     Height="240" />
 </Button>

在這段代碼中,一個 Button 控件內部嵌入了 MediaElement,並將其 LoadedBehavior 屬性設置為 Manual。Button 控件的 click 事件調用一個方法(未顯示),通知 MediaElement 開始播放文件。通過寥寥幾行代碼,您已經創建了一個互動視頻縮略圖。各種各樣富於創 造性的可能都向您敞開,這是因為 Windows Presentation Foundation 實際上將 MediaElement 控件看 作是與視覺樹中其他任何 UI 元素一樣的元素。下一節中您將發現甚至可以將 MediaElement 中的視頻播 放繪制到其他 Windows Presentation Foundation 對象之上,從而創造出意想不到地豐富的用戶體驗。

“濕地板”技巧

最近,“玻璃”效果和“倒影”效果在 所有可視界面上大行其道。毫無疑問,總有一天您會被要求在 Windows Presentation Foundation 中提 供這類方法,而幸運的是,這一點很容易做到。憑借 Windows Presentation Foundation 提供的功能全 面的畫筆系統,您可以輕松地將一個控件繪制到另外一個控件上。在該示例中,我將使用 VisualBrush 將 MediaElement 控件中的視頻播放繪制到一個矩形上,創建該視頻的完美反射效果。在設計界,這種效 果被稱為“濕地板”。

創建“濕地板”效果最簡單方法是將 MediaElement 控件放置在 StackPanel 控件的第一個插槽中。然後在下面創建一個尺寸與視頻相同的矩形。接下來,將 VisualBrush 作為矩形的填充,並將其 Visual 屬性數據綁定到 MediaElement 控件。最後翻轉倒影創建 一個鏡像圖像,並應用 OpacityMask 將倒影淡化。

圖 3 顯示操作完成後的效果,而圖 4 則顯示 了 XAML 代碼。在傳統的 Win32 編程中,要進行這類可視化操作,其復雜程度往往是讓人難以置信。而 且,由於 Windows Presentation Foundation 提供了強大的數據綁定功能,因此這種倒影是一種實時的 效果,能夠隨著您視頻的更新而自動更新。

Figure 4 用於創建“濕地板”效果的 XAML

<Grid x:Name="myGrid">
<StackPanel VerticalAlignment="Center">
  <MediaElement Name="myVid" Source="myMedia.wmv"
    LoadedBehavior="Play" Width="320" Height="240" />
  <Rectangle Width="320" Height="240">
    <Rectangle.Fill>
      <VisualBrush Visual="{Binding ElementName=myVid}" />
    </Rectangle.Fill>
    <Rectangle.OpacityMask>
      <LinearGradientBrush StartPoint="0.5,0" 

EndPoint="0.5,1">
        <GradientStop Color="#AA000000" Offset="1" />
        <GradientStop Color="#00000000" Offset="0" />
      </LinearGradientBrush>
    </Rectangle.OpacityMask>
    <Rectangle.RenderTransform>
      <TransformGroup>
        <ScaleTransform ScaleY="-1" />
        <TranslateTransform Y="242" />
      </TransformGroup>
    </Rectangle.RenderTransform>
  </Rectangle>
</StackPanel>
</Grid>

圖 3 已完成的“濕地板”效果

將視頻映射到三維表面之上

如果必須從 Windows Presentation Foundation 中選出一個最受 人歡迎的常用功能,我認為應該是將視頻文件映射到三維網格對象之上這一功能。North Face 演示向我 們展示了這一功能對於創造極具視覺沖擊的用戶界面的幫助是多麼強大。盡管許多人將這一效果描繪成唬 人的噱頭或“吃資源”的猛獸,但我認為,只要應用適度,這一技術可以使普通應用程序搖身 一變,轉而能夠向用戶提供震撼的體驗。

就性能而言,顯示三維網格並使其實現動畫效果無疑會 造成相當大的系統開銷。如果還要顯示映射在三維網格之上的全動態視頻,那麼所需的開銷將是巨大的。 就像喝摩卡星冰樂 (mocha frappucino) 一樣,關鍵還是要適度。大致說來,我發現只要將三維網格的復 雜性(多邊形計數)維持在必要的最低水平,Windows Presentation Foundation 就可以表現出很優秀的 三維性能。Windows Presentation Foundation 媒體團隊承諾會在將來的版本中減少三維媒體需要的開銷 ,盡管其開銷會始終大於二維媒體。

在介紹如何將視頻映射到三維對象之前,我們先看一下在 Windows Presentation Foundation 中設置一個三維場景都需要哪些元素。首先,也是最重要的,需要在 場景中放置一個三維對象。.NET Framework 3.0 中不包含任何三維基元類。但 Microsoft 的某位員工創 建了一個名為 Mesh3DObjects 的類,使用它可以創建各種基元對象。

要在 Windows Presentation Foundation 中創建一個三維場景,需要使用特定的元素組。首先,需要三維對象,而且該 對象需要具備某種材料才能在場景中可見。這些材料要通過畫筆(如 SolidColorBrush、 LinearGradientBrush、ImageBrush 或 VisualBrush)來創建。稍後您將知道如何使用 VisualBrush 將 視頻或任何其他可視元素映射到一個三維表面之上。這種技巧從本質上講與之前討論的“濕地板 ”技巧是相同的。

三維網格和這些材料需要分組放入一個 GeometryModel3D 元素內部,這 樣做可以創建一個有效的 Windows Presentation Foundation 三維對象。為了使三維場景可見,我們需 要向場景內添加一個或多個光源。然後,正如沒有照相機就無法拍照片一樣,Windows Presentation Foundation 中也不能缺少三維場景。最後,要完成場景,還需要將所有這些項包裝在 Viewport3D 控件 中以便進行封裝處理。

功能正常的三維場景准備就緒後,您就可以開始享受將視頻和其他媒體映 射到三維網格之上的樂趣了。使用 VisualBrush 將視頻繪制到三維表面上,整個過程即可完成。以下的 代碼段中,一個 VisualBrush 被應用於一個三維對象的 DiffuseMaterial:

<GeometryModel3D.Material>
<DiffuseMaterial>
  <DiffuseMaterial.Brush>
    <VisualBrush>
      <VisualBrush.Visual>
        <MediaElement Source="myMedia.wmv" />
      </VisualBrush.Visual>
    </VisualBrush>
  </DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>

圖 5 顯示的是映射到 Windows Presentation Foundation 三維表面之上的視頻的某一幀。

圖 5 映射到一個 WPF 三維表面

在 Windows Presentation Foundation 中,您可以使用另外一種方法將視頻映射到三維表面。 VideoDrawing 類屬於 System.Windows.Media 命名空間,它的作用是名副其實的,就是繪制視頻。該類 可以通過 DrawingBrush 將來自 MediaPlayer 實例的視頻繪制到任何與畫筆兼容的表面之上。為了實現 這一目的,您需要將 DrawingBrush 的 Drawing 屬性設置為 VideoDrawing 類的一個實例。該 VideoDrawing 實例可以通過將自己的 Player 屬性設置為一個包含視頻文件的 MediaPlayer 實例來呈現 視頻。最後,可以將 DrawingBrush 應用於一個三維對象的 DiffuseMaterial 的 Brush 屬性。以下代碼 段顯示了一個使用 C# 來實現的示例:

MediaPlayer mp = new MediaPlayer();
mp.Open(myValidMediaUri);
VideoDrawing vd = new VideoDrawing();
vd.Player = mp;
DrawingBrush db = new DrawingBrush();
db.Drawing = vd;
diffuseMat.Brush = db;
vd.Player.Play();

使用 VisualBrush 或 VisualDrawing 類的主要差異之一在於, VisualDrawing 類必須在代碼隱藏文件中才能得以創建和實現(使用 C# 或 Visual Basic)。此外, VideoDrawing 類僅對 MediaPlayer 實例起作用,對於 MediaElement 控件則不起作用。從性能方面考慮 ,兩種方法之間的差異不大,因為二者都需要 Windows Presentation Foundation 為其創建一個呈現視 頻的表面,以起到橋梁作用,以便將視頻正確映射到三維物體。

呈現來自視頻幀的視圖

視頻應用程序可能有必要捕捉視頻流的屏幕快照並將其顯示為位圖。在某些商業 DVD 播放軟件中您可 以看到這類示例,在播放視頻的過程中用戶只需隨時單擊一個照相機圖標,就可以從視頻中捕捉一張屏幕 快照。如果您不希望將一組視頻文件全部實際地連接到 MediaElement 控件,可以為這組視頻文件創建縮 略圖。而且有時還可能借此創建一些運行時視頻效果,盡管對於此類操作您最好還是先深入研究 DirectShow API 才能取得滿意的效果。

與 Windows Presentation Foundation 中的大多數情況一樣,完成一項任務可以有多種方法,顯示視 頻幀的位圖也是如此。不管使用哪種方法,要在 Windows Presentation Foundation 中呈現可視元素的 位圖,核心的功能都是通過 RenderTargetBitmap 類來實現,該類屬於 Windows.Media.Imaging 命名空 間。該類的功能之強大令人驚異,它可以從 Windows Presentation Foundation 應用程序視覺樹中的任 何一個項創建位圖。

要使用該類呈現一個位圖,首先需要新建一個 DrawingVisual 對象,該對象將傳遞給 RenderTargetBitmap.Render 方法。接下來,新建一個 DrawingContext 對象,稍後將傳遞給 DrawingVisual.Render 方法。借助該 DrawingContext 實例,您可以將各種圖形繪制到 DrawingVisual 對象中。要繪制一個視頻幀,可以調用 DrawingContext.DrawVideo 方法,並傳入一個當前正在播放視頻 文件的 MediaPlayer 實例。另外還需要傳入一個 Rect 值,該值確定了要捕捉的視頻文件區域。

現在,您可以真正地從包含已捕捉視頻幀的 DrawingVisual 實例呈現位圖了。要實現這一點,您只需 將其傳遞給 RenderTargetBitmap.Render 方法即可。現在您的 RenderTargetBitmap 實例中已包含了該 視頻幀,但只有將其傳遞給 BitmapFrame.Create 方法後,它才能夠成為位圖。要查看該位圖幀,只需將 此方法調用設為一個 Image 控件的 Source 屬性的值即可。以下代碼段顯示了如何使用 C# 來實現這一 幀捕捉技巧:

RenderTargetBitmap rtb = new RenderTargetBitmap(320, 240, 1 / 200,
1 / 200, PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();
dc.DrawVideo(myMediaPlayer, new Rect(0, 0, 320, 240));
dc.Close();
rtb.Render(dv);
Image im = new Image();
im.Source = BitmapFrame.Create(rtb);

目標位圖的格式是通過將一個有效的 PixelFormats 枚舉值傳遞給 RenderTargetBitmap 構造函數來 設置的。將視頻幀呈現為位圖的功能乍一看似乎毫不起眼,但實際上除了應用於簡單的視頻屏幕捕獲工具 外,這種功能還有很多其他的用途。

WPF 中的其他音頻功能

到目前為止,我所討論的有關 Windows Presentation Foundation 媒體集成的大部分內容都是適用於 視頻和音頻的。但另外還有幾個類可用於處理 Windows Presentation Foundation 中的音頻播放。如前 所述,Windows Presentation Foundation 中播放的媒體實際上是由一組 Windows Media Player 運行時 來驅動的,要播放文件必須先加載這些運行時。而當您嘗試同步媒體文件和用戶事件或動畫時,就會導致 一個嚴重的問題(盡管可以通過時間線中的滑移行為來緩解)。而就音頻而言,我們可以通過某些替代方 法繞過這一問題。

SoundPlayer 類屬於 System.Media 命名空間,它能提供一個簡單的接口來加載和播放 WAV 音頻文件 。這些 WAV 文件可以是外部資源、流式資源或嵌入式資源。與借助 MediaElement 控件播放音頻文件相 比,這種音頻播放方法的開銷要低得多,因為它根本不依賴 Windows Media Player 來播放文件。

要 將一個 WAV 文件加載到 SoundPlayer 實例中,首先要將 SoundLocation 屬性設置為該 WAV 文件的位置 ,然後再調用 Load 方法來啟動加載過程。文件完全加載後,就可以使用 SoundPlayer.Play 方法來播放 文件了。文件在完全加載到內存之前是不會開始播放的。

在 XAML 中,您可以使用 SoundPlayerAction 控件來播放輕型音頻,該控件使您能夠在 EventTrigger 內部播放 WAV 文件。對於實現諸如按鈕翻轉的界面聲音來說,這一功能是非常實用的。將 該控件置入 EventTrigger 的 EventTrigger.Actions 塊中即可使用。以下代碼段顯示的是響應一個按鈕 的 MouseEnter 事件對 SoundPlayerAction 進行調用的操作:

<EventTrigger RoutedEvent="Button.MouseEnter" SourceName="myButton">
<EventTrigger.Actions>
<SoundPlayerAction Source="media/overSound.wav"/>
</EventTrigger.Actions>
</EventTrigger>

總結

在本文中,我為大家介紹了將音頻和視頻集成到 Windows Presentation Foundation 應用程序的方法 。如果 Windows Presentation Foundation 為您的項目提供的控制無法滿足您的需要,您總是可以恢復 為使用 DirectShow API 進行媒體集成。但是能夠借助 XAML 添加音頻和視頻這一點使得簡單的媒體集成 可以交給設計師來做,從而解放了開發人員,使其能夠集中精力進行更復雜的代碼編寫工作。到此,我已 經將以前的懷疑態度拋到九霄雲外。Windows Presentation Foundation 提供了令人驚奇又極其豐富的視 覺體驗,這使得媒體集成不僅是可能的,更是令人極度興奮的!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved