이 페이지가 유용했습니까?
이 콘텐츠에 대한 여러분의 의견은 중요합니다. 의견을 알려주십시오.
추가 의견
1500자 남음
방법: Windows Phone용 카메라 응용프로그램에서 동영상 녹화

방법: Windows Phone용 카메라 응용프로그램에서 동영상 녹화

2012-02-09

Windows Phone OS 7.1 을 사용하면 단말기 카메라에 프로그래밍 방식으로 액세스할 수 있습니다. 단말기 카메라를 사용하여 사진뿐만 아니라 동영상도 촬영할 수 있습니다. 이 항목에서는 동영상 레코더 응용프로그램을 만드는 방법에 대해 설명하고, Windows Phone 응용프로그램에서 동영상을 촬영하고, 표시하고, 저장하는 방법을 보여 줍니다. 단말기 카메라를 사용한 사진 촬영 방법에 대한 자세한 내용은 방법: Windows Phone용 기본 카메라 응용프로그램 만들기를 참조하십시오.

참고참고:

이 항목은 동영상 레코더 샘플에 해당합니다. 전체 프로젝트를 다운로드하려면 Windows Phone용 코드 샘플을 참조하십시오.

이 항목에서는 다음 단계를 다룹니다.

  1. 응용프로그램 및 UI 만들기

  2. UI 업데이트

  3. 카메라 초기화

  4. 미리 보기와 녹화 간 카메라 상태 전환

  5. 버튼 탭 처리

  6. 녹화 및 재생 개체 삭제

  7. 응용프로그램 완성

다음 그림은 완성된 응용프로그램의 예를 보여 줍니다.

AP_Con_CameraVideoHowTo

녹화하는 동안 이 응용프로그램은 FileSink 클래스를 사용하여 CaptureSource 개체에서 동영상을 전달하고 이를 IsolatedStorageFileStream 개체를 통해 격리된 저장소에 저장합니다. 응용프로그램에 카메라 뷰파인더를 제공하기 위해서는 동일한 CaptureSourceVideoBrush 컨트롤에 대한 소스로도 사용됩니다. CaptureSourceFileSink에 연결되거나 그로부터 제거되면 실행할 수 없습니다. CaptureSourceFileSink에 연결되어 있는 동안 실행되면 동영상 녹화가 발생합니다.

녹화된 동영상 재생의 경우 IsolatedStorageFileStream 개체가 녹화된 동영상 파일을 읽어 MediaElement 컨트롤에 소스로 표시합니다. 이 응용프로그램의 구현 방법에 대한 자세한 내용은 다음 섹션을 참조하십시오.

이 섹션에서는 응용프로그램을 만들어 개발을 위해 준비합니다.

참고참고:

Windows Phone OS 7.1 의 기능을 사용하기 위해 Windows Phone OS 7.0 응용프로그램을 업그레이드하는 경우 카메라 기능 ID_CAP_ISV_CAMERA는 응용프로그램 매니페스트 파일 WMAppManifest.xml에 자동으로 추가되지 않습니다. ID_CAP_ISV_CAMERA가 없으면 카메라 API를 사용하는 응용프로그램이 작동하지 않습니다. 새 Windows Phone OS 7.1 프로젝트에서는 이 기능이 응용프로그램 매니페스트 파일에 포함되어 있습니다.

다음 절차의 단계는 Windows Phone용 Visual Studio 2010 Express에 적용됩니다. Visual Studio 2010 Professional 또는 Visual Studio 2010 Ultimate용 추가 기능을 사용하는 경우에는 메뉴 명령이나 창 레이아웃에서 일부 소규모 변형이 나타날 수 있습니다.  

