共用方式為


Windows Phone 7

在 Windows Phone 應用程式中使用相機

Matt Stroshane

通過圖片進行溝通交流是一種高效且優雅的方式,而只借助文字進行溝通是無法與之媲美的。 您聽說過“一圖抵千言”吧;請想像一下,當您的 Windows Phone 應用程式能夠直接訪問相機功能時您可以解決的各種問題。 從 Windows Phone 7.5 開始,您可以開始使用設備中的相機功能解決這些難於用語言描述的問題。

在本文中,我將介紹前置和後置相機、相機 API 及相關的清單功能,我還將討論您可以在下一版本的 Windows Phone 7.5 應用程式中使用相機功能的幾種不同方式。 我將討論以下內容:

  • 拍攝照片:我將創建一個非常簡單的照片應用程式。
  • 訪問相機預覽緩衝區:我將介紹“相機灰度示例”。
  • 錄製視頻:我將介紹“錄影機示例”。

您將需要使用 Windows Phone SDK 7.1 創建一個 Windows Phone 7.5 應用程式。 該 SDK 包括一些極為詳盡地演示其中每個方案的代碼示例。 有關詳細資訊,請參閱 SDK 中“代碼示例”頁(網址為 wpdev.ms/officialsamples)上的“基本相機示例”、“相機灰度示例”和“錄影機示例”。

請注意,本文不介紹自 Windows Phone 7 以來提供的相機捕捉任務。 儘管該任務是一種為應用程式獲取照片的簡單方式,但它不允許您以程式設計方式拍攝照片或訪問相機預覽緩衝區。

Windows Phone 7.5 設備最多可以包括兩個相機,即一個主相機和一個前置相機。 主相機位於設備的背面,與前置相機相比,它通常可提供較高的解析度和更多功能。 這兩個相機在 Windows Phone 7.5 設備中都不是必需的,因此,請確保在創建相機物件之前,在您的代碼中檢查這些相機的狀態。 稍後,我將演示如何使用靜態 IsCameraTypeSupported 方法實現此目的。

在美國地區銷售的許多 Windows Phone 設備均包括一個主相機,該相機具有 5MP 或更高圖元的感測器、閃光燈和自動聚焦功能。 前置相機是 Windows Phone 7.5 中的新增功能。

有關設備規格的詳細資訊,請參閱 windowsphone.com 上的“購買”選項卡。

拍攝照片

您可以使用相同的類同時訪問主相機和前置相機。 您將看到,選擇相機類型就是在 PhotoCamera 物件的構造函數中指定一個參數。 但是,從設計角度而言,您可能希望採用不同的方式來處理與前置相機的交互。 例如,您可能希望從前置相機翻轉圖像,以便為使用者提供更自然的鏡像體驗。

在使用 Windows Phone 7.5 應用程式拍攝照片時,您將主要使用 Microsoft.Devices 命名空間中的 PhotoCamera 類。 該類對相機設置和行為提供大量控制。 For example, you can:

  • 使用 PhotoCamera.CaptureImage 方法啟動相機快門
  • 使用 PhotoCamera.Focus 方法觸發自動聚焦
  • 通過設置 Photo-Camera.Resolution 屬性指定圖片解析度
  • 通過設置 Photo-Camera.FlashMode 屬性指定閃光燈設置
  • 使用靜態 CameraButtons 類中的事件合併硬體快門按鈕
  • 使用 PhotoCamera.Focus­AtPoint 方法實現觸控聚焦

在本文中,我將只演示第一點。 有關演示如何執行所有這些操作的示例,請參閱 Windows Phone SDK 代碼示例頁中的“基本相機示例”。

值得注意的是,即使相機可供使用,它也可能並不支援所有這些 API。 以下幾種方法可以説明確定可供使用的功能:

  • 相機:使用 PhotoCamera.IsCameraTypeSupported 靜態方法。
  • 自動聚焦:使用 PhotoCamera.IsFocus­­-Supported 方法。
  • 圖片解析度設置:檢查 Photo­-Camera.AvailableResolutions 集合。
  • 閃光燈設置:使用 PhotoCamera.IsFlashMode­Supported 方法。
  • 特定點聚焦:使用 PhotoCamera.IsFocus­AtPointSupported 方法。

