首页 > 其他分享 >在WPF中播放RTSP视频流

在WPF中播放RTSP视频流

时间:2023-01-28 14:23:24浏览次数:45  
标签:视频流 mediaPlayer RTSP MediaPlayer 300 caching new WPF

在WPF中可以使用LibVLCSharp.WPF、Vlc.DotNet.Wpf组件直接播放RTSP流,此外还可以通过LibVLCSharp + SkiaSharp的方式将VLC视频流通过WriteableBitmap的方式关联到Image对象。

1、LibVLCSharp.WPF

使用VideoView控件可以方便地播放RTSP视频流。该方法使用简单,但是不能很好的对RTSP流图像进行处理。

(1) 初始化LibVLCSharp

LibVLCSharp.Shared.Core.Initialize();

(2) 使用VideoView控件

<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <wpf:VideoView x:Name="VideoView"/>
</Grid>

(3) 初始化LibVLC对象

_libVlc = new LibVLC(true);
_mediaPlayer = new MediaPlayer(_libVlc)
{
    Volume = 0, //静音
    EnableHardwareDecoding = true //硬件加速
};
_mediaPlayer.EndReached += OnPlayerEndReached;
_mediaPlayer.Stopped += OnPlayerStopped;

VideoView.IsManipulationEnabled = true;
VideoView.IsEnabled = true;
VideoView.Loaded += (sender, args) =>
{
    VideoView.MediaPlayer = _mediaPlayer;
};

(4) Unloaded事件中销毁VLC对象

_mediaPlayer.Stop();
_mediaPlayer.Dispose();
_libVlc.Dispose();

(5) 播放RTSP

var options = new[]
{
    "file-caching=300",
    "live-capture-caching=300",
    "disc-caching-caching=300",
    "network-caching=333",
    "live-caching=300"
};
using (var media = new Media(_libVlc, new Uri(CameraPara.Url), options))
{
    VideoView.MediaPlayer.Play(media);
}

(6) 停止播放

if (VideoView.MediaPlayer.IsPlaying)
{
    VideoView.MediaPlayer.Stop();
}

2、Vlc.DotNet.Wpf

借助于VlcVideoSourceProvider类,可以将RTSP视频流经过处理后轻松绑定到Image对象。同时,通过改造VlcVideoSourceProvider类可以实现自由设置RTSP视频流的播放帧率(FPS)。

(1) 启用位图缓存

<UserControl.CacheMode>
    <BitmapCache/>
</UserControl.CacheMode>

(2)  初始化SourceProvider

_sourceProvider = new VlcVideoSourceProvider(Dispatcher);

_sourceProvider.CreatePlayer(_libDirectory, "--no-audio", "--rtsp-tcp");
_sourceProvider.MediaPlayer.Stopped += OnPlayerStopped;

VideoImage.SetBinding(Image.SourceProperty,
    new Binding(nameof(VlcVideoSourceProvider.VideoSource))
    {
        Source = _sourceProvider
    });

(3) 播放RTSP视频流

var options = new[]
{
    "file-caching=300",
    "live-capture-caching=300",
    "disc-caching-caching=300",
    "network-caching=333",
    "live-caching=300",
    HardDecoding ? "avcodec-hw=any" : "" //硬解码
};
_sourceProvider.MediaPlayer.Play(new Uri(CameraPara.Url), options);

(4) 停止播放

if (_sourceProvider.MediaPlayer.IsPlaying())
{
    _sourceProvider?.MediaPlayer?.Dispose();
    _sourceProvider?.Dispose();
    _sourceProvider = null;
}

3、LibVLCSharp + SkiaSharp

通过设置MediaPlayer的视频回调方法,在视频VideoLock回调中将视频图像拷贝至缓存中,然后在VideoDisplay回调中将缓存中的数据转换为SKImage绘制在Skia画布中,之后刷新关联的位图即可。

(1) 初始化LibVLCSharp

LibVLCSharp.Shared.Core.Initialize();

(2) 初始化LibVLC对象

_libVlc = new LibVLC(true);
_mediaPlayer = new MediaPlayer(_libVlc)
{
    Volume = 0, //静音
    EnableHardwareDecoding = true //硬件加速
};
_mediaPlayer.EndReached += OnPlayerEndReached;
_mediaPlayer.Stopped += OnPlayerStopped;

(3) Loaded事件中设置视频回调

_mediaPlayer.SetVideoFormatCallbacks(OnLibVLCVideoFormat, null);
_mediaPlayer.SetVideoCallbacks(OnLibVLCVideoLock, null, OnLibVLCVideoDisplay);

(4) Unloaded事件中销毁VLC对象

_mediaPlayer.Stop();
_mediaPlayer.Dispose();
_libVlc.Dispose();

(5) 视频回调处理

