vlc 视频局部放大【WPF版】

        最近做了一个项目,其中功能有二维、三维地图展示,视频、音频播放,视频解码同步音频等,项目过程中也遇到一些技术难题,但最终还是解决,我个人感觉最应该记录下来的就是视频局放大的功能。先上两张效果图:

vlc 视频局部放大【WPF版】_第1张图片

vlc 视频局部放大【WPF版】_第2张图片

        根据项目需求,需要对视频进行局部放大,便于对细节地方进行查看,视频播放控件采用的是xZune.Vlc.Wpf - .Net 4.5VlcMediaPlayer网上有开源的代码,因为需要对视频的音频输出端口进行设置,而不是通过默认的扬声器输出,设置音频设置端口为:

        this.videoPlayer.Initialize(libVlcPath, options);      

        libVlcPath为libvlc库文件夹路径;options为参数,包括音频输出设备(如:"-I", "dummy", "--avi-index=1", "--ignore-config", "--no-video-title", "--aout=directsound")

        视频局部放大主要参考网上有位朋友发的wpf图片局部放大的原理来实现,主要实现步骤如下:

        一、布局

 
        
            
            
            
                
            
        


        
        
            
                
            
            
            
        

 

        二、截图框的移动

 private void MoveRect_MouseMove(object sender, MouseEventArgs e)
        {
            // 鼠标按下时才移动
            if (e.LeftButton == MouseButtonState.Released) return;

            FrameworkElement element = sender as FrameworkElement;

            //计算鼠标在X轴的移动距离
            double deltaV = e.GetPosition(MoveRect).Y - MoveRect.Height / 2;
            //计算鼠标在Y轴的移动距离
            double deltaH = e.GetPosition(MoveRect).X - MoveRect.Width / 2; ;
            //得到图片Top新位置
            double newTop = deltaV + (double)MoveRect.GetValue(Canvas.TopProperty);
            //得到图片Left新位置
            double newLeft = deltaH + (double)MoveRect.GetValue(Canvas.LeftProperty);

            //边界的判断
            if (newLeft <= 0)
            {
                newLeft = 0;
            }

            //左侧图片框宽度 - 半透明矩形框宽度
            if (newLeft >= (this.SmallBox.Width - this.MoveRect.Width))
            {
                newLeft = this.SmallBox.Width - this.MoveRect.Width;
            }

            if (newTop <= 0)
            {
                newTop = 0;
            }

            //左侧图片框高度度 - 半透明矩形框高度度
            if (newTop >= this.SmallBox.Height - this.MoveRect.Height)
            {
                newTop = this.SmallBox.Height - this.MoveRect.Height;
            }
            MoveRect.SetValue(Canvas.TopProperty, newTop);
            MoveRect.SetValue(Canvas.LeftProperty, newLeft);

        }

 

         三、图片放大

          Timer事件刷新图片,30次/秒,肉眼看上去就是视频的效果啦

private void ImageTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate
            {
                if (videoPlayer.VideoSource != null)
                {
                    bigImg.Source = videoPlayer.VideoSource;
                    imageBrush.ImageSource = videoPlayer.VideoSource;

                    #region
                    //获取右侧大图框与透明矩形框的尺寸比率
                    double n = this.BigBox.Width / this.MoveRect.Width;

                    //获取半透明矩形框在左侧小图中的位置
                    double left = (double)this.MoveRect.GetValue(Canvas.LeftProperty);
                    double top = (double)this.MoveRect.GetValue(Canvas.TopProperty);

                    //计算和设置原图在右侧大图框中的Canvas.Left 和 Canvas.Top
                    bigImg.SetValue(Canvas.LeftProperty, -left * n);
                    bigImg.SetValue(Canvas.TopProperty, -top * n);
                    #endregion
                }
            }));
        }

 

完整的代码:

(布局)


    
        
        
            
            
            
        
        
            
            
        
        
            
            
        

        
        

        

        

        
    

    
        
            
            
            
        
        
        

        
            
            
        

        
            
            

            
            
            
            

            

            
            

            
        

        
        
            
            
            
                
            
        


        
        
            
                
            
            
            
        
    

 (功能代码)

using DevExpress.XtraEditors;
using NAudio.CoreAudioApi;
using QACDR.Common;
using QACDR.Common.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using xZune.Vlc.Wpf;

namespace QACDR.UI
{
    /// 
    /// VlcWpf.xaml 的交互逻辑
    /// 
    public partial class VlcWpf : UserControl
    {
        /// 
        /// VLC参数
        /// 
        private List baseVlcSettings;
        /// 
        /// vlclib路径
        /// 
        private string libVlcPath = "libvlc";
        ///音频设备            
        private MMDevice audioDevice;
        /// 
        /// 快进等级 1/2/3
        /// 
        private int rateLevel = 1;
        /// 
        /// 当前音量
        /// 
        private int currVolume = 0;
        /// 
        /// 是否静音
        /// 
        private bool bNoVoice = false;
        /// 
        /// 视频文件列表
        /// 
        private List videoList = new List();
        /// 
        /// 当前播放序号
        /// 
        private int currIndex = 0;
        /// 
        /// 图片质量
        /// 
        private int quality = 10;

