Ubuntu18.04安装Unity2017.4.10f1
1、chmod +x UnitySetup-2017.4.10f1
2、sudo apt install libgtk2.0-0 libsoup2.4-1 libarchive13 libpng16-16 libgconf-2-4 lib32stdc++6 libcanberra-gtk-module
3、Run the installer. UnitySetup-2017.4.10f1
1、chmod +x UnitySetup-2017.4.10f1
2、sudo apt install libgtk2.0-0 libsoup2.4-1 libarchive13 libpng16-16 libgconf-2-4 lib32stdc++6 libcanberra-gtk-module
3、Run the installer. UnitySetup-2017.4.10f1
思路来自 http://blog.csdn.net/yechen2320374/article/details/52226294
系统是64位的,因为我用的VLC的类库是64位的,用64位的Unity导出exe时选择x86_64,导出后需要将工程中Plugins下的plugins文件夹拷贝到发布后的Plugins文件夹下
工程地址https://gitee.com/awnuxcvbn/UnityVLC.git
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.IO;
using System.Threading;
namespace Net.Media
{
//定义替代变量
using libvlc_media_t = System.IntPtr;
using libvlc_media_player_t = System.IntPtr;
using libvlc_instance_t = System.IntPtr;
public class MediaPlayer
{
#region 全局变量
//数组转换为指针
internal struct PointerToArrayOfPointerHelper
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public IntPtr[] pointers;
}
//vlc库启动参数配置
//private static string pluginPath = System.Environment.CurrentDirectory + "\\Plugins\\VLC\\plugins\\";
private static string pluginPath = @UnityEngine.Application.dataPath + "/Plugins/";
private static string plugin_arg = "--plugin-path=" + pluginPath;
//用于播放节目时,转录节目
//private static string program_arg = "--sout=#duplicate{dst=std{access=file,mux=ts,dst=d:/test.ts}}";
private static string[] arguments = { "-I", "dummy", "--ignore-config", "--no-video-title", plugin_arg };//, program_arg };
#region 结构体
public struct libvlc_media_stats_t
{
/* Input */
public int i_read_bytes;
public float f_input_bitrate;
/* Demux */
public int i_demux_read_bytes;
public float f_demux_bitrate;
public int i_demux_corrupted;
public int i_demux_discontinuity;
/* Decoders */
public int i_decoded_video;
public int i_decoded_audio;
/* Video Output */
public int i_displayed_pictures;
public int i_lost_pictures;
/* Audio output */
public int i_played_abuffers;
public int i_lost_abuffers;
/* Stream output */
public int i_sent_packets;
public int i_sent_bytes;
public float f_send_bitrate;
}
#endregion
#endregion
#region 公开函数
/// <summary>
/// 创建VLC播放资源索引
/// </summary>
/// <param name="arguments"></param>
/// <returns></returns>
public static libvlc_instance_t Create_Media_Instance()
{
libvlc_instance_t libvlc_instance = IntPtr.Zero;
IntPtr argvPtr = IntPtr.Zero;
try
{
if (arguments.Length == 0 ||
arguments == null)
{
return IntPtr.Zero;
}
//将string数组转换为指针
argvPtr = StrToIntPtr(arguments);
if (argvPtr == null || argvPtr == IntPtr.Zero)
{
return IntPtr.Zero;
}
//设置启动参数
libvlc_instance = SafeNativeMethods.libvlc_new(arguments.Length, argvPtr);
if (libvlc_instance == null || libvlc_instance == IntPtr.Zero)
{
return IntPtr.Zero;
}
return libvlc_instance;
}
catch
{
return IntPtr.Zero;
}
}
/// <summary>
/// 释放VLC播放资源索引
/// </summary>
/// <param name="libvlc_instance">VLC 全局变量</param>
public static void Release_Media_Instance(libvlc_instance_t libvlc_instance)
{
try
{
if (libvlc_instance != IntPtr.Zero ||
libvlc_instance != null)
{
SafeNativeMethods.libvlc_release(libvlc_instance);
}
libvlc_instance = IntPtr.Zero;
}
catch (Exception)
{
libvlc_instance = IntPtr.Zero;
}
}
/// <summary>
/// 创建VLC播放器
/// </summary>
/// <param name="libvlc_instance">VLC 全局变量</param>
/// <param name="handle">VLC MediaPlayer需要绑定显示的窗体句柄</param>
/// <returns></returns>
public static libvlc_media_player_t Create_MediaPlayer(libvlc_instance_t libvlc_instance, IntPtr handle)
{
libvlc_media_player_t libvlc_media_player = IntPtr.Zero;
try
{
if (libvlc_instance == IntPtr.Zero ||
libvlc_instance == null ||
handle == IntPtr.Zero ||
handle == null)
{
return IntPtr.Zero;
}
//创建播放器
libvlc_media_player = SafeNativeMethods.libvlc_media_player_new(libvlc_instance);
if (libvlc_media_player == null || libvlc_media_player == IntPtr.Zero)
{
return IntPtr.Zero;
}
//设置播放窗口
//SafeNativeMethods.libvlc_media_player_set_hwnd(libvlc_media_player, (int)handle);
return libvlc_media_player;
}
catch
{
SafeNativeMethods.libvlc_media_player_release(libvlc_media_player);
return IntPtr.Zero;
}
}
/// <summary>
/// 释放媒体播放器
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
public static void Release_MediaPlayer(libvlc_media_player_t libvlc_media_player)
{
try
{
if (libvlc_media_player != IntPtr.Zero ||
libvlc_media_player != null)
{
if (SafeNativeMethods.libvlc_media_player_is_playing(libvlc_media_player))
{
SafeNativeMethods.libvlc_media_player_stop(libvlc_media_player);
}
SafeNativeMethods.libvlc_media_player_release(libvlc_media_player);
}
libvlc_media_player = IntPtr.Zero;
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
libvlc_media_player = IntPtr.Zero;
}
}
/// <summary>
/// 播放网络媒体
/// </summary>
/// <param name="libvlc_instance">VLC 全局变量</param>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <param name="url">网络视频URL,支持http、rtp、udp等格式的URL播放</param>
/// <returns></returns>
public static bool NetWork_Media_Play(libvlc_instance_t libvlc_instance, libvlc_media_player_t libvlc_media_player, string url)
{
IntPtr pMrl = IntPtr.Zero;
libvlc_media_t libvlc_media = IntPtr.Zero;
try
{
if (url == null ||
libvlc_instance == IntPtr.Zero ||
libvlc_instance == null ||
libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
UnityEngine.Debug.Log("url:" + url);
pMrl = StrToIntPtr(url);
if (pMrl == null || pMrl == IntPtr.Zero)
{
return false;
}
//播放网络文件
libvlc_media = SafeNativeMethods.libvlc_media_new_location(libvlc_instance, pMrl);
if (libvlc_media == null || libvlc_media == IntPtr.Zero)
{
return false;
}
SafeNativeMethods.libvlc_media_parse(libvlc_media);
long duration = SafeNativeMethods.libvlc_media_get_duration(libvlc_media);
UnityEngine.Debug.Log("duration: " + duration / 1000);
//将Media绑定到播放器上
SafeNativeMethods.libvlc_media_player_set_media(libvlc_media_player, libvlc_media);
//释放libvlc_media资源
SafeNativeMethods.libvlc_media_release(libvlc_media);
libvlc_media = IntPtr.Zero;
if (0 != SafeNativeMethods.libvlc_media_player_play(libvlc_media_player))
{
return false;
}
//休眠指定时间
Thread.Sleep(500);
return true;
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
//释放libvlc_media资源
if (libvlc_media != IntPtr.Zero)
{
SafeNativeMethods.libvlc_media_release(libvlc_media);
}
libvlc_media = IntPtr.Zero;
return false;
}
}
public static void SetFormart(libvlc_media_player_t libvlc_media_player, string formart, int width, int height, int pitch)
{
SafeNativeMethods.libvlc_video_set_format(libvlc_media_player, StrToIntPtr(formart), width, height, pitch);
}
public static int GetMediaWidth(libvlc_media_player_t libvlc_media_player)
{
int width = SafeNativeMethods.libvlc_video_get_width(libvlc_media_player);
UnityEngine.Debug.Log("width: " + width);
return width;
}
public static int GetMediaHeight(libvlc_media_player_t libvlc_media_player)
{
int height = SafeNativeMethods.libvlc_video_get_height(libvlc_media_player);
UnityEngine.Debug.Log("height: " + height);
return height;
}
/// <summary>
/// 暂停或恢复视频
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <returns></returns>
public static bool MediaPlayer_Pause(libvlc_media_player_t libvlc_media_player)
{
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
if (SafeNativeMethods.libvlc_media_player_can_pause(libvlc_media_player))
{
SafeNativeMethods.libvlc_media_player_pause(libvlc_media_player);
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// 停止播放
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <returns></returns>
public static bool MediaPlayer_Stop(libvlc_media_player_t libvlc_media_player)
{
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
SafeNativeMethods.libvlc_media_player_stop(libvlc_media_player);
return true;
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// 快进
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <returns></returns>
public static bool MediaPlayer_Forward(libvlc_media_player_t libvlc_media_player)
{
double time = 0;
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
if (SafeNativeMethods.libvlc_media_player_is_seekable(libvlc_media_player))
{
time = SafeNativeMethods.libvlc_media_player_get_time(libvlc_media_player) / 1000.0;
if (time == -1)
{
return false;
}
SafeNativeMethods.libvlc_media_player_set_time(libvlc_media_player, (Int64)((time + 30) * 1000));
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// 快退
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <returns></returns>
public static bool MediaPlayer_Back(libvlc_media_player_t libvlc_media_player)
{
double time = 0;
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
if (SafeNativeMethods.libvlc_media_player_is_seekable(libvlc_media_player))
{
time = SafeNativeMethods.libvlc_media_player_get_time(libvlc_media_player) / 1000.0;
if (time == -1)
{
return false;
}
if (time - 30 < 0)
{
SafeNativeMethods.libvlc_media_player_set_time(libvlc_media_player, (Int64)(1 * 1000));
}
else
{
SafeNativeMethods.libvlc_media_player_set_time(libvlc_media_player, (Int64)((time - 30) * 1000));
}
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// VLC MediaPlayer是否在播放
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <returns></returns>
public static bool MediaPlayer_IsPlaying(libvlc_media_player_t libvlc_media_player)
{
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
return SafeNativeMethods.libvlc_media_player_is_playing(libvlc_media_player);
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// 录制快照
/// </summary>
/// <param name="libvlc_media_player">VLC MediaPlayer变量</param>
/// <param name="path">快照要存放的路径</param>
/// <param name="name">快照保存的文件名称</param>
/// <returns></returns>
public static bool TakeSnapShot(libvlc_media_player_t libvlc_media_player, string path, string name)
{
try
{
string snap_shot_path = null;
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
//if (!Directory.Exists(path))
//{
// Directory.CreateDirectory(path);
//}
snap_shot_path = path + "\\" + name;
if (0 == SafeNativeMethods.libvlc_video_take_snapshot(libvlc_media_player, 0, snap_shot_path.ToCharArray(), 1024, 576))
{
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// 获取信息
/// </summary>
/// <param name="libvlc_media_player"></param>
/// <returns></returns>
public static bool GetMedia(libvlc_media_player_t libvlc_media_player)
{
libvlc_media_t media = IntPtr.Zero;
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
media = SafeNativeMethods.libvlc_media_player_get_media(libvlc_media_player);
if (media == IntPtr.Zero || media == null)
{
return false;
}
else
{
return true;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
return false;
}
}
/// <summary>
/// 获取已经显示的图片数
/// </summary>
/// <param name="libvlc_media_player"></param>
/// <returns></returns>
public static int GetDisplayedPictures(libvlc_media_player_t libvlc_media_player)
{
libvlc_media_t media = IntPtr.Zero;
libvlc_media_stats_t media_stats = new libvlc_media_stats_t();
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return 0;
}
media = SafeNativeMethods.libvlc_media_player_get_media(libvlc_media_player);
if (media == IntPtr.Zero || media == null)
{
return 0;
}
if (1 == SafeNativeMethods.libvlc_media_get_stats(media, ref media_stats))
{
return media_stats.i_displayed_pictures;
}
else
{
return 0;
}
}
catch (Exception)
{
return 0;
}
}
/// <summary>
/// 设置全屏
/// </summary>
/// <param name="libvlc_media_player"></param>
/// <param name="isFullScreen"></param>
public static bool SetFullScreen(libvlc_media_player_t libvlc_media_player, int isFullScreen)
{
try
{
if (libvlc_media_player == IntPtr.Zero ||
libvlc_media_player == null)
{
return false;
}
SafeNativeMethods.libvlc_set_fullscreen(libvlc_media_player, isFullScreen);
return true;
}
catch (Exception)
{
return false;
}
}
public static void SetCallbacks(libvlc_media_player_t libvlc_media_player,VideoLockCB lockcb,VideoUnlockCB unlockcb, VideoDisplayCB displaycb, IntPtr opaque)
{
try
{
SafeNativeMethods.libvlc_video_set_callbacks(libvlc_media_player, lockcb, unlockcb, displaycb, opaque);
UnityEngine.Debug.Log("SetCallbacks");
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
}
}
#endregion
public delegate IntPtr VideoLockCB(IntPtr opaque, IntPtr planes);
public delegate void VideoUnlockCB(IntPtr opaque, IntPtr picture, IntPtr planes);
//显示图片
public delegate void VideoDisplayCB(IntPtr opaque, IntPtr picture);
#region 私有函数
//将string []转换为IntPtr
public static IntPtr StrToIntPtr(string[] args)
{
try
{
IntPtr ip_args = IntPtr.Zero;
PointerToArrayOfPointerHelper argv = new PointerToArrayOfPointerHelper();
argv.pointers = new IntPtr[11];
for (int i = 0; i < args.Length; i++)
{
argv.pointers[i] = Marshal.StringToHGlobalAnsi(args[i]);
}
int size = Marshal.SizeOf(typeof(PointerToArrayOfPointerHelper));
ip_args = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(argv, ip_args, false);
return ip_args;
}
catch (Exception)
{
return IntPtr.Zero;
}
}
//将string转换为IntPtr
private static IntPtr StrToIntPtr(string url)
{
try
{
if (string.IsNullOrEmpty(url))
{
return IntPtr.Zero;
}
IntPtr pMrl = IntPtr.Zero;
byte[] bytes = Encoding.UTF8.GetBytes(url);
pMrl = Marshal.AllocHGlobal(bytes.Length + 1);
Marshal.Copy(bytes, 0, pMrl, bytes.Length);
Marshal.WriteByte(pMrl, bytes.Length, 0);
return pMrl;
}
catch (Exception)
{
return IntPtr.Zero;
}
}
#endregion
#region 导入库函数
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
// 创建一个libvlc实例,它是引用计数的
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern libvlc_instance_t libvlc_new(int argc, IntPtr argv);
// 释放libvlc实例
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_release(libvlc_instance_t libvlc_instance);
//获取libvlc的版本
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern String libvlc_get_version();
//从视频来源(例如http、rtsp)构建一个libvlc_meida
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern libvlc_media_t libvlc_media_new_location(libvlc_instance_t libvlc_instance, IntPtr path);
//从本地文件路径构建一个libvlc_media
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern libvlc_media_t libvlc_media_new_path(libvlc_instance_t libvlc_instance, IntPtr path);
//释放libvlc_media
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_release(libvlc_media_t libvlc_media_inst);
// 创建一个空的播放器
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern libvlc_media_player_t libvlc_media_player_new(libvlc_instance_t libvlc_instance);
//从libvlc_media构建播放器
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern libvlc_media_player_t libvlc_media_player_new_from_media(libvlc_media_t libvlc_media);
//释放播放器资源
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_player_release(libvlc_media_player_t libvlc_mediaplayer);
// 将视频(libvlc_media)绑定到播放器上
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_player_set_media(libvlc_media_player_t libvlc_media_player, libvlc_media_t libvlc_media);
// 设置编码
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_video_set_format(libvlc_media_player_t libvlc_media_player, IntPtr chroma, Int32 width, Int32 height, Int32 pitch);
// 视频每一帧的数据信息
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_video_set_callbacks(libvlc_media_player_t libvlc_mediaplayer,
VideoLockCB lockCB,
VideoUnlockCB unlockCB,
VideoDisplayCB displayCB,
IntPtr opaque);
// 设置图像输出的窗口
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_player_set_hwnd(libvlc_media_player_t libvlc_mediaplayer, Int32 drawable);
//播放器播放
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern int libvlc_media_player_play(libvlc_media_player_t libvlc_mediaplayer);
//播放器暂停
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_player_pause(libvlc_media_player_t libvlc_mediaplayer);
//播放器停止
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_player_stop(libvlc_media_player_t libvlc_mediaplayer);
// 解析视频资源的媒体信息(如时长等)
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_parse(libvlc_media_t libvlc_media);
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern Int32 libvlc_video_get_width(libvlc_media_player_t libvlc_mediaplayer);
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern Int32 libvlc_video_get_height(libvlc_media_player_t libvlc_mediaplayer);
// 返回视频的时长(必须先调用libvlc_media_parse之后,该函数才会生效)
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern Int64 libvlc_media_get_duration(libvlc_media_t libvlc_media);
// 当前播放时间
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern Int64 libvlc_media_player_get_time(libvlc_media_player_t libvlc_mediaplayer);
// 设置播放时间
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_media_player_set_time(libvlc_media_player_t libvlc_mediaplayer, Int64 time);
// 获取音量
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern int libvlc_audio_get_volume(libvlc_media_player_t libvlc_media_player);
//设置音量
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_audio_set_volume(libvlc_media_player_t libvlc_media_player, int volume);
// 设置全屏
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_set_fullscreen(libvlc_media_player_t libvlc_media_player, int isFullScreen);
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern int libvlc_get_fullscreen(libvlc_media_player_t libvlc_media_player);
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void libvlc_toggle_fullscreen(libvlc_media_player_t libvlc_media_player);
//判断播放时是否在播放
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern bool libvlc_media_player_is_playing(libvlc_media_player_t libvlc_media_player);
//判断播放时是否能够Seek
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern bool libvlc_media_player_is_seekable(libvlc_media_player_t libvlc_media_player);
//判断播放时是否能够Pause
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern bool libvlc_media_player_can_pause(libvlc_media_player_t libvlc_media_player);
//判断播放器是否可以播放
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern int libvlc_media_player_will_play(libvlc_media_player_t libvlc_media_player);
//进行快照
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern int libvlc_video_take_snapshot(libvlc_media_player_t libvlc_media_player, int num, char[] filepath, int i_width, int i_height);
//获取Media信息
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern libvlc_media_t libvlc_media_player_get_media(libvlc_media_player_t libvlc_media_player);
//获取媒体信息
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern int libvlc_media_get_stats(libvlc_media_t libvlc_media, ref libvlc_media_stats_t lib_vlc_media_stats);
}
#endregion
}
}
using Net.Media;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class Test : MonoBehaviour
{
//视频宽
public int width;
//视频高
public int height;
public Texture2D texture;
public Material mat;
IntPtr libvlc_instance_t;
IntPtr libvlc_media_player_t;
IntPtr handle;
private MediaPlayer.VideoLockCB _videoLockCB;
private MediaPlayer.VideoUnlockCB _videoUnlockCB;
private MediaPlayer.VideoDisplayCB _videoDisplayCB;
private const int _width = 1024;
private const int _height = 576;
private const int _pixelBytes = 4;
private const int _pitch = 1024 * _pixelBytes;
private IntPtr _buff = IntPtr.Zero;
private float fireRate = 0.02F;
private float nextFire = 0.0F;
bool ready = false;
// Use this for initialization
void Start()
{
if (_videoLockCB == null)
_videoLockCB = new MediaPlayer.VideoLockCB(VideoLockCallBack);
if (_videoUnlockCB == null)
_videoUnlockCB = new MediaPlayer.VideoUnlockCB(VideoUnlockCallBack);
if (_videoDisplayCB == null)
_videoDisplayCB = new MediaPlayer.VideoDisplayCB(VideoDiplayCallBack);
texture = new Texture2D(1024, 576, TextureFormat.RGBA32, false);
mat.mainTexture = texture;
_buff = Marshal.AllocHGlobal(_pitch * _height);
handle = new IntPtr(1);
libvlc_instance_t = MediaPlayer.Create_Media_Instance();
libvlc_media_player_t = MediaPlayer.Create_MediaPlayer(libvlc_instance_t, handle);
MediaPlayer.SetCallbacks(libvlc_media_player_t, _videoLockCB, _videoUnlockCB, _videoDisplayCB, IntPtr.Zero);
//"file:///"+Application.streamingAssetsPath+"/test.mp4");rtmp://live.hkstv.hk.lxdns.com/live/hks
//bool ready = MediaPlayer.NetWork_Media_Play(libvlc_instance_t, libvlc_media_player_t, "rtsp://127.0.0.1:8554/1");
ready = MediaPlayer.NetWork_Media_Play(libvlc_instance_t,
libvlc_media_player_t,
"rtmp://live.hkstv.hk.lxdns.com/live/hks");
Debug.Log(ready);
width = MediaPlayer.GetMediaWidth(libvlc_media_player_t);
height = MediaPlayer.GetMediaHeight(libvlc_media_player_t);
//"ARGB"
MediaPlayer.SetFormart(libvlc_media_player_t, "ARGB", _width, _height, _width * 4);
Debug.Log(MediaPlayer.MediaPlayer_IsPlaying(libvlc_media_player_t));
Debug.Log(Application.dataPath);
}
// Update is called once per frame
void Update()
{
//if (ready && Time.time > nextFire)
//{
//Debug.Log(Islock());
if (Islock())
{
texture.LoadRawTextureData(_buff, _buff.ToInt32());
texture.Apply();
}
//nextFire = Time.time + fireRate;
//}
}
private void OnGUI()
{
if(GUI.Button(new Rect(0,0,100,100),"Take"))
{
Debug.Log (MediaPlayer.TakeSnapShot(libvlc_media_player_t, @Application.streamingAssetsPath, "testa.jpg"));
}
}
private IntPtr VideoLockCallBack(IntPtr opaque, IntPtr planes)
{
Lock();
Marshal.WriteIntPtr(planes, _buff);//初始化
//Debug.Log("Lock");
return IntPtr.Zero;
}
private void VideoUnlockCallBack(IntPtr opaque, IntPtr picture, IntPtr planes)
{
Unlock();
//Debug.Log("Unlock");
}
private void VideoDiplayCallBack(IntPtr opaque, IntPtr picture)
{
if (Islock())
{
//Debug.Log("Islock");
//texture.LoadRawTextureData(picture, picture.ToInt32());
//texture.Apply();
//fwrite(buffer, sizeof buffer, 1, fp);
}
}
bool obj = false;
private void Lock()
{
obj = true;
}
private void Unlock()
{
obj = false;
}
private bool Islock()
{
return obj;
}
private void OnDestroy()
{
}
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static extern void CopyMemory(IntPtr Destination, IntPtr Source, uint Length);
private void OnApplicationQuit()
{
try
{
Debug.Log(MediaPlayer.MediaPlayer_IsPlaying(libvlc_media_player_t));
if (MediaPlayer.MediaPlayer_IsPlaying(libvlc_media_player_t))
{
MediaPlayer.MediaPlayer_Stop(libvlc_media_player_t);
}
MediaPlayer.Release_MediaPlayer(libvlc_media_player_t);
MediaPlayer.Release_Media_Instance(libvlc_instance_t);
}
catch (Exception e)
{
Debug.Log(e.Message);
}
}
}
暂停、停止、快进、音量等都还没做
win10x64 Unity 5.6.2f1 (64-bit)点击这里下载工程 http://pan.baidu.com/s/1geWfZEz
Android代码
package cn.net.xuefei.unityrec;
import java.io.File;
import java.io.IOException;
import com.unity3d.player.UnityPlayerActivity;
import android.Manifest;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.DisplayMetrics;
import android.widget.Toast;
public class MainActivity extends UnityPlayerActivity {
private static final int RECORD_REQUEST_CODE = 101;
private static final int STORAGE_REQUEST_CODE = 102;
private static final int AUDIO_REQUEST_CODE = 103;
private static final int SHOW = 1;
private static final int CANCEL = 2;
private boolean isRecording;
public static Context currentActivity;
private MediaProjectionManager mediaProjectionManager;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SHOW:
if (isRecording) {
Toast.makeText(MainActivity.this, "录制已开始", Toast.LENGTH_SHORT).show();
} else {
startScreenCapture();
isRecording = true;
}
break;
case CANCEL:
if (isRecording) {
mediaRecorder.stop();
mediaRecorder.reset();
mediaProjection.stop();
virtualDisplay.release();
isRecording = false;
insertVideoToMediaStore(getSaveDirectory() + videoName);
Toast.makeText(MainActivity.this, "录制结束", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "没有开始录制", Toast.LENGTH_SHORT).show();
}
break;
}
}
};
private MediaProjection mediaProjection;
private MediaRecorder mediaRecorder;
private VirtualDisplay virtualDisplay;
/**
* 屏幕的宽度
*/
private int screenWidth;
/**
* 屏幕的高度
*/
private int screenHeight;
/**
* 屏幕的像素
*/
private int screenDpi;
private DisplayMetrics metrics;
/**
* 保存在相册视频的名字
*/
private String videoName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mediaRecorder = new MediaRecorder();
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
/**
* 动态注册权限
*/
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
STORAGE_REQUEST_CODE);
}
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.RECORD_AUDIO },
AUDIO_REQUEST_CODE);
}
currentActivity = this;
//mUnityPlayer.requestFocus();
}
/**
* unity调用的方法,需要用一个handler进行处理实现功能,直接无法实现。
*/
public void stopRecordin() {
mHandler.sendEmptyMessage(CANCEL);
}
/**
* unity调用的方法,需要用一个handler进行处理实现功能,直接无法实现。
*/
public void startRecording() {
mHandler.sendEmptyMessage(SHOW);
}
private void startScreenCapture() {
mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
}
public void setConfig(int screenWidth, int screenHeight, int screenDpi) {
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.screenDpi = screenDpi;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);
startRecord();
Toast.makeText(this, "开始录制", Toast.LENGTH_SHORT).show();
}
}
public boolean startRecord() {
initRecorder();
createVirtualDisplay();
mediaRecorder.start();
return true;
}
private void createVirtualDisplay() {
virtualDisplay = mediaProjection.createVirtualDisplay("MainScreen", screenWidth, screenHeight, screenDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
}
private void initRecorder() {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
videoName = System.currentTimeMillis() + ".mp4";
mediaRecorder.setOutputFile(getSaveDirectory() + videoName);
mediaRecorder.setVideoSize(screenWidth, screenHeight);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
mediaRecorder.setVideoFrameRate(30);
try {
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getSaveDirectory() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String screenRecordPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
+ "DCIM" + File.separator + "Camera" + File.separator;
return screenRecordPath;
} else {
return null;
}
}
public void insertVideoToMediaStore(String filePath) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, filePath);
// video/*
values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}
/**
* 打开相册,
*
* @return
*/
public void openAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
startActivity(intent);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.net.xuefei.unityrec"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="22"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--往sdcard中写入数据的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!--在sdcard中创建/删除文件的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<application
>
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Unity代码
using UnityEngine;
using System.Collections;
public class UnityRec : MonoBehaviour
{
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnGUI()
{
if (GUI.Button(new Rect(0, 0, 300, 300), "开始录屏"))
{
#if UNITY_ANDROID
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("startRecording");
#elif UNITY_IPHONE
#endif
}
if (GUI.Button(new Rect(0, 300, 300, 300), "停止录屏"))
{
# if UNITY_ANDROID
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("stopRecordin");
#elif UNITY_IPHONE
#endif
}
}
}
using UnityEngine;
using System.Collections;
using OpenCvSharp;
public class VideoTest : MonoBehaviour
{
public WebCamTexture cameraTexture;
Texture2D rt;
public string cameraName = "";
private bool isPlay = false;
static int mPreviewWidth = 320;
static int mPreviewHeight = 240;
bool state = false;
CascadeClassifier haarCascade;
WebCamDevice[] devices;
// Use this for initialization
void Start()
{
rt = new Texture2D(mPreviewWidth, mPreviewHeight, TextureFormat.RGB565, false);
temp = new Texture2D(mPreviewWidth, mPreviewHeight, TextureFormat.RGB565, false);
StartCoroutine(Test());
haarCascade = new CascadeClassifier(Application.streamingAssetsPath + "/haarcascades/haarcascade_frontalface_alt2.xml");
}
// Update is called once per frame
void Update()
{
}
IEnumerator Test()
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
devices = WebCamTexture.devices;
cameraName = devices[0].name;
cameraTexture = new WebCamTexture(cameraName, mPreviewWidth, mPreviewHeight, 15);
cameraTexture.Play();
isPlay = true;
}
}
Mat haarResult;
byte[] bs;
void OnGUI()
{
if (isPlay)
{
GUI.DrawTexture(new UnityEngine.Rect(0, 0, mPreviewWidth, mPreviewHeight), cameraTexture, ScaleMode.ScaleToFit);
if (GUI.Button(new UnityEngine.Rect(0, 240, 80, 80), "START"))
{
if (state)
{
state = false;
return;
}
else
{
state = true;
}
}
if (state)
{
// Detect faces
haarResult = DetectFace(haarCascade, GetTexture2D(cameraTexture));
bs = haarResult.ToBytes(".png");
rt.LoadImage(bs);
rt.Apply();
GUI.DrawTexture(new UnityEngine.Rect(mPreviewWidth, 0, mPreviewWidth, mPreviewHeight), rt, ScaleMode.StretchToFill);
}
}
}
Mat result;
OpenCvSharp.Rect[] faces;
Mat src;
Mat gray = new Mat();
Size axes = new Size();
Point center = new Point();
/// <summary>
///
/// </summary>
/// <param name="cascade"></param>
/// <returns></returns>
private Mat DetectFace(CascadeClassifier cascade, Texture2D t)
{
src = Mat.FromImageData(t.EncodeToPNG(), ImreadModes.Color);
result = src.Clone();
Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
src = null;
// Detect faces
faces = cascade.DetectMultiScale(gray, 1.08, 2, HaarDetectionType.ScaleImage, new Size(30, 30));
// Render all detected faces
for (int i = 0; i < faces.Length; i++)
{
center.X = (int)(faces[i].X + faces[i].Width * 0.5);
center.Y = (int)(faces[i].Y + faces[i].Height * 0.5);
axes.Width = (int)(faces[i].Width * 0.5);
axes.Height = (int)(faces[i].Height * 0.5);
Cv2.Ellipse(result, center, axes, 0, 0, 360, new Scalar(255, 0, 255), 4);
}
return result;
}
Texture2D temp;
Texture2D GetTexture2D(WebCamTexture wct)
{
temp.SetPixels(wct.GetPixels());
temp.Apply();
return temp;
}
}
OpenCvSharp github地址 https://github.com/shimat/opencvsharp
工程下载(.3.5f1&win10x64)http://pan.baidu.com/s/1pLy6W4N
OpenCV相关插件下载 https://pan.baidu.com/s/1c2agKHM
package com.xuefei.game;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import com.unity3d.player.UnityPlayerNativeActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends UnityPlayerNativeActivity {
public static Context context;
public static MainActivity mainActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = this;
}
// 保存到相册
public static void savePng(final String fileName) {
context = mainActivity.getApplicationContext();
mainActivity.runOnUiThread(new Runnable() {
public void run() {
Bitmap bitmap = BitmapFactory.decodeFile(Environment
.getExternalStorageDirectory()
+ "/Android/data/com.xuefei.game/files/"
+ fileName
+ ".png");
File file = new File(Environment.getExternalStorageDirectory()
+ "/DCIM/Camera", fileName + ".jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
Log.w("cat", e.toString());
}
bitmap.compress(CompressFormat.JPEG, 100, fos);
try {
fos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.w("cat", e.toString());
}
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.w("cat", e.toString());
}
bitmap.recycle();//扫描保存的图片
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" +Environment.getExternalStorageDirectory()
+ "/DCIM/Camera/"+fileName + ".jpg")));
Toast.makeText(context, "照片已保存到相册", Toast.LENGTH_SHORT).show();
}
});
}
}
Unity中代码:
if (GUI.Button(new Rect(0, 720, 400, 120), "SavePng"))
{
StartCoroutine(SavePngToSD(DateTime.Now.ToFileTime().ToString()));
}
/// <summary>
/// 截图后先检测图片是否保存成功然后调用保存到相册
/// </summary>
/// <param name="name"></param>
public void SavePng(string name)
{
#if UNITY_ANDROID
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.CallStatic("SavePng", name);
#elif UNITY_IPHONE
#endif
}
/// <summary>
/// 保存截图到相册
/// </summary>
/// <param name="pngName"></param>
/// <returns></returns>
IEnumerator SavePngToSD(string pngName)
{
yield return new WaitForEndOfFrame();
Application.CaptureScreenshot(pngName + ".png");
while (!IsFileExistByPath(Application.persistentDataPath + "/" + pngName + ".png"))
{
yield return new WaitForSeconds(0.05f);
}
SavePng(pngName);
yield return new WaitForSeconds(0.3f);
//测试请求文件
WWW www = new WWW("file:///" + Application.persistentDataPath + "/" + pngName + ".png");
yield return www;
}
/// <summary>
/// 检测文件是否存在
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool IsFileExistByPath(string path)
{
FileInfo info = new FileInfo(path);
bool b = false;
if (info == null || info.Exists == false)
{
b = false;
}
else
{
b = true;
}
return b;
}
注意文件路径是否存在,不存在就创建
流程:Unity截屏--调用安卓拷贝到相册--扫描保存的文件
解决的问题:截屏图片在相册不显示。