為使您瞭解如何使用應用程式拍攝照片,我將指導您創建一個簡單的應用程式,該應用程式會在您觸摸取景器時拍攝照片,然後將照片保存到圖片中心的“本機照片”資料夾中。

可使用 Windows Phone 應用程式範本從標準 Windows Phone 專案開始。 您可以在 C# 或 Visual Basic 中編寫 Windows Phone 7.5 應用程式。 本示例將使用 C#。

我會通過將應用程式限制為僅橫向方向以及僅使用主相機來簡化本示例。 管理設備和兩個相機的方向,如果每個都指向不同的方向,很快會令人困惑;建議使用物理設備進行測試,以確保獲得所需的行為。 我將在稍後更詳細地介紹方向。

在 MainPage.xaml 上,更新 PhoneApplicationPage 屬性,如下所示:

SupportedOrientations="Landscape" Orientation="LandscapeLeft"

然後,使用圖 1 中所示的 Canvas 和 TextBlock 替換 LayoutRoot Grid 的內容。

圖 1 添加 Canvas 和 TextBlock

<Canvas x:Name="viewfinderCanvas" Width="640" Height="480" Tap="viewfinder_Tapped">
  <Canvas.Background>
    <VideoBrush x:Name="viewfinderBrush">
      <VideoBrush.RelativeTransform>
        <CompositeTransform
          x:Name="viewfinderTransform"
          CenterX="0.5"
          CenterY="0.5"/>
      </VideoBrush.RelativeTransform>
    </VideoBrush>
  </Canvas.Background>
</Canvas>
<TextBlock Width="626" Height="40"
           HorizontalAlignment="Left"
           Margin="8,428,0,0"
           Name="txtMessage"
           VerticalAlignment="Top"
           FontSize="24"
           FontWeight="ExtraBold"
           Text="Tap the screen to capture a photo."/>

圖 1 中的 XAML 在 Canvas 中使用 VideoBrush 來顯示取景器,並提供用於和使用者進行溝通的文字區塊。 相機感測器的長寬比為 4:3,而螢幕的長寬比為 15:9。 如果您不使用同一 4:3 比率指定畫布尺寸 (640x480),圖像將在螢幕上拉伸顯示。

在 Canvas 元素中,Tap 屬性指定當使用者點擊螢幕時調用的方法,即 viewfinder_Tapped 方法。 為從相機預覽緩衝區中顯示圖像流,已將名為 viewfinderBrush 的 Video­Brush 指定為畫布的背景。 與單反 (SLR) 相機中的取景器一樣,viewfinderBrush 使您能夠查看相機預覽幀。 ViewfinderBrush 中的轉換實際上會在取景器旋轉時將其“固定”到畫布的中心。 我將在以下部分中討論此 XAML 後面的代碼。 圖 2 顯示該簡單照片應用程式的使用者介面。

The Simple Photo App UI
圖 2 簡單照片應用程式的使用者介面

初始化和釋放相機:要拍攝照片並將照片保存到圖片中心的“本機照片”資料夾中,您將分別需要 PhotoCamera 和 MediaLibrary 類。 首先添加對 Microsoft.Xna.Framework 程式集的引用。 對於本示例,您無需瞭解 XNA 程式設計;但是,您確實需要此程式集中的類型,以便訪問媒體庫。

在 MainPage.xaml.cs 檔的頂部,為相機和媒體庫添加指令:

using Microsoft.Devices;
using Microsoft.Xna.Framework.Media;

在 MainPage 類中,添加以下類級別的變數:

private int photoCounter = 0;
PhotoCamera cam;
MediaLibrary library = new MediaLibrary();

相機可能需要幾秒鐘時間來進行初始化。 通過在類級別聲明 PhotoCamera 物件,您可在導航到頁面時創建該物件,並在離開該頁面時將其從記憶體中刪除。 我們將使用 OnNavigatedTo 和 OnNavigatingFrom 方法實現此目的。

