信息
您所需的主题如下所示。但此主题未包含在此库中。

如何在 Windows Phone 8 的相机应用中录制视频

2014/6/18

适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

从 Windows Phone OS 7.1 开始,您可以以编程方式访问手机相机。除了拍摄照片之外,您还可以使用手机相机拍摄视频。本主题介绍如何创建录像机应用并演示如何拍摄、显示以及如何将视频存储在 Windows Phone 应用中。有关如何使用设备相机拍摄照片的信息,请参阅如何为 Windows Phone 8 创建基本相机应用

提示提示:

本主题介绍如何使用 System.Windows.Media.CaptureSourceFileSink 类录制视频。如果您的应用对相机传感器的控制要求比本主题所介绍的多,那么请考虑使用 AudioVideoCaptureDevice 类。有关更多信息,请参见 AudioVideoCaptureDevice

本主题与录像机示例相对应。

本主题涉及以下步骤:

  1. 创建应用和 UI

  2. 更新 UI

  3. 初始化相机

  4. 在预览和录制之间切换相机状态

  5. 处理按钮点按

  6. 处置录制和播放对象

  7. 完成应用

下图显示已完成的应用示例。

AP_Con_CameraVideoHowTo

在录制期间,该应用使用 FileSink 类传递 CaptureSource 对象中的视频并通过 IsolatedStorageFileStream 对象将其存储到独立存储。若要为应用提供相机取景器,也可以使用相同的 CaptureSource 作为 VideoBrush 控件的源。当 CaptureSource 连接到 FileSink 或将前者从后者中删除时,不能运行前者。如果在连接到 FileSink 时运行 CaptureSource,则会发生视频录制。

为了播放录制的视频,IsolatedStorageFileStream 对象读取录制的视频文件并将其作为 MediaElement 控件的源提供。有关如何实现该应用的更多信息,请参阅以下各节。

在本节中,您创建应用并为开发准备该应用。

说明注意:

当升级 Windows Phone OS 7.0 应用以使用 Windows Phone OS 7.1 中的功能时,相机功能 ID_CAP_ISV_CAMERA 不会自动添加到应用清单文件 WMAppManifest.xml 中。如果没有 ID_CAP_ISV_CAMERA,则使用相机 API 的应用将无法工作。在新的 Windows Phone OS 7.1 项目中,该功能包含在应用的清单文件中。

创建应用的步骤

  1. 若使用 Windows Phone SDK,则使用 Windows Phone 应用 模板创建新项目。

  2. 创建好应用后,在 Visual Studio 设计器窗口中打开 MainPage.xaml。

指定应用功能

  1. 若要创建相机应用,必须在应用清单文件中声明相机功能。由于视频应用还录制声音,因此还必须声明麦克风功能。如果不声明这些功能,此应用将无法使用。打开 WMAppManifest.xml 并确认其中存在以下功能元素。

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

    如果您的 Windows Phone 8 应用要求具有背面相机,则使用 ID_REQ_BACKCAMERA 硬件要求。这将防止用户在没有背面相机的情况下下载您的应用。有关功能和要求的更多信息,请参见 Windows Phone 8 应用功能和硬件要求

    重要说明重要说明:

    使用 CaptureSource 类的 Windows Phone OS 7.1 应用还必须使用 Microsoft.Devices.CameraMicrosoft.Devices.PhotoCameraMicrosoft.Xna.Framework.Audio.Microphone 类,以能够在应用中启用音频捕获和准确的功能检测。

    尽管此特定的应用不需要上述任何类,但 Windows Phone OS 7.1 应用仍需要包含其中一个类的代码,用来提示 Windows Phone 应用商店 功能检测过程在摄取时将 ID_CAP_MICROPHONE 功能添加到应用功能列表中。有关示例,请查看录像机示例中的 CapabilityPlaceholder 文件。

    从 Windows Phone 8 开始,指定麦克风功能足以访问手机的麦克风。

  2. (可选)如果您的应用功能要求具有前置相机,考虑将前置相机功能或硬件要求添加至应用清单文件中,具体取决于您的应用面向何种版本的 Windows Phone:

    • ID_HW_FRONTCAMERA:Windows Phone OS 7.1 应用可以使用该功能。通过该功能,没有前置相机的用户将被告知,您的应用的部分功能无法在其手机上使用,但他们仍可以选择下载它。

    • ID_REQ_FRONTCAMERA:Windows Phone 8 应用可以使用该硬件要求。借助此要求,不具有前置相机的用户将无法下载应用。

    有关功能和要求的更多信息,请参见 Windows Phone 8 应用功能和硬件要求

