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
如果這篇文章有幸幫助到你,請不要吝嗇你的贊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章