WPF에서 비디오 재생하는 두가지 방법 :: Media Player on WPF

WPF상에서 비디오를 재생하기 위해서 다음과 같은 2가지 객체를 이용 할 수 있습니다.

System.Window.Control.MediaElement System.Window.Media.MediaFlayer가 그것입니다.

동작 영상은 http://screencast.com/t/6IoXozpFL 을 참조.

( 프레임레이트가 낮은 것은 캡처링 때문이지 WPF성능상의 문제는 아닙니다. )


MediaPlayer를 사용할 때 주의해야 할 점은 이 클래스는 직접적인 시각 표현이 없으며 시각적 트리에
직접 추가할 수 없다는 점입니다.
비디오를 재생하려면 MediaPlayer를 가져온 다음 해당 표면을
VisualBrush
와 같은 시각적
트리에 추가해야 합니다.

기본적으로 MediaElement MediaPlayer 클래스의 상위 래퍼입니다.

n[#M_소스 코드 보기..|소스 코드 접기..|n

XAML 코드
[code]
<Window x:Class=”CoWorkVideoPlayer.Window1″
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
    Title=”CoWorkVideoPlayer” Height=”700″ Width=”640″>
    <Grid>
 <Grid x:Name=”mediaPlayerGrid” VerticalAlignment=”Top” Height=”300″>
 <Rectangle x:Name=”rec” HorizontalAlignment=”Stretch” Width=”Auto” Fill=”#FFFFEBEB” Stroke=”#FF000000″/>
 <StackPanel Margin=”5,0,0,5″  VerticalAlignment=”Top” Orientation=”Horizontal” HorizontalAlignment=”Center”>
 <TextBox Text=”System.Window.Media.MediaFlayer 영역입니다. ” x:Name=”tbmp” FontWeight=”SemiBold” Height=”25″ FontFamily=”Arial” FontSize=”11″ Foreground=”Black” Opacity=”0.6″ Background=”#FFFFFF”  />
 </StackPanel>
 </Grid>
 
 <Grid x:Name=”mediaElementGrid” VerticalAlignment=”Bottom”>
 <MediaElement x:Name=”me” HorizontalAlignment=”Stretch” VerticalAlignment=”Stretch” Width=”Auto” Height=”Auto”/>
 <StackPanel Margin=”5,0,0,5″  VerticalAlignment=”Top” Orientation=”Horizontal” HorizontalAlignment=”Center”>
 <TextBox Text=”System.Window.Control.MediaElement  영역입니다.”  x:Name=”tbme” FontWeight=”SemiBold” Height=”25″ FontFamily=”Arial” FontSize=”11″ Foreground=”Black” Opacity=”0.6″ Background=”#FFFFFF”  />
 </StackPanel>
        <StackPanel Margin=”5,0,0,5″  VerticalAlignment=”Bottom” Orientation=”Horizontal” HorizontalAlignment=”Center”>
  <TextBox Text=”D:\download\Apple.Seed.2004.XviD.DTS.CD2-WAF.avi” x:Name=”tb” FontWeight=”SemiBold” Height=”25″ FontFamily=”Arial” FontSize=”11″ Foreground=”Black” Opacity=”0.6″ Background=”#FFFFFF”  />
  <Button Margin=”5,0,0,0″ Width=”50″ Height=”25″ Content=”LOAD” Click=”OpenFIle” HorizontalAlignment=”Right” />
  <Button Margin=”5,0,0,0″ Width=”50″ Height=”25″ Content=”PLAY” Click=”Play” HorizontalAlignment=”Right” />
  <Button Margin=”5,0,0,0″ Width=”50″ Height=”25″ Content=”STOP” Click=”Stop” HorizontalAlignment=”Right”  />
  <Button Margin=”5,0,0,0″ Width=”50″ Height=”25″ Content=”PAUSE” Click=”Pause” HorizontalAlignment=”Right”  />
 </StackPanel>
 <StackPanel Margin=”5,0,0,35″  VerticalAlignment=”Bottom” Orientation=”Horizontal” HorizontalAlignment=”Center”>
  <Slider Cursor=”Hand” x:Name=”timeSlider” ValueChanged=”SeekToMediaPosition”/>
 </StackPanel>
 </Grid>
 
    </Grid>
</Window>
[/code]

C#코드
[code]
using System;
using System.Collections.Generic;
using System.Text;
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;
using System.Diagnostics;
using Microsoft.Win32;


namespace CoWorkVideoPlayer
{
    /// <summary>
    /// 본 코드는 System.Window.Control.MediaElement 와 System.Window.Media.MediaFlayer 를
    /// 동시에 WPF상에 올려 제어합니다.
    /// MediaPlayer를 사용할 때 가장 주의해야 할 부분은 이 클래스는 직접적인 시각 표현이 없으며
    /// 시각적 트리에 직접 추가할 수 없다는 점입니다. 비디오를 재생하려면 
    /// MediaPlayer를 가져온 다음 해당 표면을 VisualBrush와 같은 시각적 트리에 추가해야 합니다.
    /// 기본적으로 MediaElement는 MediaPlayer 클래스의 상위 래퍼입니다
    /// </summary>

    public partial class Window1 : System.Windows.Window
    {

        //MediaElement 는 xaml영역에 설정되어 있으며
        //MediaPlayer는 코드단에서 생성합니다.
        MediaPlayer mp = new MediaPlayer();
        Stopwatch stop = new Stopwatch();
        Image videoImage = new Image();

       
        Boolean nowPlay = false; //미디어 재생중인지여부
        TimeSpan timeSpan; //Pause한 시점의 위치값 저장

        public Window1()
        {
            //어플리케이션 윈도우 설정
            this.Background = new SolidColorBrush(Color.FromArgb(0, 34, 34, 34));
            this.Title = “WPF Video Player”;
            InitializeComponent();
            tbmp.Visibility = Visibility.Hidden;
            tbme.Visibility = Visibility.Hidden;

            //MediaElement의 경우 LoadedBehavior,UnloadedBehavior 를
            //Manual로하지않으면 미디어 제어를 할 수 없음
            me.LoadedBehavior = MediaState.Manual;
            me.UnloadedBehavior = MediaState.Manual;

            //MediaPlayer표현영역 Rectangle 설정
            rec.Stroke = new SolidColorBrush(Colors.Black);
            rec.Fill = new VisualBrush(videoImage);

            //Seeker 설정
            timeSlider.Width = 400.0D;
            timeSlider.IsEnabled = false;
            timeSlider.Visibility = Visibility.Hidden;

            //미디어가 오픈 이벤트 핸들러
            me.MediaOpened += new RoutedEventHandler(me_MediaOpened);

            tb.ToolTip = new TextBox().Text =”재생 할 미디어의 전체 경로를 입력 해 주세요”;
           
           
        }

        /// <summary>
        /// Load 버튼 클릭에 대한 이벤트로 텍스트박스의 파일을 읽어와 재생을 시작합니다.
        /// </summary>
        /// <param name=”sender”></param>
        /// <param name=”e”></param>
        private void Play(object sender, RoutedEventArgs e)
        {
           
            try
            {

                if (tb.Text.Length > 0)
                {
                    me.Stop();
                    mp.Stop();
                    timeSpan = new TimeSpan(0L);

                    me.Source = new Uri(tb.Text);
                    mp.Open(new Uri(tb.Text));

                    me.Play();
                    mp.Play();

                    tbmp.Visibility = Visibility.Visible;
                    tbme.Visibility = Visibility.Visible;
                    nowPlay = true;

                    stop.Start();
                    //Rendering 이벤트 핸들러를 설정합니다.
                    VisualTarget.Rendering += renda;
                }
                else
                {
                    MessageBox.Show(“재생 할 미디어의 전체 경로를 택스트 상자에 입력 해 주세요”);
                }
               
               
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
           

           
        }

        //미디어가 오픈되면 TimeSpan을 통해 전체 길이를 알 수 있다.
        void me_MediaOpened(object sender, RoutedEventArgs e)
        {
            if (me.NaturalDuration.HasTimeSpan)
            {
                timeSlider.Maximum = me.NaturalDuration.TimeSpan.TotalMilliseconds;
                System.Diagnostics.Debug.WriteLine(” timeSlider.Maximum : ” + timeSlider.Maximum);
                timeSlider.IsEnabled = true;
            }
        }

        //이벤트 발생시 WPF의 Image 영역에 이미지를 뿌립니다.
        private void renda(Object sender, EventArgs e)
        {
            try
            {
                RenderTargetBitmap rtb = new RenderTargetBitmap(mp.NaturalVideoWidth, mp.NaturalVideoHeight, 1 / 200, 1 / 200, PixelFormats.Pbgra32);
                DrawingVisual dv = new DrawingVisual();
                DrawingContext dc = dv.RenderOpen();
                dc.DrawVideo(mp, new Rect(0, 0, mp.NaturalVideoWidth, mp.NaturalVideoHeight));
                dc.Close();
                rtb.Render(dv);
                videoImage.Source = BitmapFrame.Create(rtb);

            }
            catch (Exception ee)
            {
                System.Diagnostics.Debug.WriteLine(ee.Message);
            }

        }

        private void Stop(object sender, RoutedEventArgs e)
        {
            try
            {
                me.Stop();
                mp.Stop();
                timeSlider.Value = 0.0D;
                timeSlider.IsEnabled = false;
                tbmp.Visibility = Visibility.Hidden;
                tbme.Visibility = Visibility.Hidden;
                nowPlay = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void Pause(object sender, RoutedEventArgs e)
        {
            try
            {
                if ( nowPlay)
                {
                    me.Pause();
                    mp.Pause();
                    timeSpan = me.Position;
                    nowPlay = false;
                }
                else
                {
                    me.Position = timeSpan;
                    mp.Position = timeSpan;
              
                    me.Play();
                    mp.Play();

                    nowPlay = true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void SeekToMediaPosition(object sender, RoutedEventArgs e)
        {
            int SliderValue = (int)timeSlider.Value;
            // Overloaded constructor takes the arguments days, hours, minutes, seconds, miniseconds.
            // Create a TimeSpan with miliseconds equal to the slider value.
            TimeSpan ts = new TimeSpan(0, 0, 0, 0, SliderValue);
            me.Position = ts;
            mp.Position = ts;
        }

        private void OpenFIle(object sender, RoutedEventArgs e)
        {
            // 파일 열기 다이얼로그 박스를 설정
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = “.avi”; // 기본 확장자
            dlg.Filter = “Video File (.avi)|*.avi|Video File (.wmv)|*.wmv|Video File (.mpg)|*.mpg|Video File (.mpeg)|*.mpeg”; // 확장 파일 필터


            // Show open file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process open file dialog box results
            if (result == true)
            {
                // Open document
                //string filename = dlg.FileName;
                tb.Text = dlg.FileName;
            }

        }

    }
}
[/code]

_M#]

본 코드를 작성 한 후 XP에서 테스트를 진행 했을 때 아래와 같은 현상을 발견 할 수 있었습니다.

OS

.Net Framework

Codec 설치여부

WMP 버전

Direct X

영상 표시 여부

Win XP sp2

3.0

X

9

9.0c

X

Win XP sp2

3.0

O

9

9.0c

X

Win XP sp2

3.0

X

11

9.0c

X

Win XP sp2

3.0

O

11

9.0c

O

Win XP sp2

3.5

O

10

9.0c

O


위 표로 미루어 보아 C#에서 제공하고 있는 MediaPlayer 클래스를 사용하기 위해서는 기본적으로

윈도우 미디어 플레이어 10이상과 플레이하고자 하는 동영상의 코덱이 필요합니다.

( 윈도우즈 Vista는 기본적으로 WMP 11 이 설치되어 있으므로 해당 코덱만 설치되어 있다면 영상이 표시됩니다.
MSDN 공식문서에도 WMP 10이상이 필요하다고 명시되어 있군요..)

1 Comment

Add Yours →

답글 남기기

This site uses Akismet to reduce spam. Learn how your comment data is processed.