Vlc.DotNet 视频画面拉伸满整个控件的方法

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
如果这篇文章有幸帮助到你,请不要吝啬你的赞。

发布了15 篇原创文章 · 获赞 2 · 访问量 4857

猜你喜欢

转载自blog.csdn.net/weixin_38138153/article/details/100674017
今日推荐