private uint OnLibVLCVideoFormat(ref IntPtr opaque, IntPtr chroma,
        ref uint width, ref uint height, ref uint pitches, ref uint lines)
    // ReSharper restore RedundantAssignment
{
    var bytes = Encoding.ASCII.GetBytes("RV32"); //I420, RV32, AVC1
    for (var i = 0; i < bytes.Length; i++)
    {
        Marshal.WriteByte(chroma, i, bytes[i]);
    }

    if (_mediaPlayer.Media is Media media)
    {
        foreach (MediaTrack track in media.Tracks)
        {
            if (track.TrackType == TrackType.Video)
            {
                var trackInfo = track.Data.Video;
                if (trackInfo.Width > 0 && trackInfo.Height > 0)
                {
                    width = trackInfo.Width;
                    height = trackInfo.Height;
                }

                break;
            }
        }
    }

    var pixelFormat = PixelFormats.Bgra32;
    pitches = (uint) (width * pixelFormat.BitsPerPixel) / 8;
    lines = height;

    _videoWidth = (int) width;
    _videoHeight = (int) height;

    _buffer = new byte[_videoWidth * _videoHeight * 4];
    _plane = Marshal.UnsafeAddrOfPinnedArrayElement(_buffer, 0);

    Dispatcher.Invoke(delegate
    {
        _bitmap = new WriteableBitmap(_videoWidth, _videoHeight, 96, 96, PixelFormats.Bgra32, null);
        _imageInfo = new SKImageInfo(_videoWidth, _videoHeight, SKColorType.Bgra8888);
        _surface = SKSurface.Create(
            new SKImageInfo(_videoWidth, _videoHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul),
            _bitmap.BackBuffer, _bitmap.BackBufferStride);
        _rect = new Int32Rect(0, 0, _videoWidth, _videoHeight);

        VideoImage.Source = _bitmap;
        VideoImage.Stretch = IsMainControl ? Stretch.Fill : Stretch.Uniform;
    });

    return 1;
}

private IntPtr OnLibVLCVideoLock(IntPtr opaque, IntPtr planes)
{
    IntPtr[] dataArray = {_plane};
    Marshal.Copy(dataArray, 0, planes, dataArray.Length);
    return IntPtr.Zero;
}

private void OnLibVLCVideoDisplay(IntPtr opaque, IntPtr picture)
{
    var image = SKImage.FromPixels(_imageInfo, _plane);
    _surface.Canvas.DrawImage(image, new SKPoint(0, 0));

    Dispatcher.Invoke(delegate
    {
        _bitmap.Lock();
        _bitmap.AddDirtyRect(_rect);
        _bitmap.Unlock();
    });
}

(6) 播放RTSP视频

var options = new[]
{
    "file-caching=300",
    "live-capture-caching=300",
    "disc-caching-caching=300",
    "network-caching=333",
    "live-caching=300"
};
using (var media = new Media(_libVlc, new Uri(CameraPara.Url), options))
{
    _mediaPlayer.Play(media);
}

(7) 停止播放

if (_mediaPlayer.IsPlaying)
{
    _mediaPlayer.Stop();
}

标签:视频流,mediaPlayer,RTSP,MediaPlayer,300,caching,new,WPF
From: https://www.cnblogs.com/xhubobo/p/17070223.html

相关文章

  • 界面组件DevExpress WPF v22.2 - Windows 11暗黑主题发布
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专......
  • WPF鼠标、键盘、拖拽事件、用行为封装事件
    WPF鼠标、键盘、拖拽事件、用行为封装事件本文主要介绍了WPF中常用的鼠标事件、键盘事件以及注意事项,同时使用一个案例讲解了拓展事件。除此之外,本文还讲述如何用行为(Behav......
  • WPF鼠标、键盘、拖拽事件、用行为封装事件
    WPF鼠标、键盘、拖拽事件、用行为封装事件本文主要介绍了WPF中常用的鼠标事件、键盘事件以及注意事项,同时使用一个案例讲解了拓展事件。除此之外,本文还讲述如何用行为(Beha......
  • C# WPF 报错 CS0103 当前上下文中不存在名称的解决方法
    使用WPF时有时会出现此错误 但是此部分是软件自动生成的,所以不可能出错,有时候重启VS就会好,但是也会遇到重启几次仍然报错的情况这个问题的解决方法是,在调试中打开,启动......
  • WPF的MVVM的数据驱动学习示例
    项目结构  界面数据绑定<Windowx:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="h......
  • WPF的APP生命周期以及全局异常捕获
    WPF的APP生命周期以及全局异常捕获APP生命周期wpf项目目录中有一个App.xaml.cs文件,该文件中App是一个partical类,与之对应的另一partical部分在App.g.i.cs文件中,该文件是......
  • WPF的APP生命周期以及全局异常捕获
    WPF的APP生命周期以及全局异常捕获APP生命周期wpf项目目录中有一个App.xaml.cs文件,该文件中App是一个partical类,与之对应的另一partical部分在App.g.i.cs文件中,该文件是在......
  • WPF-3D图形
    WPF-3D图形WPF的3D功能可以在不编写任何c#代码的情况下进行绘制,只需要使用xaml即可完成3D图形的渲染。本文主要讲述了WPF-3D中的关键概念,以及常用到的命中测试、2d控件如......
  • wpf 空间坐标系下,画一个立方体轮廓
    代码:publicpartialclassMainWindow:Window{publicMainWindow(){InitializeComponent();Worignpt=newPoi......
  • Vlc播放rtsp视频
    Vlc播放rtsp视频,网上的例子不少,我看后觉得有点不足的地方,就是他们没有设置播放rtsp视频时的参数,参数设置对播放网络视频是很重要的,如果设置不当,或不设置,可能你的程序就播放......