在 OnNavigatedTo 方法中,創建相機物件,註冊將要使用的相機事件,並將相機預覽設置為取景器、viewfinderBrush 的源。 雖然相機通常在 Windows Phone 7.5 中是可選功能;但在創建相機物件之前檢查相機十分重要。 如果主相機不可用,則該方法會向使用者寫入一條消息。

圖 3 中所示的方法添加到 MainPage 類。

圖 3 OnNavigatedTo 和 OnNavigatingFrom 方法

protected override void OnNavigatedTo
  (System.Windows.Navigation.NavigationEventArgs e)
{
  if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true)
  {
    cam = new PhotoCamera(CameraType.Primary);
    cam.CaptureImageAvailable +=
      new EventHandler<Microsoft.Devices.ContentReadyEventArgs>
        (cam_CaptureImageAvailable);
    viewfinderBrush.SetSource(cam);
  }
  else
  {
    txtMessage.Text = "A Camera is not available on this device.";
  }
}
protected override void OnNavigatingFrom
  (System.Windows.Navigation.NavigatingCancelEventArgs e)
{
  if (cam != null)
  {
    cam.Dispose();
  }
}

當離開頁面時,可以使用 OnNavigatingFrom 方法處理相機物件並取消註冊任何相機事件。 這有助於將電能消耗降至最低、加快關機速度和釋放記憶體。

拍攝照片:如 XAML 中所示,在使用者點擊取景器之後,會調用 viewfinder_Tapped 方法。 此方法會在相機準備就緒時啟動圖像捕獲。 如果相機尚未初始化或者當前正在捕獲另一個圖像,則會引發異常。 為説明減少異常情況,請考慮禁用觸發照片拍攝的機制,直到觸發 Initialized 事件。 為簡便起見,在本示例中,我們將跳過這一步驟。

圖 4 顯示需要添加到 MainPage 類的代碼。

圖 4 viewfinder_Tapped 方法

void viewfinder_Tapped(object sender, GestureEventArgs e)
{
  if (cam != null)
  {
    try
    {
      cam.CaptureImage();
    }
    catch (Exception ex)
    {
      this.Dispatcher.BeginInvoke(delegate()
      {
        txtMessage.Text = ex.Message;
      });
    }
  }
}

拍攝照片和保存照片是非同步任務。 調用 CaptureImage 方法後,會啟動一系列事件並且控制權將傳遞回 UI。 如圖 5 中的事件序列圖所示,每個圖像捕獲過程都包含兩個階段。 首先,相機感測器拍攝照片,然後根據感測器資料創建圖像。

The Image-Capture Event Sequence of the PhotoCamera Class
圖 5 PhotoCamera 類的圖像捕獲事件序列

保存照片:在感測器拍攝照片後,會並行創建兩個影像檔:一個完整尺寸的影像檔和一個縮略圖。 您沒有必要使用這兩個檔。 每個檔均作為相應事件參數中 e.ImageStream 屬性中的 JPG 圖像流提供。

媒體庫會自動創建其自己的縮略圖,以便在設備的圖片中心中顯示,因此本示例不需要圖像的縮略圖版本。 但是,如果您希望在自己的應用程式中顯示縮略圖,Capture­ThumbnailAvailable 事件處理常式中的 e.ImageStream 將是一個有效的選擇。

當該圖像流可用時,您可以使用它將圖像保存到多個位置。 For example:

  • “本機照片”資料夾: Use the MediaLibrary.SavePictureToCameraRoll method.
  • “已保存圖片”資料夾:使用 MediaLibary.Save­-Picture 方法。
  • 獨立存儲:使用 IsolatedStorageFile­-Stream.Write 方法。

在本示例中,我們會將圖像保存到“本機照片”資料夾。 有關如何將圖像保存到獨立存儲的示例,請參閱 Windows Phone SDK 中的“基本相機示例”。 將圖 6 中的代碼添加到 MainPage 類。

圖 6 將圖像保存到“本機照片”資料夾

