using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Container.Common { class VlcPlayer { private IntPtr libvlc_instance_; private IntPtr libvlc_media_player_; private double duration_; public VlcPlayer(string pluginPath, bool isTransform) { /* * --avcodec-hurry-up, --no-avcodec-hurry-up 紧急 (默认启用) 解码器在时间不充足的情况下可能部分解码器或跳过帧。在 CPU 不是很强大时这非常有用,但是可能会破坏图像。 (默认启用) * --sout-avcodec-rc-buffer-size=<整数 [-2147483648 .. 2147483647]> 速率控制缓存大小 速率控制缓存大小 (以千字节为单位)。一个较大的缓存将会有较佳的帧率控制,但是可能会导致流的延迟。 * --avcodec-fast, --no-avcodec-fast 允许非正常速度优化 (默认关闭) 允许不符合标准的速度优化。更快但可能会出错。 (默认关闭) --avcodec-skiploopfilter={0 (无), 1 (非参考), 2 (双向), 3 (非关键), 4 (全部)} 用于 H.264 解码的跳过循环滤镜 跳过循环滤镜 (又作去块) 通常对图像质量会造成不良的效果。但是它能为高分辨率的流提供一个很大的提速。 * --avcodec-codec=<字串> 编解码器名称 libavcodec 内部编解码器名称 --avcodec-hw=<字串> 硬件解码 这将允许硬件解码(当硬件解码可用时)。 * --drop-late-frames, --no-drop-late-frames 丢弃延迟的帧 (默认启用) 这将丢弃延迟的帧 (在它们实际应该显示的时间后到达视频输出)。 (默认启用) --skip-frames, --no-skip-frames 跳帧 (默认启用) 在 MPEG2 串流上启用帧丢弃。帧丢弃在您的计算机性能不够强大时发生 (默认启用) */ string plugin_arg = "--plugin-path=" + pluginPath; string[] arguments = { plugin_arg, "--network-caching=<300", ":sout=#transcode{vcodec=h264,acodec=mpga,ab=128,channels=2,samplerate=44100" }; //string[] arguments = { plugin_arg, "--network-caching=<300", ":sout=#transcode{vcodec=h264,acodec=mpga,ab=128,channels=2,samplerate=44100" }; string[] argumentTransform = { "-I", "dummy", "--ignore-config", "--video-title", plugin_arg, "--avcodec-skiploopfilter=4", "--avcodec-fast", "--network-caching<=1800", "pe=270", ":sout=#transcode{vcodec=h264,acodec=mpga,ab=128,channels=2,samplerate=44100" }; //sring[] arguments = { "-I", "--avcodec-hw=any", plugin_arg,"--avcodec-codec=q//", "--avcodec-skiploopfilter=4", "--avcodec-fast", "--network-caching=<1800" }; //if (isTransform) // libvlc_instance_ = LibVlcAPI.libvlc_new(argumentTransform); //else libvlc_instance_ = LibVlcAPI.libvlc_new(arguments); libvlc_media_player_ = LibVlcAPI.libvlc_media_player_new(libvlc_instance_); } public void SetRenderWindow(int wndHandle) { if (libvlc_instance_ != IntPtr.Zero && wndHandle != 0) { LibVlcAPI.libvlc_media_player_set_hwnd(libvlc_media_player_, wndHandle); } } public void PlayFile(string filePath) { IntPtr libvlc_media = LibVlcAPI.libvlc_media_new_path(libvlc_instance_, filePath); if (libvlc_media != IntPtr.Zero) { LibVlcAPI.libvlc_media_parse(libvlc_media); duration_ = LibVlcAPI.libvlc_media_get_duration(libvlc_media) / 1000.0; LibVlcAPI.libvlc_media_player_set_media(libvlc_media_player_, libvlc_media); LibVlcAPI.libvlc_media_release(libvlc_media); LibVlcAPI.libvlc_media_player_play(libvlc_media_player_); } } public void PlayStream(string url) { IntPtr libvlc_media = LibVlcAPI.libvlc_media_new_location(libvlc_instance_, url); if (libvlc_media != IntPtr.Zero) { LibVlcAPI.libvlc_media_player_set_media(libvlc_media_player_, libvlc_media); LibVlcAPI.libvlc_media_release(libvlc_media); LibVlcAPI.libvlc_media_player_play(libvlc_media_player_); LibVlcAPI.libvlc_media_parse(libvlc_media); Thread.Sleep(300); duration_ = LibVlcAPI.libvlc_media_get_duration(libvlc_media) / 1000.0; } } public void Pause() { if (libvlc_media_player_ != IntPtr.Zero) { LibVlcAPI.libvlc_media_player_pause(libvlc_media_player_); } } public void Stop() { if (libvlc_media_player_ != IntPtr.Zero) { LibVlcAPI.libvlc_media_player_stop(libvlc_media_player_); } } public double GetPlayTime() { return LibVlcAPI.libvlc_media_player_get_time(libvlc_media_player_) / 1000.0; } public void SetPlayTime(double seekTime) { LibVlcAPI.libvlc_media_player_set_time(libvlc_media_player_, (Int64)(seekTime * 1000)); } public int GetVolume() { return LibVlcAPI.libvlc_audio_get_volume(libvlc_media_player_); } public void SetVolume(int volume) { LibVlcAPI.libvlc_audio_set_volume(libvlc_media_player_, volume); } public void SetFullScreen(bool istrue) { LibVlcAPI.libvlc_set_fullscreen(libvlc_media_player_, istrue ? 1 : 0); } public double Duration() { return duration_; } public string Version() { return LibVlcAPI.libvlc_get_version(); } } internal static class LibVlcAPI { internal struct PointerToArrayOfPointerHelper { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public IntPtr[] pointers; } public static IntPtr libvlc_new(string[] arguments) { PointerToArrayOfPointerHelper argv = new PointerToArrayOfPointerHelper(); argv.pointers = new IntPtr[11]; for (int i = 0; i < arguments.Length; i++) { argv.pointers[i] = Marshal.StringToHGlobalAnsi(arguments[i]); } IntPtr argvPtr = IntPtr.Zero; try { int size = Marshal.SizeOf(typeof(PointerToArrayOfPointerHelper)); argvPtr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(argv, argvPtr, false); return libvlc_new(arguments.Length, argvPtr); } finally { for (int i = 0; i < arguments.Length + 1; i++) { if (argv.pointers[i] != IntPtr.Zero) { Marshal.FreeHGlobal(argv.pointers[i]); } } if (argvPtr != IntPtr.Zero) { Marshal.FreeHGlobal(argvPtr); } } } public static IntPtr libvlc_media_new_path(IntPtr libvlc_instance, string path) { IntPtr pMrl = IntPtr.Zero; try { byte[] bytes = Encoding.UTF8.GetBytes(path); pMrl = Marshal.AllocHGlobal(bytes.Length + 1); Marshal.Copy(bytes, 0, pMrl, bytes.Length); Marshal.WriteByte(pMrl, bytes.Length, 0); return libvlc_media_new_path(libvlc_instance, pMrl); } finally { if (pMrl != IntPtr.Zero) { Marshal.FreeHGlobal(pMrl); } } } public static IntPtr libvlc_media_new_location(IntPtr libvlc_instance, string path) { IntPtr pMrl = IntPtr.Zero; try { byte[] bytes = Encoding.UTF8.GetBytes(path); pMrl = Marshal.AllocHGlobal(bytes.Length + 1); Marshal.Copy(bytes, 0, pMrl, bytes.Length); Marshal.WriteByte(pMrl, bytes.Length, 0); return libvlc_media_new_location(libvlc_instance, pMrl); } finally { if (pMrl != IntPtr.Zero) { Marshal.FreeHGlobal(pMrl); } } } // ---------------------------------------------------------------------------------------- // 以下是libvlc.dll导出函数 // 创建一个libvlc实例,它是引用计数的 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] private static extern IntPtr libvlc_new(int argc, IntPtr argv); // 释放libvlc实例 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_release(IntPtr libvlc_instance); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern String libvlc_get_version(); // 从视频来源(例如Url)构建一个libvlc_meida [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] private static extern IntPtr libvlc_media_new_location(IntPtr libvlc_instance, IntPtr path); // 从本地文件路径构建一个libvlc_media [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] private static extern IntPtr libvlc_media_new_path(IntPtr libvlc_instance, IntPtr path); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_release(IntPtr libvlc_media_inst); // 创建libvlc_media_player(播放核心) [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern IntPtr libvlc_media_player_new(IntPtr libvlc_instance); // 将视频(libvlc_media)绑定到播放器上 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_set_media(IntPtr libvlc_media_player, IntPtr libvlc_media); // 设置图像输出的窗口 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_set_hwnd(IntPtr libvlc_mediaplayer, Int32 drawable); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_play(IntPtr libvlc_mediaplayer); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_pause(IntPtr libvlc_mediaplayer); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_stop(IntPtr libvlc_mediaplayer); // 解析视频资源的媒体信息(如时长等) [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_parse(IntPtr libvlc_media); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern bool libvlc_media_is_parsed(IntPtr libvlc_media); // 返回视频的时长(必须先调用libvlc_media_parse之后,该函数才会生效) [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern Int64 libvlc_media_get_duration(IntPtr libvlc_media); // 当前播放的时间 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern Int64 libvlc_media_player_get_time(IntPtr libvlc_mediaplayer); // 设置播放位置(拖动) [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_set_time(IntPtr libvlc_mediaplayer, Int64 time); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_media_player_release(IntPtr libvlc_mediaplayer); // 获取和设置音量 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern int libvlc_audio_get_volume(IntPtr libvlc_media_player); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_audio_set_volume(IntPtr libvlc_media_player, int volume); // 设置全屏 [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [SuppressUnmanagedCodeSecurity] public static extern void libvlc_set_fullscreen(IntPtr libvlc_media_player, int isFullScreen); } }