응용프로그램을 만들려면

  1. Windows Phone용 Visual Studio 2010 Express 에서 파일 | 새 프로젝트 메뉴 명령을 선택하여 새 프로젝트를 만듭니다.

  2. 새 프로젝트 창이 표시됩니다. Visual C# 템플릿을 확장하고 Windows Phone용 Silverlight 템플릿을 선택합니다.

  3. Windows Phone 응용프로그램 템플릿을 선택합니다. 이름 상자에 선택한 이름을 입력합니다.

  4. 확인을 클릭합니다. 새 Windows Phone 응용프로그램 창이 표시됩니다.

  5. 대상 Windows Phone 버전 메뉴에서 Windows Phone 7.1 이 선택되었는지 확인합니다.

  6. 확인을 클릭합니다. 새 프로젝트가 생성되고 MainPage.xaml이 Visual Studio 디자이너 창에서 열립니다.

응용프로그램 기능을 지정하려면

  1. 카메라 응용프로그램을 만들려면 응용프로그램 매니페스트 파일에서 카메라 기능을 선언해야 합니다. 동영상 응용프로그램에서 소리도 녹음하므로 마이크 기능도 선언해야 합니다. 이 기능을 선언하지 않으면 응용프로그램이 작동하지 않습니다. WMAppManifest.xml을 열고 다음 기능 요소가 있는지 확인합니다.

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

    중요중요:

    CaptureSource 클래스를 사용하는 Windows Phone 응용프로그램에서는 Microsoft.Devices.Camera, Microsoft.Devices.PhotoCamera 또는 Microsoft.Xna.Framework.Audio.Microphone 클래스도 사용하여 응용프로그램에서 오디오 캡처 및 정확한 기능 검색을 지원해야 합니다.

    해당 응용프로그램에서 이 클래스를 필요로 하지 않더라도, 마켓플레이스 기능 검색 프로세스에서 수집 시 응용프로그램 기능 목록에 ID_CAP_MICROPHONE 기능을 추가하라는 메시지를 표시하려면 이 클래스 중 하나를 포함하는 코드가 필요합니다. 예제는 Windows Phone용 코드 샘플에서 비디오 레코더 샘플CapabilityPlaceholder 파일을 참조하십시오.

  2. (선택 사항) 응용프로그램에 전면을 향하는 카메라가 필요하게 하려는 경우 응용프로그램 매니페스트 파일의 Capabilities 요소에 전면을 향하는 카메라 기능을 더 추가합니다.

    <Capability Name="ID_HW_FRONTCAMERA"/>
    

    이 기능은 새 프로젝트에 자동으로 추가되지 않으므로 수동으로 추가해야 합니다. 전면을 향하는 카메라가 없는 사용자에게는 단말기가 응용프로그램의 요구 사항을 충족하지 않는다는 알림이 표시되지만 사용자가 기능을 다운로드하도록 선택할 수 있습니다. 이 응용프로그램에서 구체적으로 전면을 향하는 카메라를 사용하지는 않습니다. 이 기능이 응용프로그램에 필요한 것은 아닙니다. 자세한 내용은 Windows Phone의 카메라 및 사진 개요기능 단원을 참조하십시오.