void cam_CaptureImageAvailable(object sender,
  Microsoft.Devices.ContentReadyEventArgs e)
{
  photoCounter++;
  string fileName = photoCounter + ".jpg";
  Deployment.Current.Dispatcher.BeginInvoke(delegate()
  {
    txtMessage.Text = "Captured image available, saving picture.";
  });
  library.SavePictureToCameraRoll(fileName, e.ImageStream);
  Deployment.Current.Dispatcher.BeginInvoke(delegate()
  {
    txtMessage.Text = "Picture has been saved to camera roll.";
  });
}

圖 6 中的代碼中,消息將在圖像保存到“本機照片”資料夾前後發送到 UI。 這些消息只用于説明您瞭解發生的情況;它們不是必需的。 將消息傳遞到 UI 執行緒需要使用 BeginInvoke 方法。 如果您未使用 BeginInvoke,則會引發跨執行緒異常。 為簡便起見,此方法不包含錯誤處理代碼。

處理旋轉:在將圖片保存到媒體庫時,將在檔的 EXIF 資訊中注明圖像的正確方向。 應用程式最關注的是如何在使用者介面中調整相機的預覽方向。 若要始終以正確的方向顯示預覽,可在適當的時候旋轉取景器 (VideoBrush)。 可以通過重寫 OnOrientationChanged 虛擬方法來實現旋轉。 將圖 7 中的代碼添加到 MainPage 類。

圖 7 重寫 OnOrientationChanged 虛擬方法

void cam_CaptureImageAvailable(object sender,
  Microsoft.Devices.ContentReadyEventArgs e)
{
  photoCounter++;
  string fileName = photoCounter + ".jpg";
  Deployment.Current.Dispatcher.BeginInvoke(delegate()
  {
    txtMessage.Text = "Captured image available, saving picture.";
  });
  library.SavePictureToCameraRoll(fileName, e.ImageStream);
  Deployment.Current.Dispatcher.BeginInvoke(delegate()
  {
    txtMessage.Text = "Picture has been saved to camera roll.";
  });
}
protected override void OnOrientationChanged
  (OrientationChangedEventArgs e)
{
  if (cam != null)
  {
    Dispatcher.BeginInvoke(() =>
    {
      double rotation = cam.Orientation;
      switch (this.Orientation)
      {
        case PageOrientation.LandscapeLeft:
          rotation = cam.Orientation - 90;
          break;
        case PageOrientation.LandscapeRight:
          rotation = cam.Orientation + 90;
          break;
      }
        viewfinderTransform.Rotation = rotation;
    });
  }
  base.OnOrientationChanged(e);
}

無需對取景器方向進行任何調整,只要硬體快門按鈕朝上 (LandscapeLeft),常用主相機的取景器就會以正確方向顯示。 如果您旋轉設備使得硬體快門按鈕朝下 (LandscapeRight),則取景器必須旋轉 180 度才能在使用者介面中正確顯示。 如果主相機的物理方向是非常規的,則此處會使用 PhotoCamera Orientation 屬性。

聲明應用程式功能:最後,當您的應用程式使用相機時,您必須在應用程式清單檔 (WMAppManifest.xml) 中聲明這一點。 無論使用哪個相機,您都會需要 ID_CAP_ISV_CAMERA 功能。 您還可以選擇使用 ID_HW_FRONTCAMERA 指定您的應用程式需要前置相機:

<Capability Name="ID_CAP_ISV_CAMERA"/>
<Capability Name="ID_HW_FRONTCAMERA"/>

如果沒有 ID_CAP_ISV_CAMERA 功能,您的相機應用程式將無法運行。 如果到目前為止一直都能正常運行程式,則是因為此功能已自動添加到新的 Windows Phone 專案中。 但是,如果您要升級您的應用程式,您將需要手動添加它。 必須始終手動添加 ID_HW_FRONTCAMERA,但缺少它不會阻止應用程式運行。

這些功能有助於對其設備上不具有相機功能的使用者加以警告,但不會阻止他們下載和購買您的應用程式。 因此,最好提供您的應用程式的試用版。 其次,如果使用者錯過警告,他們不會花了錢卻得知您的應用程式無法在其設備上按預期運行。 您將獲得好的應用程式評級。