        private System.Timers.Timer imageTimer = null;
        private ImageBrush imageBrush = new ImageBrush();

        public VlcWpf()
        {
            InitializeComponent();

            InitVlc();   // 初始化VLC

            EventPublisher.ChangeVolChEvent += EventPublisher_ChangeVolChEvent;
            EventPublisher.SearchDataEvent += EventPublisher_SearchDataEvent;
            videoPlayer.StateChanged += VideoPlayer_StateChanged;
            EventPublisher.ZoomVideoEvent += EventPublisher_ZoomVideoEvent;

            int interValue = 100;
            string str = ConfigurationManager.AppSettings["FreamCount"];
            if (!string.IsNullOrEmpty(str))
            {
                interValue = Convert.ToInt32(str);
            }

            string strQuality = ConfigurationManager.AppSettings["FreamCount"];
            if (!string.IsNullOrEmpty(strQuality))
                quality = Convert.ToInt32(strQuality);

            imageTimer = new System.Timers.Timer();
            imageTimer.Enabled = true;
            imageTimer.Interval = 30;
            imageTimer.Elapsed += ImageTimer_Elapsed;
            // 初始化时复制,避免内存增加
            SmallBox.Background = imageBrush;

            SmallBox.Visibility = Visibility.Hidden;
            MoveRect.Visibility = Visibility.Hidden;
            videoPlayer.Visibility = Visibility.Visible;
            bigImg.Visibility = Visibility.Hidden;

        }

        private void EventPublisher_ZoomVideoEvent(object sender, ZoomVideoEventArgs e)
        {
            if (e.IsZoom)
            {
                imageTimer.Start();
                SmallBox.Visibility = Visibility.Visible;
                MoveRect.Visibility = Visibility.Visible;
                BigBox.Visibility = Visibility.Visible;
                videoPlayer.Visibility = Visibility.Hidden;
                bigImg.Visibility = Visibility.Visible;
            }
            else
            {
                imageTimer.Stop();
                SmallBox.Visibility = Visibility.Hidden;
                MoveRect.Visibility = Visibility.Hidden;
                BigBox.Visibility = Visibility.Hidden;
                videoPlayer.Visibility = Visibility.Visible;
                bigImg.Visibility = Visibility.Hidden;
            }
        }