添加应用所使用的图标

  1. “解决方案资源管理器”中,右键单击项目,选择“添加”,然后选择“新建文件夹”

  2. 将新文件夹命名为 Icons

  3. “解决方案资源管理器”中,右键单击 Icons 文件夹,选择“添加”,然后选择“现有项”。这将打开“添加现有项”菜单,从中您可以选择应用使用的图标。

  4. “添加现有项”窗口中,导航到以下路径以选择这些图标。此步骤假定采用的是以默认方式安装的 Visual Studio。如果您将其安装在其他位置,则在相应的位置查找图标。

    C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons\dark

    从该文件夹中,选择以下图标:

    • appbar.feature.video.rest.png

    • appbar.stop.rest.png

    • appbar.transport.pause.rest.png

    • appbar.transport.play.rest.png

    这些图标是专门用深色背景设计的并且颜色为白色;在白色的“添加现有项”窗口背景上图标可能显示为空白。

  5. “解决方案资源管理器”中,右键单击每个图标并设置文件属性,以便将图标生成为“内容”,并始终复制到输出目录(“始终复制”)。

创建 UI

  1. MainPage.xaml 上,更新 phone:PhoneApplicationPage 元素,如以下代码中所示。

    SupportedOrientations="Landscape" Orientation="LandscapeLeft"
        shell:SystemTray.IsVisible="False"
    
    

    该代码隐藏系统托盘并且使应用保持横向。不能旋转 CaptureSource 对象中的视频;如果是面朝下拍摄的,则也是面朝下录制视频。

    说明注意:

    可以旋转 PhotoCamera 类中的图像。有关如何执行此操作的示例,请参阅如何为 Windows Phone 8 创建基本相机应用

  2. MainPage.xaml 中,将名为 LayoutRootGrid 替换为以下代码。

        <!--LayoutRoot is the root grid where all page content is placed-->
        <Canvas x:Name="LayoutRoot" Background="Transparent">
    
            <!--Camera viewfinder >-->
            <Rectangle 
                x:Name="viewfinderRectangle"
                Width="640" 
                Height="480" 
                HorizontalAlignment="Left" 
                Canvas.Left="80"/>
    
            <MediaElement 
                x:Name="VideoPlayer" 
                Width="640" 
                Height="480"
                AutoPlay="True" 
                RenderTransformOrigin="0.5, 0.5" 
                VerticalAlignment="Center" 
                HorizontalAlignment="Center" 
                Stretch="Fill"
                Canvas.Left="80"/>
    
            <!--Used for debugging >-->
            <TextBlock 
                Height="40" 
                HorizontalAlignment="Left" 
                Margin="100,428,0,0"
                Name="txtDebug" 
                VerticalAlignment="Top"
                Width="626"
                FontSize="24" 
                FontWeight="ExtraBold"/>
    
        </Canvas>
    
    

    该代码指定一个名为 viewfinderRectangleRectangle、一个名为 VideoPlayerMediaElement 和一个名为 txtDebugTextBlockviewfinderRectangle 用于显示 CaptureSource 对象中的视频图像,VideoPlayer 用于播放被存储到独立存储的录制的视频,txtDebug 用于交流应用状态。

  3. MainPage.xaml 的名为 LayoutRootGrid 下面添加以下代码。

        <phone:PhoneApplicationPage.ApplicationBar>
            <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" x:Name="PhoneAppBar" Opacity="0.0">
                <shell:ApplicationBarIconButton IconUri="/Icons/appbar.feature.video.rest.png" Text="record"  x:Name="StartRecording" Click="StartRecording_Click" />
                <shell:ApplicationBarIconButton IconUri="/Icons/appbar.stop.rest.png" Text="stop" x:Name="StopPlaybackRecording" Click="StopPlaybackRecording_Click"/>
                <shell:ApplicationBarIconButton IconUri="/Icons/appbar.transport.play.rest.png" Text="play" x:Name="StartPlayback" Click="StartPlayback_Click"  />
                <shell:ApplicationBarIconButton IconUri="/Icons/appbar.transport.pause.rest.png" Text="pause" x:Name="PausePlayback" Click="PausePlayback_Click"/>
            </shell:ApplicationBar>
        </phone:PhoneApplicationPage.ApplicationBar>
    
    

    该代码指定一个具有四个按钮的应用栏:recordstopplaypause。在该应用中,stop 按钮用于停止录制和播放。有关使用应用栏的更多信息,请参见 Windows Phone 的应用栏

