| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Runtime.InteropServices;
- using SLAMUVC;
- using UnityEngine.UI;
- using System.Collections.Generic;
- using AOT;
- using System.Threading;
- using UnityEngine.Events;
- using UnityEngine.Android;
- namespace SLAMUVC
- {
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
- public struct UVCCtrlInfo
- {
- public string name;
- public Int32 current;
- public Int32 min;
- public Int32 max;
- public Int32 def;
- public override string ToString()
- {
- return $"{base.ToString()}(name={name},min={min},max={max},def={def},current={current})";
- }
- }
- [System.Serializable]
- public class UVCCtrl
- {
- public string name;
- public bool isAuto;
- public bool isEnable;
- public int[] limit;
- public int value;
- }
- [System.Serializable]
- public class UVCCtrlWrapper
- {
- public UVCCtrl[] uvcCtrls;
- }
- public enum CameraFormat
- {
- MJPEG,
- YUV,
- }
- public enum CameraMirror
- {
- NONE,
- HORIZONTAL,//水平翻转
- VERTICAL//垂直翻转
- }
- public enum UVCCameraPixelFormat
- {
- PIXEL_FORMAT_RAW,
- PIXEL_FORMAT_YUV,
- PIXEL_FORMAT_NV12, // one format of YUV420SemiPlanar
- PIXEL_FORMAT_NV21, // one format of YUV420SemiPlanar
- PIXEL_FORMAT_RGB,
- PIXEL_FORMAT_RGB565,
- PIXEL_FORMAT_RGBX
- }
- //UVC的管理类
- public class UVCInterface : MonoBehaviour
- {
- private const string UVC_MANAGER = "com.slambb.myuvc.MyUVCManager";
- //java对象
- private AndroidJavaObject uvcManagerObj = null;
- CameraFormat mCameraFormat = CameraFormat.MJPEG;
- CameraMirror mCameraMirror = CameraMirror.VERTICAL;//默认垂直
- int Width = 1280;
- int Height = 720;
- Texture2D _cameraTexture;
- public Texture2D CameraTexture => _cameraTexture;
- private UVCCtrl[] uvcCtrls;
- public UVCCtrl[] UVCCtrls => uvcCtrls;
- private SynchronizationContext mainContext;
- /// <summary>
- /// 初始化相机权限成功
- /// </summary>
- public CameraPermissionHandle systemCameraPermissionHandle;
- public delegate void CameraPermissionHandle();
- /// <summary>
- /// 纹理更新事件
- /// </summary>
- public CameraTextureHandle cameraTextureHandle;
- public delegate void CameraTextureHandle();
- private static readonly string ActivityClassName = "com.slambb.myuvc.UsbPermissionActivity";
- //public void RequestUsbPermission()
- //{
- // using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
- // {
- // AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
- // AndroidJavaClass usbPermissionActivity = new AndroidJavaClass(ActivityClassName);
- // // Start UsbPermissionActivity
- // activity.Call("startActivity", usbPermissionActivity.CallStatic<AndroidJavaObject>("newIntent", activity));
- // }
- //}
- void Awake()
- {
- try
- {
- // 创建 uvcManagerObj 对象
- uvcManagerObj = new AndroidJavaObject(UVC_MANAGER);
- }
- catch (Exception e)
- {
- Debug.LogError("UVC_MANAGER Exception: " + e.Message);
- }
- //RequestUsbPermission();
- }
- void Start()
- {
- OpenCameraPermisson();
- }
- private void OnDestroy()
- {
- Remove(this);
- uvcManagerObj.Call("clearCameraHelper");
- }
- /// <summary>
- /// 创建一个纹理id到插件
- /// </summary>
- private void CreateTextureAndPassToPlugin()
- {
- // 销毁纹理
- if (_cameraTexture != null)
- {
- Destroy(_cameraTexture);
- _cameraTexture = null;
- }
- // Create a texture
- Texture2D tex = new Texture2D(Width, Height, TextureFormat.ARGB32, false);
- // 设置点过滤,以便我们可以清楚地看到像素
- tex.filterMode = FilterMode.Point;
- // 调用Apply(),使其实际上传到GPU
- tex.Apply();
- _cameraTexture = tex;
- //将纹理指针传递给插件
- SetTexture(tex.GetNativeTexturePtr(), tex.width, tex.height);
- cameraTextureHandle?.Invoke();
- }
- //private IEnumerator CallPluginAtEndOfFrames()
- //{
- // while (true)
- // {
- // //等待所有帧渲染完成
- // yield return new WaitForEndOfFrame();
- // //发出具有任意整数标识符的插件事件。
- // //该插件可以区分不同的
- // //它需要根据这个ID做的事情。
- // //对于我们的简单插件,我们在这里传递哪个ID并不重要。
- // if(GetIsPreviewing()) GL.IssuePluginEvent(GetRenderEventFunc(), 1);
- // }
- //}
- /// <summary>
- /// 更新纹理
- /// </summary>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="bUpdate"></param>
- public void OnTextureUpdate(int width, int height, bool bUpdate)
- {
- mainContext.Post(__ =>
- {
- if (bUpdate)
- {
- Debug.Log("创建新纹理:size=[" + width + "," + height + "]");
- Width = width;
- Height = height;
- CreateTextureAndPassToPlugin();
- }
- else
- {
- GL.IssuePluginEvent(GetRenderEventFunc(), 1);
- }
- }, null);
- }
- public bool GetIsPreviewing()
- {
- if (uvcManagerObj != null)
- {
- if (uvcManagerObj.Call<int>("GetIsPreviewing") == 1)
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// 初始化相机和对应的操作,初始化后会自动打开相机
- /// </summary>
- /// <param name="width"></param>
- /// <param name="height"></param>
- public void InitCamera(int width, int height)
- {
- Width = width;
- Height = height;
- uvcManagerObj.Call("initCameraHelper", Width, Height, mCameraFormat.ToString(), mCameraMirror.ToString());
- //主线程
- mainContext = SynchronizationContext.Current;
- //注册c回调
- Add(this);
- //mainContext.Post(__ =>
- //{
- // //CreateTextureAndPassToPlugin();
- //}, null);
- //StartCoroutine("CallPluginAtEndOfFrames");
- }
- public void OpenCamera()
- {
- uvcManagerObj.Call("OpenCamera");
- }
- public void CloseCamera()
- {
- uvcManagerObj.Call("CloseCamera");
- }
- public void ChangeCameraInfo(int width, int height)
- {
- uvcManagerObj.Call("ChangeCameraInfo", width, height, mCameraFormat.ToString());
- }
- public string[] GetSupportedResolutions()
- {
- if (uvcManagerObj != null)
- {
- var objPtr = uvcManagerObj.Call<AndroidJavaObject>("GetSupportedResolutions").GetRawObject();
- if (objPtr != IntPtr.Zero)
- return AndroidJNIHelper.ConvertFromJNIArray<string[]>(objPtr);
- }
- return null;
- }
- /// <summary>
- /// 水平翻转
- /// </summary>
- public void FlipHorizontally()
- {
- uvcManagerObj.Call("FlipHorizontally");
- }
- /// <summary>
- /// 垂直翻转
- /// </summary>
- public void FlipVertically()
- {
- uvcManagerObj.Call("FlipVertically");
- }
- public void resetControlParams()
- {
- uvcManagerObj.Call("resetControlParams");
- }
- public void GetUvcCtrlList()
- {
- if (uvcManagerObj != null)
- {
- string json = uvcManagerObj.Call<string>("GetUvcCtrlList");
- UVCCtrlWrapper wrapper = JsonUtility.FromJson<UVCCtrlWrapper>("{\"uvcCtrls\":" + json + "}");
- if (wrapper != null && wrapper.uvcCtrls != null)
- {
- //赋值
- uvcCtrls = wrapper.uvcCtrls;
- //foreach (UVCCtrl ctrl in wrapper.uvcCtrls)
- //{
- // Debug.Log($"name:{ctrl.name}, isAuto: {ctrl.isAuto}, isEnable: {ctrl.isEnable}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}");
- //}
- }
- else
- {
- Debug.LogError("Failed to parse JSON data.");
- }
- }
- }
- public void SetBrightness(int value)
- {
- uvcManagerObj.Call("SetBrightness", value);
- }
- public void SetContrast(int value)
- {
- uvcManagerObj.Call("SetContrast", value);
- }
- public int SetCtrlValue(string type, Int32 value)
- {
- int result = -1;
- if (type == "PU_BRIGHTNESS")
- {
- uvcManagerObj.Call("SetBrightness", value);
- result = 0;
- }
- else if (type == "PU_CONTRAST")
- {
- uvcManagerObj.Call("SetContrast", value);
- result = 0;
- }
- return result;
- }
- //--------------------------------------------------------------------------------
- /**
- * 先处理相机权限
- */
- private void OpenCameraPermisson()
- {
- if (Permission.HasUserAuthorizedPermission(Permission.Camera))
- {
- //Debug.LogError("HasUserAuthorizedPermission!");
- systemCameraPermissionHandle?.Invoke();
- return;
- }
- bool useCallbacks = true;
- if (!useCallbacks)
- {
- // We do not have permission to use the microphone.
- // Ask for permission or proceed without the functionality enabled.
- Permission.RequestUserPermission(Permission.Camera);
- }
- else
- {
- var callbacks = new PermissionCallbacks();
- callbacks.PermissionDenied += PermissionCallbacks_PermissionDenied;
- callbacks.PermissionGranted += PermissionCallbacks_PermissionGranted;
- callbacks.PermissionDeniedAndDontAskAgain += PermissionCallbacks_PermissionDeniedAndDontAskAgain;
- Permission.RequestUserPermission(Permission.Camera, callbacks);
- }
- }
- void PermissionCallbacks_PermissionDenied(string PermissionName)
- {
- Debug.LogError($"PermissionCallbacks_PermissionDenied[{PermissionName}]");
- }
- //本次允许
- void PermissionCallbacks_PermissionGranted(string PermissionName)
- {
- Debug.Log($"PermissionCallbacks_PermissionGranted[{PermissionName}]");
- systemCameraPermissionHandle?.Invoke();
- }
- void PermissionCallbacks_PermissionDeniedAndDontAskAgain(string PermissionName)
- {
- Debug.Log($"PermissionCallbacks_PermissionDeniedAndDontAskAgain[{PermissionName}]");
- systemCameraPermissionHandle?.Invoke();
- }
- //设置GL纹理
- [DllImport("TransferTexture")]
- private static extern void SetTexture(IntPtr texture, int w, int h);
- //GL渲染事件
- [DllImport("TransferTexture")]
- private static extern IntPtr GetRenderEventFunc();
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate void TextureUpdateDelegate(Int32 id, int width, int height, bool bUpdate);
- [DllImport("TransferTexture")]
- private static extern void RegisterTextureUpdateCallback(Int32 id, TextureUpdateDelegate callback);
- [DllImport("TransferTexture")]
- private static extern void UnregisterTextureUpdateCallback(Int32 id, TextureUpdateDelegate callback);
- //记录MyUVCInterface
- private static Dictionary<Int32, UVCInterface> mUVCInterfaces = new Dictionary<Int32, UVCInterface>();
- private static TextureUpdateDelegate textureUpdateDelegate;
- //注册回调事件
- public static void Add(UVCInterface myUVCInterface)
- {
- Int32 id = myUVCInterface.GetHashCode();
- textureUpdateDelegate = new TextureUpdateDelegate(TextureUpdateHandler);
- mUVCInterfaces.Add(id, myUVCInterface);
- RegisterTextureUpdateCallback(id, textureUpdateDelegate);
- }
- //移除回调事件
- public static void Remove(UVCInterface myUVCInterface)
- {
- Int32 id = myUVCInterface.GetHashCode();
- UnregisterTextureUpdateCallback(id, textureUpdateDelegate);
- mUVCInterfaces.Remove(id);
- }
- //数据更新时候回调
- [MonoPInvokeCallback(typeof(TextureUpdateDelegate))]
- private static void TextureUpdateHandler(Int32 id, int width, int height, bool bUpdate)
- {
- var myUVCInterface = mUVCInterfaces.ContainsKey(id) ? mUVCInterfaces[id] : null;
- if (myUVCInterface != null)
- {
- myUVCInterface.OnTextureUpdate(width, height, bUpdate);
- }
- }
- }
- }
|