如果您尚未做到這一點,請按 F5 並在您的設備上調試這一簡單的相機應用程式。 您可以在模擬器上調試該應用程式,但是,您只會看到一個黑色方框在螢幕上移動,因為模擬器不具有物理相機。 對設備進行調試時,請記住,在將設備從您的 PC 移除之前,您無法在圖片中心查看您的新圖像。

為深入瞭解,我們來看一看 Windows Phone SDK 中的“基本相機示例”。 該示例演示用於拍攝照片的完整 API:從調整閃光燈和解析度設置到合併觸控聚焦和硬體快門按鈕。

訪問相機預覽緩衝區

在前面的示例中,相機預覽緩衝區中的幀傳送到了取景器。 PhotoCamera 類還會公開預覽緩衝區的當前幀以允許對每個幀進行逐圖元操控。 讓我們看一個 Windows Phone SDK 中的示例,以便了解如何操控預覽緩衝區中的幀並將其顯示在使用者介面中的可寫點陣圖上。

PhotoCamera 類使用以下“get preview”方法公開預覽緩衝區的當前幀:

  • GetPreviewBufferArgb32:ARGB 格式的當前幀的整數陣列
  • GetPreviewBufferYCbCr:YCbCr 格式的當前幀的位元組陣列
  • GetPreviewBufferY:僅亮度平面的類似格式的位元組陣列

ARGB 是用於描述 Silverlight for Windows Phone 應用程式中的顏色的格式。 YCbCr 支援有效的影像處理功能,但 Silverlight 無法使用 YCbCr。 如果您希望在應用程式中操控 YCbCr 幀,則必須將該幀轉換為 ARGB 格式,之後才能顯示它。 有關這些格式和顏色轉換的詳細資訊,請參閱 MSDN 庫頁面的“Windows Phone 的相機顏色轉換(YCbCr 到 ARGB)”,網址為 wpdev.ms/colorconversion

Windows Phone SDK 中的“相機灰度示例”(參見圖 8)演示如何操控預覽緩衝區中的 ARGB 幀以及如何將這些幀幾乎即時地寫入可寫點陣圖圖像。 在此示例中,每個幀均由彩色轉換為灰度。 請注意,此示例旨在演示 ARGB 操控;如果您的應用程式只需要灰度,請考慮改用 GetPreviewBufferY 方法。

The Camera Grayscale Sample UI
圖 8 相機灰度示例的使用者介面

在 XAML 檔中,圖像標記用於承載相應的可寫點陣圖(使用者介面左下角的黑白圖像),如下所示:

<Image x:Name="MainImage"
       Width="320" Height="240"
       HorizontalAlignment="Left" VerticalAlignment="Bottom" 
       Margin="16,0,0,16"
       Stretch="Uniform"/>

當按下按鈕以啟用灰度轉換時,會創建一個新的執行緒來執行該過程;還會創建一個具有與預覽緩衝區相同尺寸的可寫點陣圖,並將此點陣圖指定為 Image 控制項的源:

wb = new WriteableBitmap(
        (int)cam.PreviewResolution.Width,
        (int)cam.PreviewResolution.Height);
this.MainImage.Source = wb;

該執行緒使用 PumpARGBFrames 方法執行其任務。 此處會使用一個名為 ARGBPx 的整數陣列來承載當前預覽緩衝區的快照。 陣列中的每個整數代表幀的一個圖元(ARGB 格式)。 創建的此陣列同樣具有與預覽緩衝區相同的尺寸:

int[] ARGBPx = new int[
    (int)cam.PreviewResolution.Width *
    (int)cam.PreviewResolution.Height];

當啟用示例的“灰度”功能時,該執行緒會將預覽緩衝區中的當前幀複製到 ARGBPx 陣列。 此處,phCam 是相機物件:

phCam.GetPreviewBufferArgb32(ARGBPx);

將緩衝區複製到陣列後,該執行緒將遍歷每個圖元並將其轉換為灰度(有關如何完成此操作的更多詳細資訊,請參見示例):

for (int i = 0; i < ARGBPx.Length; i++)
{
  ARGBPx[i] = ColorToGray(ARGBPx[i]);
}