准备代码隐藏文件

  1. 在主页的代码隐藏文件 MainPage.xaml.cs 中,向应用中添加以下指令。

    // Directives
    using System.ComponentModel;
    using System.Threading;
    using System.IO;
    using System.IO.IsolatedStorage;
    using Microsoft.Phone.Shell;
    using System.Windows.Navigation;
    using Microsoft.Devices;
    
    
  2. MainPage.xaml.cs 中,在 MainPage 构造函数上面添加以下变量。

    // 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";
    
    // For managing button and application state.
    private enum ButtonState { Initialized, Ready, Recording, Playback, Paused, NoChange, CameraNotSupported };
    private ButtonState currentAppState;
    
    

    该代码声明稍后在应用中使用的变量。

  3. MainPage.xaml.cs 中,向 MainPage 构造函数中添加以下代码,放在 InitializeComponent 调用的正下方。

    // Prepare ApplicationBar and buttons.
    PhoneAppBar = (ApplicationBar)ApplicationBar;
    PhoneAppBar.IsVisible = true;
    StartRecording = ((ApplicationBarIconButton)ApplicationBar.Buttons[0]);
    StopPlaybackRecording = ((ApplicationBarIconButton)ApplicationBar.Buttons[1]);
    StartPlayback = ((ApplicationBarIconButton)ApplicationBar.Buttons[2]);
    PausePlayback = ((ApplicationBarIconButton)ApplicationBar.Buttons[3]);
    
    

    在此代码中,指定了应用栏按钮,以便它们能够在代码中引用。有关应用栏的更多信息,请参见 Windows Phone 的应用栏

  4. MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
    
        // Initialize the video recorder.
        InitializeVideoRecorder();
    }
    
    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        // Dispose of camera and media objects.
        DisposeVideoPlayer();
        DisposeVideoRecorder();
    
        base.OnNavigatedFrom(e);
    }
    

    当导航离开页面时处置与相机相关的对象和事件处理程序,这一点非常重要。这有助于在未使用应用时释放内存。每次导航页面时,都需要启动录制操作工作线程和相机对象(如果这些对象未运行)。

为了提高该代码的可读性,使用一个枚举和方法通过应用的各种状态来管理应用栏按钮的可见性。方法 UpdateUI 也更新 txtDebug。通过提取单个方法调用的 UI 更新,应用的其他部分需要很少代码。

更新 UI

  • 在主页的代码隐藏文件 MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    // Update the buttons and text on the UI thread based on app state.
    private void UpdateUI(ButtonState currentButtonState, string statusMessage)
    {
        // Run code on the UI thread.
        Dispatcher.BeginInvoke(delegate
        {
    
            switch (currentButtonState)
            {
                // When the camera is not supported by the phone.
                case ButtonState.CameraNotSupported:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = false;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = false;
                    break;
    
                // First launch of the application, so no video is available.
                case ButtonState.Initialized:
                    StartRecording.IsEnabled = true;
                    StopPlaybackRecording.IsEnabled = false;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = false;
                    break;
    
                // Ready to record, so video is available for viewing.
                case ButtonState.Ready:
                    StartRecording.IsEnabled = true;
                    StopPlaybackRecording.IsEnabled = false;
                    StartPlayback.IsEnabled = true;
                    PausePlayback.IsEnabled = false;
                    break;
    
                // Video recording is in progress.
                case ButtonState.Recording:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = true;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = false;
                    break;
    
                // Video playback is in progress.
                case ButtonState.Playback:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = true;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = true;
                    break;
    
                // Video playback has been paused.
                case ButtonState.Paused:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = true;
                    StartPlayback.IsEnabled = true;
                    PausePlayback.IsEnabled = false;
                    break;
    
                default:
                    break;
            }
    
            // Display a message.
            txtDebug.Text = statusMessage;
    
            // Note the current application state.
            currentAppState = currentButtonState;
        });
    }
    
    

    该代码更新应用栏按钮和应用状态。它使用 BeginInvoke 方法以便可以在 UI 线程上执行语句。为了进一步简化代码,使用一个名为 ButtonState 的枚举来指定应用的状态。

在本节中,您初始化 CaptureSourceFileSink 对象,并且显示描述如何开始使用应用的消息。

