Vlc.DotNet 视频画面拉伸满整个控件的方法
引用Vlc.DotNet
根据官方的例子,首先下载VLC,把VLC里面的各种dll拷贝到输出目录里面,然后安装Nuget包Vlc.DotNet.Core.Interops ,Vlc.DotNet.Core,根据程序的类型选择用Vlc.DotNet.Forms还是Vlc.DotNet.Wpf。具体教程网上有很多例子。相信各位搜索到这个问题也是把环境已经搭好了。
实现代码
这里我的程序用的是Wpf,直接上效果。
xaml代码如下
基本上和官方的示例代码一样
<Window x:Class="VLCTest.DemoWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf"
xmlns:local="clr-namespace:VLCTest"
mc:Ignorable="d"
Title="DemoWin" Height="450" Width="800">
<Grid>
<ContentControl Width="400" Height="400" Name="Container">
<wpf:VlcControl x:Name="VlcControl" />
</ContentControl>
<Button Content="Stop" HorizontalAlignment="Left" Margin="664,360,0,0" VerticalAlignment="Top" Width="75" Click="StopPlay"/>
</Grid>
</Window>
播放代码如下
private void Play()
{
string path = @"D:\TestFiles\TestVideo.mp4";
string currentDirectory = Directory.GetCurrentDirectory();
DirectoryInfo vlcDirectory = new DirectoryInfo(System.IO.Path.Combine(currentDirectory, "VLC"));
VlcControl.SourceProvider.CreatePlayer(vlcDirectory);
FileInfo playFile = new FileInfo(path);
// 这里把帧图像拉伸成填满整个控件
var viewBox = VlcControl.Content as Viewbox;
viewBox.Stretch = System.Windows.Media.Stretch.Fill;
VlcControl.SourceProvider.MediaPlayer.Play(playFile);
}
这里可以看到,只要把控件里面的ViewBox拉伸模式改成Fill填满整个控件即可。
实现思路
这里先要感谢这位大佬的文章为我提供了思路。
参考:https://my.oschina.net/duoing/blog/1499664
要实现视频画面填满整个控件的效果,其实就是要吧视频的输出横纵比改变。这里有两种思路:
1.视频流渲染成画面的时侯就按一定的横纵比渲染然后缩放。这就需要在调用VLC时通过参数或者调用改变横纵比的方法实现。
2.拿到渲染的每一帧画面后,在呈现到界面之前,对画面进行缩放调整横纵比然后再输出到画面上。这中方案就要靠界面程序来实现,靠也就是我们自己写的程序对每一帧画面再加工一次然后输出。
以上代码采用的是第二种方案。
方案对比
第一种方案明显比第二种方案更节约性能,因为它在源头就把帧画面渲染好了。第二种方案虽然多了一个拉伸画面的操作,但是它不需要深入地了解VLC内部的实现机制。总的来说,第二种方案其实属于取巧的方案,遇到多区域播放或者播放高分辨率视频的时候可能还是会有卡顿。
踩坑记录
一开始决定自己拉伸帧画面的时候,我的第一想法就先看看Vlc.dotnet.Wpf 源码中VlcControl 这个控件是怎么实现的,结果一看发现代码不多,才几十行。虽然说是几十行,但还是十分硬核,作者把帧渲染和呈现完全分离开,在控件里就只负责把拿到的画面丢到Image里面,然后绑定渲染源,每变化一帧就改变画面。
部分源码
/// <summary>
/// The constructor
/// </summary>
public VlcControl()
{
sourceProvider = new VlcVideoSourceProvider(this.Dispatcher);
this.viewBox = new Viewbox
{
Child = this.videoContent,
Stretch = Stretch.Uniform
};
this.Content = this.viewBox;
this.Background = Brushes.Black;
// Binds the VideoSource to the Image.Source property
this.videoContent.SetBinding(Image.SourceProperty, new Binding(nameof(VlcVideoSourceProvider.VideoSource)) { Source = sourceProvider });
}
刚刚好这里的VlcControl是继承于UserControl控件,里面的Content就是ViewBox,把ViewBox的拉伸模式改成Fill就刚好能实现效果。
最后感谢一下Vlc.dotnet 作者的良好设计和开源精神,站在巨人的肩膀上我们才看得更远。
Vlc.dotnet 源码:https://github.com/ZeBobo5/Vlc.DotNet/tree/develop/src
如果这篇文章有幸帮助到你,请不要吝啬你的赞。