最後,在處理下個幀之前,該執行緒將使用 BeginInvoke 方法更新使用者介面中的 WriteableBitmap。 CopyTo 方法使用 ARGBPx 陣列覆蓋 WriteableBitmap 圖元,而 Invalidate 方法強制 WriteableBitmap 重繪,如下所示:

Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
  // Copy to WriteableBitmap.
ARGBPx.CopyTo(wb.Pixels, 0);
  wb.Invalidate();
  pauseFramesEvent.Set();
});

WriteableBitmap 類支援多種創意目標。 現在,您可以將相機預覽緩衝區合併到您的使用者介面的視覺效果庫中。

錄製視頻

雖然您可以使用 PhotoCamera 類將預覽緩衝區資料流到使用者介面,但您無法使用它來錄製視頻。 因此,您將需要 System.Windows.Media 命名空間中的一些類。 在本文的最後一部分中,我們來看看 Windows Phone SDK 中的“錄影機示例”(參見圖 9),瞭解如何在獨立存儲中將視頻錄製為 MP4 檔。 您可以在 SDK 代碼示例頁上找到此示例。

The Video Recorder Sample UI
圖 9 錄影機示例使用者介面

視頻錄製的主類有:

  • CaptureDeviceConfiguration:用於檢查視訊擷取裝置的可用性
  • CaptureSource:用於開始和停止視頻錄製/預覽
  • VideoBrush:用於使用 CaptureSource 或 PhotoCamera 物件填充 Silverlight UI 控制項
  • FileSink:用於在 CaptureSource 物件運行時將視頻錄製到獨立存儲

在 XAML 檔中,Rectangle 控制項用於顯示相機取景器:

<Rectangle
  x:Name="viewfinderRectangle"
  Width="640"
  Height="480"
  HorizontalAlignment="Left"
  Canvas.Left="80"/>

但是,Rectangle 控制項並非顯示視頻所必需的。 您可以使用 Canvas 控制項,如第一個示例所示。 使用 Rectangle 控制項只是為了介紹顯示視頻的另一種方法。

在頁面級別,聲明瞭以下變數:

// Viewfinder for capturing video.
private VideoBrush videoRecorderBrush;
// Source and device for capturing video.
private CaptureSource captureSource;
private VideoCaptureDevice videoCaptureDevice;
// File details for storing the recording.       
private IsolatedStorageFileStream isoVideoFile;
private FileSink fileSink;
private string isoVideoFileName = "CameraMovie.mp4";

當使用者導航到頁面時,InitializeVideoRecorder 方法將啟動相機並將相機預覽發送到 Rectangle。 創建 captureSource 和 fileSink 物件後,InitializeVideoRecorder 方法將使用靜態 Capture­DeviceConfiguration 物件查找視頻設備。 如果沒有相機可用,videoCaptureDevice 將為 null:

videoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();

在 Windows Phone 7.5 中,相機是可選功能。 雖然相機在現在的設備中很常見,但最好還是在您的代碼中對其進行檢查。 如圖 10 所示,videoCaptureDevice 用於檢查是否存在相機。 如果有可用的相機,captureSource 將設置為名為 videoRecorderBrush 的 VideoBrush 的源,且 videoRecorderBrush 將用作名為 viewfinderRectangle 的 Rectangle 控制項的填充。 調用 captureSource 的 Start 方法後,相機開始向 Rectangle 發送視頻。

圖 10 顯示視頻預覽

// Initialize the camera if it exists on the device.
if (videoCaptureDevice != null)
{
  // Create the VideoBrush for the viewfinder.
videoRecorderBrush = new VideoBrush();
  videoRecorderBrush.SetSource(captureSource);
  // Display the viewfinder image on the rectangle.
viewfinderRectangle.Fill = videoRecorderBrush;
  // Start video capture and display it on the viewfinder.
captureSource.Start();
  // Set the button state and the message.
UpdateUI(ButtonState.Initialized, "Tap record to start recording...");
}
else
{
  // Disable buttons when the camera is not supported by the device.
UpdateUI(ButtonState.CameraNotSupported, "A camera is not supported on this device.");
}

在本示例中,名為 UpdateUI 的説明程式方法管理按鈕狀態並向使用者寫入消息。 有關更多詳細資訊,請參閱“錄影機示例”。