初始化相机

  • 在主页的代码隐藏文件 MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    public void InitializeVideoRecorder()
    {
        if (captureSource == null)
        {
            // Create the VideoRecorder objects.
            captureSource = new CaptureSource();
            fileSink = new FileSink();
    
            videoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
    
            // Add eventhandlers for captureSource.
            captureSource.CaptureFailed += new EventHandler<ExceptionRoutedEventArgs>(OnCaptureFailed);
    
            // Initialize the camera if it exists on the phone.
            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 phone.
                UpdateUI(ButtonState.CameraNotSupported, "A camera is not supported on this phone.");
            }
        }
    }
    
    

    该代码每次导航应用时执行大量任务。尽管创建了 fileSink,但它未连接到 captureSource,直到用户想录制视频为止。在这之前,未将任何视频保存到本地文件夹。

    静态方法 GetDefaultVideoCaptureDevicecaptureSource 连接到手机上的主相机。若要提供相机取景器,将 captureSource 设置为用于填充 viewfinderRectangleVideoBrush 的源。直到 captureSource 启动,视频图像才会显示在取景器上。

    提示提示:

    如果手机支持多个相机,则使用 GetAvailableVideoCaptureDevices 方法来获得视频拍摄手机的集合。例如,某些手机可能具有一个前置相机,还有另一个位于手机背面的相机。还有可能手机没有相机。这种情况下,使用 CameraNotSupported 按钮状态来禁用应用栏按钮。

在本节中,您添加在预览和录制之间更改相机状态的代码。在本主题的上下文中,录制视频意味着正在将相机中的视频流式传输到本地文件夹中的某个文件。为此,将 fileSink 连接到 captureSource,然后在您希望保持在视频文件中的时间段内运行 captureSource。当 captureSource 未运行或 fileSink 未连接到 captureSource 时,视频将不会流式传输到本地文件夹中的文件。

在预览和录制之间切换相机状态

  • MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    // Set recording state: start recording.
    private void StartVideoRecording()
    {
        try
        {
            // 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;
            }
    
            // Begin recording.
            if (captureSource.VideoCaptureDevice != null
                && captureSource.State == CaptureState.Stopped)
            {
                captureSource.Start();
            }
    
            // Set the button states and the message.
            UpdateUI(ButtonState.Recording, "Recording...");
        }
    
        // If recording fails, display an error.
        catch (Exception e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ERROR: " + e.Message.ToString();
            });
        }
    }
    
    // Set the recording state: stop recording.
    private void StopVideoRecording()
    {
        try
        {
            // 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();
            }
        }
        // If stop fails, display an error.
        catch (Exception e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ERROR: " + e.Message.ToString();
            });
        }
    }
    
    // Set the recording state: display the video on the viewfinder.
    private void StartVideoPreview()
    {
        try
        {
            // Display the video on the viewfinder.
            if (captureSource.VideoCaptureDevice != null
            && captureSource.State == CaptureState.Stopped)
            {
                // Add captureSource to videoBrush.
                videoRecorderBrush.SetSource(captureSource);
    
                // Add videoBrush to the visual tree.
                viewfinderRectangle.Fill = videoRecorderBrush;
    
                captureSource.Start();
    
                // Set the button states and the message.
                UpdateUI(ButtonState.Ready, "Ready to record.");
            }
        }
        // If preview fails, display an error.
        catch (Exception e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ERROR: " + e.Message.ToString();
            });
        }
    }
    

    该代码更新相机的录制状态。StartVideoRecording 方法停止 captureSource,将 fileSink 连接到相机和本地文件夹,然后再次启动 captureSourceStopVideoRecording 方法停止 captureSource 并断开 fileSink 与相机和本地文件夹的连接。StartVideoPreview 方法将 captureSource 重新连接到取景器,然后启动它。

在本节中,您添加四个应用程序栏按钮的代码:“录制”“停止”“播放”“暂停”。为了避免通过点按两次重复调用这些方法,每个方法会立即禁用相应的按钮。

在应用 UI 中一次只能显示一个视频流。视频播放之前,视频预览控件已从可视化树中删除,在视频预览之前反之亦然。删除是由稍后在本主题中创建的方法 DisposeVideoPlayerDisposeVideoRecorder 执行。

