1 Star 0 Fork 11

云之梦歌 / CPF.Vlc

forked from csharpui / CPF.Vlc 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
VideoView .cs 9.93 KB
一键复制 编辑 原始数据 按行查看 历史
小红帽 提交于 2023-11-22 23:59 . 初始化
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using CPF.Controls;
using CPF.Drawing;
using LibVLCSharp.Shared;
using CPF.Reflection;
namespace CPF.Controls
{
/// <summary>
/// vlc视频播放器
/// </summary>
public class VideoView : Control
{
/// <summary>
/// MediaPlayer property for this VideoView
/// </summary>
[NotCpfProperty]
[Browsable(false)]
public MediaPlayer MediaPlayer
{
get;
set;
}
static LibVLC libVLC;
[Browsable(false)]
public static LibVLC LibVLC
{
get
{
if (libVLC == null)
{
Core.Initialize();
libVLC = new LibVLC();
}
return libVLC;
}
}
IntPtr m_videoBuffer;
uint m_videoWidth = 640;
uint m_videoHeight = 360;
PixelSize? newSize;
//object m_lockObj = new object();
/// <summary>
/// 视频渲染尺寸,下次播放视频时生效。如果不设置则是自动尺寸
/// </summary>
[Description("视频渲染尺寸,下次播放视频时生效。如果不设置则是自动尺寸")]
public PixelSize VideoRenderSize
{
get { return GetValue<PixelSize>(); }
set { SetValue(value); }
}
protected override void OnInitialized()
{
if (!DesignMode)
{
m_videoBuffer = Marshal.AllocHGlobal((int)(m_videoWidth * m_videoHeight * 4));
using (Bitmap bmp = new Bitmap((int)m_videoWidth, (int)m_videoHeight, (int)m_videoWidth * 4, PixelFormat.Bgra, m_videoBuffer))
{
using (var dc = DrawingContext.FromBitmap(bmp))
{
dc.Clear(Color.Transparent);
}
}
MediaPlayer = new MediaPlayer(LibVLC);
//MediaPlayer.SetVideoFormatCallbacks(VideoFormat, CleanupVideo);
var rs = VideoRenderSize;
if (rs.Width > 0 && rs.Height > 0)
{
m_videoWidth = (uint)rs.Width;
m_videoHeight = (uint)rs.Height;
}
MediaPlayer.SetVideoFormat("RV32", m_videoWidth, m_videoHeight, m_videoWidth * 4);
MediaPlayer.SetVideoCallbacks(libvlc_video_lock, libvlc_video_unlock, libvlc_video_display);
MediaPlayer.Opening += MediaPlayer_Opening;
}
base.OnInitialized();
}
private void MediaPlayer_Opening(object sender, EventArgs e)
{
Invoke(() =>
{
if (newSize.HasValue)
{
if (m_videoBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(m_videoBuffer);
}
m_videoWidth = (uint)newSize.Value.Width;
m_videoHeight = (uint)newSize.Value.Height;
m_videoBuffer = Marshal.AllocHGlobal((int)(m_videoWidth * m_videoHeight * 4));
newSize = null;
MediaPlayer.SetVideoFormat("RV32", m_videoWidth, m_videoHeight, m_videoWidth * 4);
}
});
}
///// <summary>
///// Called by Vlc when it requires a cleanup
///// </summary>
///// <param name="userdata">The parameter is not used</param>
//private void CleanupVideo(ref IntPtr userdata)
//{
// // This callback may be called by Dispose in the Dispatcher thread, in which case it deadlocks if we call RemoveVideo again in the same thread.
//}
//private uint VideoFormat(ref IntPtr opaque, IntPtr chroma, ref uint width,
// ref uint height, ref uint pitches, ref uint lines)
//{
// TextWriteTo("RV32", chroma);
// Invoke(() =>
// {
// if (newSize.HasValue)
// {
// if (m_videoBuffer != IntPtr.Zero)
// {
// Marshal.FreeHGlobal(m_videoBuffer);
// }
// m_videoWidth = (uint)newSize.Value.Width;
// m_videoHeight = (uint)newSize.Value.Height;
// m_videoBuffer = Marshal.AllocHGlobal((int)(m_videoWidth * m_videoHeight * 4));
// newSize = null;
// }
// });
// width = m_videoWidth;
// height = m_videoHeight;
// //lines = m_videoHeight;
// //pitches = width * 4;
// pitches = this.GetAlignedDimension((uint)(width * 4) / 8, 32);
// lines = this.GetAlignedDimension(height, 32);
// return 1;
//}
//private uint GetAlignedDimension(uint dimension, uint mod)
//{
// var modResult = dimension % mod;
// if (modResult == 0)
// {
// return dimension;
// }
// return dimension + mod - (dimension % mod);
//}
private IntPtr libvlc_video_lock(IntPtr opaque, IntPtr planes)
{
//Monitor.Enter(m_lockObj);
if (Root != null && !IsDisposing && !IsDisposed)
{
BeginInvoke(Invalidate);
}
Marshal.WriteIntPtr(planes, m_videoBuffer);
return IntPtr.Zero;
}
void libvlc_video_unlock(IntPtr opaque, IntPtr picture, IntPtr planes)
{
//Monitor.Exit(m_lockObj);
}
private void libvlc_video_display(IntPtr opaque, IntPtr picture)
{
}
public void Play(Uri uri = null)
{
if (uri == null)
{
MediaPlayer.Play();
}
else
{
if (MediaPlayer.IsPlaying)
{
new Thread(() =>
{
MediaPlayer.Stop();
MediaPlayer.Play(new Media(libVLC, uri));
})
{ Name = "停止并播放新的视频", IsBackground = true }.Start();
}
else
{
MediaPlayer.Play(new Media(libVLC, uri));
}
}
}
public void Pause()
{
MediaPlayer.Pause();
}
public void Stop()
{
new Thread(() =>
{
if ((bool)MediaPlayer.GetType().GetField("IsDisposed", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).GetValue(MediaPlayer))
{
return;
}
MediaPlayer.Stop();
})
{ Name = "停止播放", IsBackground = true }.Start();
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (m_videoBuffer == IntPtr.Zero)
{
return;
}
using (Bitmap bmp = new Bitmap((int)m_videoWidth, (int)m_videoHeight, (int)m_videoWidth * 4, PixelFormat.Bgra, m_videoBuffer))
{
dc.DrawImage(bmp, new Rect(new Point(), ActualSize), new Rect(0, 0, (int)m_videoWidth, (int)m_videoHeight));
}
}
[PropertyChanged(nameof(VideoRenderSize))]
void OnVideoRenderSize(object newValue, object oldValue, PropertyMetadataAttribute attribute)
{
var rs = (PixelSize)newValue;
if (rs.Width > 0 && rs.Height > 0)
{
newSize = rs;
}
else
{
newSize = null;
}
}
protected override void OnLayoutUpdated()
{
base.OnLayoutUpdated();
var rs = VideoRenderSize;
if (rs.Width <= 0 || rs.Height <= 0)
{
if (!IsDisposed && !IsDisposing && ActualSize != new Size(m_videoWidth, m_videoWidth) / Root.RenderScaling)
{
var max = Root.Screen.Bounds.Size;
var w = Math.Min(ActualSize.Width * Root.RenderScaling, max.Width);
var h = Math.Min(ActualSize.Height * Root.RenderScaling, max.Height);
if ((int)w != m_videoWidth || (int)h != m_videoHeight)
{
newSize = new PixelSize((int)w, (int)h);
//if (MediaPlayer != null)
//{
// MediaPlayer.SetVideoFormat("RV32", (uint)w, (uint)h, (uint)w * 4);
//}
}
}
}
}
public static void TextWriteTo(string fourCCString, IntPtr destination)
{
if (fourCCString.Length != 4)
{
throw new ArgumentException("4CC codes must be 4 characters long", nameof(fourCCString));
}
var bytes = Encoding.ASCII.GetBytes(fourCCString);
for (var i = 0; i < 4; i++)
{
Marshal.WriteByte(destination, i, bytes[i]);
}
}
protected override void Dispose(bool disposing)
{
var m = MediaPlayer;
if (m != null)
{
new Thread(() =>
{
m.Dispose();
if (m_videoBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(m_videoBuffer);
m_videoBuffer = IntPtr.Zero;
}
})
{ Name = "关闭播放器", IsBackground = true }.Start();
//libVLC.Dispose();
}
base.Dispose(disposing);
}
}
}
1
https://gitee.com/dresnclor/cpf.vlc.git
git@gitee.com:dresnclor/cpf.vlc.git
dresnclor
cpf.vlc
CPF.Vlc
master

搜索帮助