        private void ImageTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(delegate
            {
                if (videoPlayer.VideoSource != null)
                {
                    bigImg.Source = videoPlayer.VideoSource;
                    imageBrush.ImageSource = videoPlayer.VideoSource;

                    #region
                    //获取右侧大图框与透明矩形框的尺寸比率
                    double n = this.BigBox.Width / this.MoveRect.Width;

                    //获取半透明矩形框在左侧小图中的位置
                    double left = (double)this.MoveRect.GetValue(Canvas.LeftProperty);
                    double top = (double)this.MoveRect.GetValue(Canvas.TopProperty);

                    //计算和设置原图在右侧大图框中的Canvas.Left 和 Canvas.Top
                    bigImg.SetValue(Canvas.LeftProperty, -left * n);
                    bigImg.SetValue(Canvas.TopProperty, -top * n);
                    #endregion
                }
            }));
        }

        /// 
        /// 初始化VLC
        /// 
        private void InitVlc()
        {
            try
            {
                baseVlcSettings = new List { "-I", "dummy", "--avi-index=1", "--ignore-config", "--no-video-title", "--aout=directsound" };

                // 初始化:设置音频输出的默认通道
                bool bIsVlcInit = false;
                MMDeviceEnumerator dve = new MMDeviceEnumerator();
                MMDeviceCollection devices = dve.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);
                foreach (var device in devices)
                {
                    if (device.ID == Properties.Settings.Default.AudioDeviceID)
                    {
                        audioDevice = device;
                        List vlcSettings = new List(baseVlcSettings);
                        string[] temp_params = audioDevice.ID.Split('.');
                        vlcSettings.Add(string.Format("--directx-audio-device={0}", temp_params[temp_params.Length - 1]));
                        this.videoPlayer.Initialize(libVlcPath, vlcSettings.ToArray());

                        bIsVlcInit = true;
                        break;
                    }
                }

                if (bIsVlcInit == false)
                {
                    this.videoPlayer.Initialize(libVlcPath, baseVlcSettings.ToArray());
                }

                currVolume = 100;
                videoPlayer.Volume = 100;
                voiceSlider.Value = 100;
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        /// 
        /// 播放视频
        /// 
        /// 
        public void PlayVideo(VideoFileInfo videoInfo)
        {
            try
            {
                if (!File.Exists(videoInfo.path))
                {
                    MessageBox.Show("视频文件不存在!");
                    return;
                }

                videoPlayer.BeginStop(new Action(delegate
                {
                    while (videoPlayer.VlcMediaPlayer.Media != null)
                    {
                        videoPlayer.VlcMediaPlayer.Media = null;
                        Thread.Sleep(200);
                    } // 添加此段代码,修复连续播放视频时会死掉的现象

                    if (videoPlayer.State == xZune.Vlc.Interop.Media.MediaState.Stopped || videoPlayer.State == xZune.Vlc.Interop.Media.MediaState.NothingSpecial)
                    {
                        videoPlayer.LoadMedia(videoInfo.path);
                        videoPlayer.Play();
                    }
                }));

                // 获取当前播放的序号
                for (int i = 0; i < videoList.Count; i++)
                {
                    if (videoList[i].path == videoInfo.path && videoList[i].id == videoInfo.id)
                    {
                        currIndex = i;
                        break;
                    }
                }

                FileInfo fi = new FileInfo(videoInfo.path);
                this.Dispatcher.Invoke(new Action(delegate
                {
                    //lbTitle.Content = fi.Name;
                }));
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        /// 
        /// 设置VLC音频输出端口
        /// 
        /// 
        public void SelectAudioDevice(string[] options)
        {
            try
            {
                videoPlayer.BeginStop(new Action(delegate
                {
                    this.videoPlayer.Initialize(libVlcPath, options);
                }));
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        /// 
        /// 视频截图
        /// 
        public void Snapshot()
        {
            try
            {
                string path = AppDomain.CurrentDomain.BaseDirectory + "snapshot";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);

                string name = path + "\\" + DateTime.Now.ToFileTime() + ".png";
                videoPlayer.TakeSnapshot(name, SnapshotFormat.JPG, 30);
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        #region 控件事件

        private void VideoPlayer_StateChanged(object sender, xZune.Vlc.ObjectEventArgs e)
        {
            if (e.Value == xZune.Vlc.Interop.Media.MediaState.Ended)
            {
                if (currIndex + 1 < videoList.Count)
                {
                    // 播放下一视频
                    currIndex++;
                    PlayVideo(videoList[currIndex]);
                }
                else
                {
                    this.Dispatcher.Invoke(new Action(delegate
                    {
                        //lbTitle.Content = "播放完成。";
                    }));
                }

                //EventPublisher.PictureShowEvent(this, new PictureShowEventArgs() { StateShow = ShowEnum.Stop });
            }
            else if (e.Value == xZune.Vlc.Interop.Media.MediaState.Paused)
            {
            }
        }

        // 声道切换事件
        private void EventPublisher_ChangeVolChEvent(object sender, ChangeVolChEventArgs e)
        {
            if (e.CType != 2) return;  // 如果不是音频所发起的,则不执行
            //cbvChanel.Text = e.VolChStr;
        }

        // 查询数据
        private void EventPublisher_SearchDataEvent(object sender, SearchDataEventArgs e)
        {
            string cmdText = "select * from QACDR_VIDEO where operation_id > 0 " + e.Condition + " order by start_time asc";
            DataSet ds = SQLiteHelper.ExecuteDataSet(cmdText);
            if (ds == null || ds.Tables.Count <= 0 || ds.Tables[0].Rows.Count <= 0) return;

            videoList.Clear();
            foreach (DataRow row in ds.Tables[0].Rows)
            {
                VideoFileInfo video = new VideoFileInfo();
                video.id = Convert.ToInt32(row["id"]);
                video.operation_id = Convert.ToInt32(row["operation_id"]);
                video.machine_id = Convert.ToInt32(row["machine_id"]);
                video.path = row["path"].ToString();
                video.start_time = Convert.ToDateTime(row["start_time"]);
                video.import_time = Convert.ToDateTime(row["import_time"]);
                videoList.Add(video);
            }
        }

        // 声道
        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                //string str = cbvChanel.Text;
                //EventPublisher.PublishChangeVolChEvent(this, str, 1);
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        // 静音/取消静音
        private void Label_MouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                if (bNoVoice == true)
                {
                    currVolume = videoPlayer.Volume;
                    videoPlayer.Volume = 0;
                    System.Windows.Controls.Image img = new Image();
                    img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"Image\NoVoice.png"));
                    lbVoice.Content = img;
                    voiceSlider.IsEnabled = false;
                    bNoVoice = false;
                }
                else
                {
                    videoPlayer.Volume = currVolume;
                    System.Windows.Controls.Image img = new Image();
                    img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"Image\Voice.png"));
                    lbVoice.Content = img;
                    voiceSlider.IsEnabled = true;
                    bNoVoice = true;
                }
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        // 停止
        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                videoPlayer.BeginStop(new Action(delegate
                {
                    this.Dispatcher.Invoke(new Action(delegate
                    {
                        //lbTitle.Content = "播放完成。";
                    }));
                }));
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        // 快退
        private void VideoBack_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                float tp = videoPlayer.Position - (float)0.05;
                if (tp > 0)
                {
                    videoPlayer.Position = tp;
                }
                else
                {
                    videoPlayer.Position = 0;
                }
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        // 播放/暂停
        private void VideoPlay_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (videoPlayer.State == xZune.Vlc.Interop.Media.MediaState.Playing)
                {
                    System.Windows.Controls.Border boder = (System.Windows.Controls.Border)VideoPlay.Template.FindName("btnBoder", VideoPlay);
                    System.Windows.Controls.Image img = (System.Windows.Controls.Image)boder.FindName("img");
                    img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"Image\Play.png"));
                }
                else if (videoPlayer.State == xZune.Vlc.Interop.Media.MediaState.Paused)
                {
                    System.Windows.Controls.Border boder = (System.Windows.Controls.Border)VideoPlay.Template.FindName("btnBoder", VideoPlay);
                    System.Windows.Controls.Image img = (System.Windows.Controls.Image)boder.FindName("img");
                    img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"Image\Pause.png"));
                }

                videoPlayer.PauseOrResume();
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        // 快进
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (rateLevel == 1)
                {
                    rateLevel = 2;
                    videoPlayer.Rate = 3.0f;
                    //lpSpeed.Content = "播放速度:快进x1";
                }
                else if (rateLevel == 2)
                {
                    rateLevel = 3;
                    videoPlayer.Rate = 5.0f;
                    //lpSpeed.Content = "播放速度:快进x2";
                }
                else if (rateLevel == 3)
                {
                    rateLevel = 4;
                    videoPlayer.Rate = 7.0f;
                    //lpSpeed.Content = "播放速度:快进x3";
                }
                else if (rateLevel == 4)
                {
                    rateLevel = 1;
                    videoPlayer.Rate = 1;
                    //lpSpeed.Content = "播放速度:正常";
                }
            }
            catch (Exception ex)
            {
                Log4Allen.WriteLog(typeof(VlcWpf), ex);
            }
        }

        // 同步音频
        private void cbSync_Checked(object sender, RoutedEventArgs e)
        {
            if (Utils.Mode == SyncModeEnum.DDS)
            {
                XtraMessageBox.Show("正在进行DDS同步,视频同步音频。");
                return;
            }

            EventPublisher.PublishSetAudioSyncEvent(this, new SetAudioSyncEventArgs() { IsSync = true });
            Utils.Mode = SyncModeEnum.VIDEO;
        }

        private void cbSync_Unchecked(object sender, RoutedEventArgs e)
        {
            EventPublisher.PublishSetAudioSyncEvent(this, new SetAudioSyncEventArgs() { IsSync = false });
            Utils.Mode = SyncModeEnum.NONE;
        }
        #endregion

        private void MoveRect_MouseMove(object sender, MouseEventArgs e)
        {
            // 鼠标按下时才移动
            if (e.LeftButton == MouseButtonState.Released) return;

            FrameworkElement element = sender as FrameworkElement;

            //计算鼠标在X轴的移动距离
            double deltaV = e.GetPosition(MoveRect).Y - MoveRect.Height / 2;
            //计算鼠标在Y轴的移动距离
            double deltaH = e.GetPosition(MoveRect).X - MoveRect.Width / 2; ;
            //得到图片Top新位置
            double newTop = deltaV + (double)MoveRect.GetValue(Canvas.TopProperty);
            //得到图片Left新位置
            double newLeft = deltaH + (double)MoveRect.GetValue(Canvas.LeftProperty);

            //边界的判断
            if (newLeft <= 0)
            {
                newLeft = 0;
            }

            //左侧图片框宽度 - 半透明矩形框宽度
            if (newLeft >= (this.SmallBox.Width - this.MoveRect.Width))
            {
                newLeft = this.SmallBox.Width - this.MoveRect.Width;
            }

            if (newTop <= 0)
            {
                newTop = 0;
            }

            //左侧图片框高度度 - 半透明矩形框高度度
            if (newTop >= this.SmallBox.Height - this.MoveRect.Height)
            {
                newTop = this.SmallBox.Height - this.MoveRect.Height;
            }
            MoveRect.SetValue(Canvas.TopProperty, newTop);
            MoveRect.SetValue(Canvas.LeftProperty, newLeft);

        }

        public void ResizeCtrl()
        {
        }
    }
}

 

转载于:https://www.cnblogs.com/Jins/p/5639045.html

你可能感兴趣的:(vlc 视频局部放大【WPF版】)