응용프로그램에서 사용되는 아이콘을 추가하려면

  1. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 추가, 새 폴더를 차례로 선택합니다.

  2. 새 폴더의 이름을 아이콘으로 지정합니다.

  3. 솔루션 탐색기에서 아이콘 폴더를 마우스 오른쪽 버튼으로 클릭하고 추가, 기존 항목을 선택합니다. 응용프로그램에서 사용되는 아이콘을 선택할 수 있는 기존 항목 추가 메뉴가 열립니다.

  4. 기존 항목 추가 창에서 다음 경로 중 하나로 이동하여 아이콘을 선택합니다. 이 단계에서는 Visual Studio가 기본 위치에 설치되어 있다고 가정합니다. 다른 위치에 설치한 경우 해당 위치에서 아이콘을 찾습니다.

    • 64비트 운영 체제: C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Icons\dark

    • 32비트 운영 체제: C:\Program Files\Microsoft SDKs\Windows Phone\v7.1\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용 기본 카메라 응용프로그램 만들기를 참조하십시오.

  2. MainPage.xaml에서 LayoutRoot라는 Grid를 다음 코드로 바꿉니다.

        <!--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>
    
    

    이 코드는 viewfinderRectangle이라는 Rectangle, VideoPlayer라는 MediaElement, txtDebug라는 TextBlock을 지정합니다. viewfinderRectangleCaptureSource 개체로부터 동영상 이미지를 표시하는 데 사용되고, VideoPlayer는 녹화된 동영상이 격리된 저장소에 저장된 후 이를 재생하는 데 사용되며, txtDebug는 응용프로그램 상태를 전달하는 데 사용됩니다.

  3. MainPage.xaml에서 LayoutRoot라는 Grid 아래에 다음 코드를 추가합니다.

        <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>
    
    

    이 코드는 record, stop, playpause라는 4개의 버튼이 있는 응용프로그램 모음을 지정합니다. 이 응용프로그램에서 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 device.
                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;
        });
    }
    
    

    이 코드는 응용프로그램 모음 버튼 및 응용프로그램 상태를 업데이트합니다. 이 코드는 UI 스레드에서 문을 실행할 수 있도록 BeginInvoke 메서드를 사용합니다. 코드를 더 단순화하기 위해, 응용프로그램의 상태를 지정하는 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 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.");
            }
        }
    }
    
    

    이 코드는 응용프로그램이 탐색될 때마다 다수의 작업을 수행합니다. fileSink가 만들어지더라도 사용자가 동영상을 녹화하기 전에는 captureSource에 연결되지 않습니다. 그때까지 격리된 저장소에 어떠한 동영상도 저장되지 않습니다.

    정적 메서드 GetDefaultVideoCaptureDevicecaptureSource를 단말기의 기본 카메라에 연결합니다. 카메라 뷰파인더를 제공하기 위해, captureSourceviewfinderRectangle을 채우는 데 사용되는 VideoBrush의 소스로 설정됩니다. 동영상 이미지가 뷰파인드에 표시되려면 captureSource가 시작되어야 합니다.

    팁팁:

    단말기가 다중 카메라를 지원하지 않으면 GetAvailableVideoCaptureDevices 메서드를 사용하여 동영상 캡처 단말기 컬렉션을 가져옵니다. 예를 들어 어떤 단말기는 정면에 카메라가 있고 어떤 단말기는 뒷면에 카메라가 있습니다. 또는 단말기에 카메라가 없는 경우도 있습니다. 그런 경우 응용프로그램 모음 버튼을 비활성화하는 데 CameraNotSupported 버튼 상태가 사용됩니다.

이 섹션에서는 카메라 상태를 미리 보기와 녹화 간에 변경하는 코드를 추가합니다. 이 항목 컨텍스트에서는 동영상 녹화가 카메라에서 격리된 저장소의 파일에 동영상을 스트리밍하는 것을 의미합니다. 이를 위해서는 fileSinkcaptureSource에 연결한 다음 동영상 파일에서 지속되도록 할 시간 동안 captureSource를 실행합니다. captureSource가 실행되고 있지 않거나 fileSinkcaptureSource에 연결되어 있지 않으면 동영상은 격리된 저장소의 파일에 스트리밍되지 않습니다.

미리 보기와 녹화 간에 카메라 상태를 전환하려면

  • 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를 카메라 및 격리된 저장소에 연결한 다음 captureSource를 다시 시작합니다. StopVideoRecording 메서드는 captureSource를 중지하고 카메라 및 격리된 저장소에서 fileSink를 분리합니다. StartVideoPreview 메서드는 captureSource를 뷰파인더에 다시 연결한 다음 이를 시작합니다.

이 섹션에서는 4개의 응용프로그램 모음 버튼 record, stop, playpause에 대한 코드를 추가합니다. 두 번 탭으로 이러한 메서드를 중복 호출하지 않기 위해, 각 메서드는 해당 버튼을 즉시 비활성화합니다.

한 번에 하나의 동영상 스트림만 응용프로그램 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 메서드를 호출하여 captureSource에서 fileSink를 분리합니다. 동영상을 재생하는 동안 이 메서드는 동영상 재생 개체를 삭제하고 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 키를 눌러 디버깅을 시작하고 응용프로그램을 테스트합니다.

표시:
© 2015 Microsoft