处理按钮点按

  • MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    // Start the video recording.
    private void StartRecording_Click(object sender, EventArgs e)
    {
        // Avoid duplicate taps.
        StartRecording.IsEnabled = false;
    
        StartVideoRecording();
    }
    
    // Handle stop requests.
    private void StopPlaybackRecording_Click(object sender, EventArgs e)
    {
        // Avoid duplicate taps.
        StopPlaybackRecording.IsEnabled = false;
    
        // Stop during video recording.
        if (currentAppState == ButtonState.Recording)
        {
            StopVideoRecording();
    
            // Set the button state and the message.
            UpdateUI(ButtonState.NoChange, "Recording stopped.");
        }
    
        // Stop during video playback.
        else
        {
            // Remove playback objects.
            DisposeVideoPlayer();
    
            StartVideoPreview();
    
            // Set the button state and the message.
            UpdateUI(ButtonState.NoChange, "Playback stopped.");
        }
    }
    
    // Start video playback.
    private void StartPlayback_Click(object sender, EventArgs e)
    {
        // Avoid duplicate taps.
        StartPlayback.IsEnabled = false;
    
        // Start video playback when the file stream exists.
        if (isoVideoFile != null)
        {
            VideoPlayer.Play();
        }
        // Start the video for the first time.
        else
        {
            // Stop the capture source.
            captureSource.Stop();
    
            // Remove VideoBrush from the tree.
            viewfinderRectangle.Fill = null;
    
            // Create the file stream and attach it to the MediaElement.
            isoVideoFile = new IsolatedStorageFileStream(isoVideoFileName,
                                    FileMode.Open, FileAccess.Read,
                                    IsolatedStorageFile.GetUserStoreForApplication());
    
            VideoPlayer.SetSource(isoVideoFile);
    
            // Add an event handler for the end of playback.
            VideoPlayer.MediaEnded += new RoutedEventHandler(VideoPlayerMediaEnded);
    
            // Start video playback.
            VideoPlayer.Play();
        }
    
        // Set the button state and the message.
        UpdateUI(ButtonState.Playback, "Playback started.");
    }
    
    // Pause video playback.
    private void PausePlayback_Click(object sender, EventArgs e)
    {
        // Avoid duplicate taps.
        PausePlayback.IsEnabled = false;
    
        // If mediaElement exists, pause playback.
        if (VideoPlayer != null)
        {
            VideoPlayer.Pause();
        }
    
        // Set the button state and the message.
        UpdateUI(ButtonState.Paused, "Playback paused.");
    }
    
    
    

    该代码处理应用栏上的按钮点按。StartRecording_Click 方法通过调用 StartVideoRecording 方法开始录制。

    StopPlaybackRecording_Click 方法停止视频录制或视频播放,具体情况取决于应用的状态。在视频录制期间,该方法调用 StopVideoRecording 方法以断开 fileSinkcaptureSource 的连接。在视频播放期间,该方法处置视频播放对象并调用 StartVideoPreview 方法以在取景器上显示视频。

    StartPlayback_Click 方法停止 captureSource,然后将 VideoPlayer MediaElement 控件连接到本地文件夹中的视频文件 CameraMovie.mp4。当调用 VideoPlayerPlay 方法时,在屏幕上显示视频。当视频的播放结束时,MediaEnded 事件的事件处理程序确保该应用返回预览状态。

在本节中,您添加处置视频播放和视频录制对象的代码。在应用 UI 中一次只能运行一个视频流。这些方法用于停止一个流以便可以启动其他流。它们还删除相应对象的事件处理程序以便在不使用这些对象时帮助释放内存。

处置录制和播放对象

  • MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    private void DisposeVideoPlayer()
    {
        if (VideoPlayer != null)
        {
            // Stop the VideoPlayer MediaElement.
            VideoPlayer.Stop();
    
            // Remove playback objects.
            VideoPlayer.Source = null;
            isoVideoFile = null;
    
            // Remove the event handler.
            VideoPlayer.MediaEnded -= VideoPlayerMediaEnded;
        }
    }
    
    private void DisposeVideoRecorder()
    {
        if (captureSource != null)
        {
            // Stop captureSource if it is running.
            if (captureSource.VideoCaptureDevice != null
                && captureSource.State == CaptureState.Started)
            {
                captureSource.Stop();
            }
    
            // Remove the event handler for captureSource.
            captureSource.CaptureFailed -= OnCaptureFailed;
    
            // Remove the video recording objects.
            captureSource = null;
            videoCaptureDevice = null;
            fileSink = null;
            videoRecorderBrush = null;
        }
    }
    
    

    尽管这些对象都不实现 Dispose 方法,但将它们设置为等于 null 将允许垃圾收集器在需要时回收这些对象使用的内存。

在本节中,您添加剩余的代码并启动该应用。

完成应用

  1. MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

    // If recording fails, display an error message.
    private void OnCaptureFailed(object sender, ExceptionRoutedEventArgs e)
    {
        this.Dispatcher.BeginInvoke(delegate()
        {
            txtDebug.Text = "ERROR: " + e.ErrorException.Message.ToString();
        });
    }
    
    // Display the viewfinder when playback ends.
    public void VideoPlayerMediaEnded(object sender, RoutedEventArgs e)
    {
        // Remove the playback objects.
        DisposeVideoPlayer();
    
        StartVideoPreview();
    }
    
    

    该代码分别处理 CaptureSource 中的 CaptureFailed 事件以及 MediaPlayer 对象中的 MediaEnded 事件。

  2. 现在您已经完成了该应用。按 F5 开始调试并测试该应用。

显示: