You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
14 KiB
335 lines
14 KiB
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);
|
|
}
|
|
}
|
|
|