• WPF中的使用视频流的两种方式


         WPF中的进行视频的播放有两种方式:一种是采用MediaElement+VisualBrush的方式;而另一种则是采用MediaPlayer+VideoDrawing的方式。考虑到MediaElement在处理视频时会将布局的Stretch和StretchDirect缩放视频窗口的内容以适应包容器,而MediaPlayer相反则不需要管理布局、焦点以及所有其他元素细节。所以后者相比前者有更高的效率。当然现代的处理器下是不会看到这两者的明显的区别的。不过笔者试了一下,在.Net Framework 3.5下对同一视频的两个窗口,会出现其中一个窗口的视频帧率不一样的情况,也就是说一个窗口的视频播放很平滑的,而另一个则以动画的形式出现,这可能是在3.5下为了实现同步,不得不使用剪帧技术造成的。不过我试着将同一个项目升级到.net Framework 4.0下,则不会出现此类现象,可见微软在4.0下做了不小的优化技术。正如微软在发布4.0所说的一样,其效率已经大大的改进了,一点儿不假。

        当然我个人建议在使用视频播放设计中,应该使用4.0框架,这样可以很高效地运行你开发的视频播放程序。这是闲话,现在言归正传,我在这个例子中使用了两种不同的方式来实现视频播放的控制,实现一些比较通行的视频编程框架。

    同样我们还是先来了解一下几个比较重要的类型

    MediaTimeline 

    一个 Timeline 对象,它控制媒体计时的方式,与动画时间线对象控制动画的方式相同。这个类型有一个很重要的方法CreateClock();它的签名如下:

    public MediaClock CreateClock();创建一个与 MediaTimeline 关联的新的 MediaClock

    MediaClock 

    通过 MediaTimeline 维护媒体的计时状态的类。 通过它我们可以同步MediaElement和MediaPlayer对象。以实现视频播放的控制。

    public ClockController Controller { get; }这个属性是对播放进行控制。

    VisualBrush 

    使用 Visual 绘制区域。

    public Visual Visual { get; set; }设置源对象。

    public Transform RelativeTransform { get; set; }获取或设置要使用相对坐标应用于画笔的变换。

    DrawingBrush 

    用 Drawing 绘制区域,其中可以包括形状、文本、视频、图像或其他绘图。

    方式一:MediaElement+VisualBrush

    步骤1:布置可视元素:这里为了实现的方便,我们在主窗体中放置了一个两行的Grid控件,第一行胜于按键控件的安装,第二行用于视频的播放和倒影窗口,相应的代码如下:

    代码

    <Window.Resources><MediaElement x:Key="video" Source="future_nasa.wmv" Stretch="Fill" LoadedBehavior="Manual"/></Window.Resources><Grid x:Name="LayoutRoot" Background="#FFC7DAE5"><Grid.RowDefinitions><RowDefinition Height="50"/><RowDefinition Height="1*"/><RowDefinition Height="1*"/></Grid.RowDefinitions><Border x:Name="orgin" BorderBrush="DarkGray" BorderThickness="1" Grid.Row="1" CornerRadius="2" ></Border><Border BorderBrush="Black" BorderThickness="1" Grid.Row="2" CornerRadius="2" Background="Black" ><Rectangle x:Name="reflector" VerticalAlignment="Stretch" Stretch="Fill" HorizontalAlignment="Stretch"></Rectangle></Border><Border x:Name="controls" BorderThickness="3" CornerRadius="3" ><Border.BorderBrush><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="#FF98BBD2" Offset="0"/><GradientStop Color="White" Offset="1"/><GradientStop Color="#FFBDD3E2" Offset="0.648"/><GradientStop Color="#FFD3E1EB" Offset="0.258"/></LinearGradientBrush></Border.BorderBrush><Rectangle><Rectangle.Fill><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="#CCFFFFFF" Offset="1"/><GradientStop Color="#33FFFFFF"/></LinearGradientBrush></Rectangle.Fill></Rectangle></Border><StackPanel Orientation="Horizontal" ><Button x:Name="tme" Content="Test MediaElement" Width="125" Height="30" Margin="50,0,20,0" Click="tme_Click"/><Button x:Name="tmp" Content="Test MediaPlayer" Width="125" Height="30" Margin="0,10" Click="tmp_Click"/><Button x:Name="start" Content="Start" Width="75" Height="30" Margin="20,10,0,10" Click="start_Click" /><Button x:Name="stop" Content="Stop" Width="75" Height="30" Margin="20,10,0,10" Click="stop_Click" /><Button x:Name="resume" Content="Resume" Width="75" Height="30" Margin="20,10,0,10" Click="resume_Click" /><Button x:Name="pause" Content="Pause" Width="75" Height="30" Margin="20,10,0,10" Click="pause_Click" /></StackPanel></Grid>

    步骤2:在代码文件的最前面声明了三个对象,以引用XAML声明的元素:

    复制代码
    //保存引用的元素

    private FrameworkElement reflectorElement;

    private FrameworkElement originElement;

    private MediaClock clock;

    复制代码

    步骤3:在后置代码中处理MediaElement对象,正如XAML声明式的代码中我们看到的那样,我们这儿将MediaElement对象声明成了一个资源,这样就可以以共享方式使用元素了。这儿先引用MediaElement对象,接着声明一个MediaClock对象。相应的代码如下:

    代码

    MediaElement mediaElement = Resources["video"] as MediaElement;//得到资源orgin.Child = mediaElement;mediaElement.Clock = clock;clock.Controller.Seek(new TimeSpan(0, 0, 0, 2), TimeSeekOrigin.BeginTime);//跳过固定的时间线

    步骤4:声明一个VisualBrush对象,并利用其RelativeTransform属性将视频倒置,形成倒影图像。

    VisualBrush brush = new VisualBrush();

    brush.Visual = mediaElement;//使用MediaElement对象

    brush.RelativeTransform = new ScaleTransform { ScaleY = -1, CenterY = 0.5 };//通过VisualBrush对象进行布局控制

    步骤5:实现蒙版效果,即设置OpacityMask的透明掩码。

    代码

    LinearGradientBrush maskBrush = new LinearGradientBrush { StartPoint = new Point(0, 0), EndPoint = new Point(0, 1) };GradientStop stopOne = new GradientStop { Color = Colors.Black, Offset = 0 };GradientStop stopTwo = new GradientStop { Color = Colors.Transparent, Offset = 0.875 };maskBrush.GradientStops.Add(stopOne);maskBrush.GradientStops.Add(stopTwo);//生成掩码的对象reflector.Fill = brush;reflector.OpacityMask = maskBrush;

     至此,我们就实现了VisualElement+VisualBrush的组合实现了视频的播放。

    方式二:MediaPlayer+DrawingBrush

    步骤1:采用方式一的布局格式,相应代码不变。

    步骤2:声明MediaPlayer对象以及时钟控制关。

    代码

    reflector.LayoutTransform = new ScaleTransform { ScaleY = -1, CenterY = 0.5 };//设置自己的布局LinearGradientBrush maskBrush = new LinearGradientBrush { StartPoint = new Point(0, 0), EndPoint = new Point(0, 1) };GradientStop stopOne = new GradientStop { Color = Colors.Black, Offset = 0.875 };GradientStop stopTwo = new GradientStop { Color = Colors.Transparent, Offset = 0 };maskBrush.GradientStops.Add(stopOne);maskBrush.GradientStops.Add(stopTwo);reflector.OpacityMask = maskBrush;//以下是联合VideoDrawing和MediaPlayer的设置MediaPlayer player = new MediaPlayer();//使用MediaPlayer对象player.Clock = clock;

    步骤3:定义一个VideoDrawing对象,并关联到MediaPlayer对象。

    代码

    VideoDrawing drawing = new VideoDrawing();drawing.Rect = new Rect(150, 0, 100, 100);drawing.Player = player;//将MediaPlayer赋给VideoDrawingDrawingBrush brush = new DrawingBrush(drawing);//得到使用的绘图画刷

    步骤4:关联到布局元素.

    代码

    Rectangle border = new Rectangle();border.Stretch = Stretch.Fill;orgin.Child = border;border.Fill = brush;orgin.Child = border;reflector.Fill = brush;clock.Controller.Stop();

    步骤5:现在我们可以利用MediaClock对象的Controller对象来实现播放的开始、停止等控制了。

    代码

    private void start_Click(object sender, RoutedEventArgs e){clock.Controller.Stop();clock.Controller.Begin();pause.IsEnabled =true ;resume.IsEnabled = false ;stop.IsEnabled = true ;start.IsEnabled = false;}private void stop_Click(object sender, RoutedEventArgs e){clock.Controller.Stop();start.IsEnabled = true;pause.IsEnabled = false;resume.IsEnabled = false;stop.IsEnabled = false;}private void resume_Click(object sender, RoutedEventArgs e){clock.Controller.Resume();start.IsEnabled = false;pause.IsEnabled = true ;resume.IsEnabled = true ;stop.IsEnabled = true ;}private void pause_Click(object sender, RoutedEventArgs e){clock.Controller.Pause();start.IsEnabled = false ;pause.IsEnabled = false;resume.IsEnabled = true ;stop.IsEnabled = false;}

    总结:上面的两种方式都很好地实现了视频的播放控制,通过关联到MediaTimeline时钟,我们可以控制其中的任何一种方式的实现,至于两者的效率方面,我觉得用MediaElement的方式使用更为方便,因为只需在XAML代码中简单声明即可使用,而MediaPlayer则需要相应的后置代码的配合,使用起来不如前者方便,由于其在效率方面略高,所以我们可以在效率和方便性两个方面权衡使用这两种方式。

    效果如下:

     转自:https://www.cnblogs.com/suyan010203/archive/2010/07/12/1776053.html

  • 相关阅读:
    通过HttpListener实现简单的Http服务
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    NHibernate初学六之关联多对多关系
    NHibernate初学五之关联一对多关系
    EXTJS 4.2 资料 跨域的问题
    EXTJS 4.2 资料 控件之Grid 那些事
    EXTJS 3.0 资料 控件之 GridPanel属性与方法大全
    EXTJS 3.0 资料 控件之 Toolbar 两行的用法
    EXTJS 3.0 资料 控件之 combo 用法
    EXTJS 4.2 资料 控件之 Store 用法
  • 原文地址:https://www.cnblogs.com/javalinux/p/14473105.html
Copyright © 2020-2023  润新知