雖然 fileSink 物件已創建,但此時沒有錄製任何視頻。 應用程式的這種狀態稱為視頻“預覽”。若要錄製視頻,則需要在開始之前將 fileSink 連接到 captureSource。 換言之,您需要停止 captureSource,之後才能錄製視頻。

當使用者點擊“錄影機示例”中的錄製按鈕時,StartVideoRecorder 方法將啟動從預覽到錄製的轉換。 轉換的第一歩是停止 captureSource 並重新配置 fileSink:

// Connect fileSink to captureSource.
if (captureSource.VideoCaptureDevice != null
    && captureSource.State == CaptureState.Started)
{
  captureSource.Stop();
  // Connect the input and output of fileSink.
fileSink.CaptureSource = captureSource;
  fileSink.IsolatedStorageFileName = isoVideoFileName;
}

在您為 Silverlight 外掛程式開發了應用程式之後,雖然 CaptureSource 和 VideoBrush 類可能有些耳熟,但 FileSink 類是全新的。 FileSink 類為 Windows Phone 應用程式所獨有,它瞭解關於寫入獨立存儲的全部資訊;您只需提供檔案名稱即可。

重新配置 fileSink 後,StartVideoRecorder 方法將重新開機 captureSource 並更新使用者介面:

captureSource.Start();
// Set the button states and the message.
UpdateUI(ButtonState.Ready, "Ready to record.");

當使用者停止錄製,從錄製轉換為預覽時,需要在重新配置 fileSink 之前再次停止 captureSource,如圖 11 所示。

圖 11 從錄製轉換為預覽

// Stop recording.
if (captureSource.VideoCaptureDevice != null
&& captureSource.State == CaptureState.Started)
{
  captureSource.Stop();
  // Disconnect fileSink.
fileSink.CaptureSource = null;
  fileSink.IsolatedStorageFileName = null;
  // Set the button states and the message.
UpdateUI(ButtonState.NoChange, "Preparing viewfinder...");
  StartVideoPreview();
}

啟動視頻預覽邏輯隔離在另一方法中,以便啟用從視頻播放狀態(本文不對此進行介紹)到預覽的轉換。 儘管在此不對播放進行介紹,但請務必注意,在 Windows Phone 中一次只能運行一段視頻流。

“錄影機示例”具有兩個獨立的視頻流:

  1. captureSource g videoRecorderBrush g viewfinderRectangle(Rectangle 控制項)
  2. isoVideoFile g VideoPlayer(MediaElement 控制項)

因為一次只能運行一段視頻流,所以此示例為每段流提供了可在其他流運行之前調用的“dispose”方法。 在 DisposeVideoPlayer 和 Dispose­VideoRecorder 方法中,可以通過對各自的物件調用 Stop 方法(以及將 MediaElement 的源設置為 null)來停止流。 CaptureSource 和 MediaElement 物件實際上並不實現 IDisposable 介面。

此時,您可能在想“相機灰度示例”似乎同時運行了兩個視頻。 事實上,該應用程式中只有一段視頻流:從 PhotoCamera 物件到 VideoBrush 控制項的流。 灰度“視頻”實際上只是基於相機預覽緩衝區中單獨操控的幀以高速率重繪的點陣圖。

總結

相機 API 是 Windows Phone 7.5 的新增功能,它為新型應用程式開啟了希望之門,從而能夠以早期版本的作業系統無法實現的方式解決問題並進行娛樂。 本文介紹的只是 API 的幾個方面。 有關完整參考,請參閱 Windows Phone SDK 文檔中的“相機與照片”一節,網址為 wpdev.ms/cameraandphotos

Matt Stroshane 負責為 Windows Phone 團隊編寫開發人員文檔。他在 MSDN 庫中發表的其他文章主要涉及 SQL Server、SQL Azure 和 Visual Studio 等產品。在他不工作的時候,您可能會在西雅圖的大街上看見他正在為下一次馬拉松比賽進行訓練。請在 Twitter 上關注他:twitter.com/mattstroshane

衷心感謝以下技術專家對本文的審閱:Eric BennettNikhil DeoreAdam LydickJon Sheller