WPF中两种不同的视频流的使用

开发 后端
本文将为大家介绍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控件,第一行胜于按键控件的安装,第二行用于视频的播放和倒影窗口,相应的代码如下:

  1. <Window.Resources> 
  2. <MediaElement x:Key="video" Source="future_nasa.wmv" Stretch="Fill" LoadedBehavior="Manual"/> 
  3. </Window.Resources> 
  4. <Grid x:Name="LayoutRoot" Background="#FFC7DAE5"> 
  5. <Grid.RowDefinitions 
  6. ><RowDefinition Height="50"/> 
  7. <RowDefinition Height="1*"/> 
  8. <RowDefinition Height="1*"/> 
  9. </Grid.RowDefinitions> 
  10. <Border x:Name="orgin" BorderBrush="DarkGray" BorderThickness="1" Grid.Row="1" CornerRadius="2" > 
  11. </Border> 
  12. <Border BorderBrush="Black" BorderThickness="1" Grid.Row="2" CornerRadius="2" Background="Black" > 
  13. <Rectangle x:Name="reflector" VerticalAlignment="Stretch" Stretch="Fill" HorizontalAlignment="Stretch"> 
  14. </Rectangle> 
  15. </Border> 
  16. <Border x:Name="controls" BorderThickness="3" CornerRadius="3" > 
  17. <Border.BorderBrush> 
  18. <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
  19. <GradientStop Color="#FF98BBD2" Offset="0"/> 
  20. <GradientStop Color="White" Offset="1"/> 
  21. <GradientStop Color="#FFBDD3E2" Offset="0.648"/> 
  22. <GradientStop Color="#FFD3E1EB" Offset="0.258"/> 
  23. </LinearGradientBrush> 
  24. </Border.BorderBrush> 
  25. <Rectangle> 
  26. <Rectangle.Fill> 
  27. <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
  28. <GradientStop Color="#CCFFFFFF" Offset="1"/> 
  29. <GradientStop Color="#33FFFFFF"/> 
  30. </LinearGradientBrush> 
  31. </Rectangle.Fill> 
  32. </Rectangle> 
  33. </Border> 
  34. <StackPanel Orientation="Horizontal" > 
  35. <Button x:Name="tme" Content="Test MediaElement" Width="125" Height="30" Margin="50,0,20,0" Click="tme_Click"/> 
  36. <Button x:Name="tmp" Content="Test MediaPlayer" Width="125" Height="30" Margin="0,10" Click="tmp_Click"/> 
  37. <Button x:Name="start" Content="Start" Width="75" Height="30" Margin="20,10,0,10" Click="start_Click" /> 
  38. <Button x:Name="stop" Content="Stop" Width="75" Height="30" Margin="20,10,0,10" Click="stop_Click" /> 
  39. <Button x:Name="resume" Content="Resume" Width="75" Height="30" Margin="20,10,0,10" Click="resume_Click" /> 
  40. <Button x:Name="pause" Content="Pause" Width="75" Height="30" Margin="20,10,0,10" Click="pause_Click" /> 
  41. </StackPanel> 
  42. </Grid>  

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

  1. //保存引用的元素private FrameworkElement reflectorElement;
  2. private FrameworkElement originElement;
  3. private MediaClock clock;  

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

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

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

 
  1. VisualBrush brush = new VisualBrush();brush.Visual = mediaElement;  
  2. //使用MediaElement对象brush.RelativeTransform = new ScaleTransform { ScaleY = -1, CenterY = 0.5 };  
  3. //通过VisualBrush对象进行布局控制  

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

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

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

方式二:MediaPlayer+DrawingBrush

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

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

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

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

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

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

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

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

  1. private void start_Click(object sender, RoutedEventArgs e){clock.Controller.Stop();  
  2. clock.Controller.Begin();  
  3. pause.IsEnabled =true ;  
  4. resume.IsEnabled = false ;  
  5. stop.IsEnabled = true ;  
  6. start.IsEnabled = false;}
  7. private void stop_Click(object sender, RoutedEventArgs e){clock.Controller.Stop();  
  8. start.IsEnabled = true;
  9. pause.IsEnabled = false;
  10. resume.IsEnabled = false;
  11. stop.IsEnabled = false;  
  12. }  
  13. private void resume_Click(object sender, RoutedEventArgs e){clock.Controller.Resume();  
  14. start.IsEnabled = false;
  15. pause.IsEnabled = true ;  
  16. resume.IsEnabled = true ;
  17. stop.IsEnabled = true ;  
  18. }  
  19. private void pause_Click(object sender, RoutedEventArgs e){clock.Controller.Pause();  
  20. start.IsEnabled = false ;  
  21. pause.IsEnabled = false;  
  22. resume.IsEnabled = true ;
  23. stop.IsEnabled = false;}  

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

效果如下:

原文标题:WPF中的使用视频流的两种方式

链接:http://www.cnblogs.com/suyan010203/archive/2010/07/12/1776053.html

【编辑推荐】

  1. Visual Studio 2010截图曝光 以WPF开发UI
  2. 为WPF项目创建单元测试
  3. 详解Silverlight和WPF互相扩展
  4. 教你如何理解WPF中的Template类
  5. 详谈WPF开发中的数据虚拟化
责任编辑:彭凡 来源: 博客园
相关推荐

2023-03-29 13:06:36

2019-01-11 13:57:06

2010-03-16 15:23:32

java动态载入

2010-03-15 15:30:35

Python模块

2009-06-08 20:07:44

Eclipse中使用p

2015-04-30 08:00:05

数据中心多种操作系统

2010-07-15 14:38:55

Perl eval函数

2012-12-13 10:32:34

路由器线路输出

2024-10-14 08:35:29

2010-07-13 15:39:23

SQL Server

2009-06-29 18:11:40

JSP设计模式

2009-09-14 19:25:09

Ruby form

2010-01-19 14:08:29

路由交换一体机

2011-03-03 17:00:37

pure-ftpdchroot

2020-06-18 08:18:35

密码加密安全

2021-05-27 10:57:01

TCP定时器网络协议

2010-10-11 10:31:51

MySQL分区

2013-05-27 14:31:34

Hadoop 2.0

2022-01-17 09:01:41

Pythonnc文件Python基础

2010-07-02 10:28:41

虚拟化桌面虚拟化
点赞
收藏

51CTO技术栈公众号