#define ENABLE_LOG #define DEBUG /* * Copyright (c) 2014 - 2022 t_saki@serenegiant.com */ using AOT; using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using UnityEngine; using UnityEngine.Events; #if UNITY_ANDROID && UNITY_2018_3_OR_NEWER using UnityEngine.Android; #endif namespace SLAMUVC { //[RequireComponent(typeof(UVCInterface))] public class UVCManager : MonoBehaviour { private const string TAG = "UVCManager#"; //-------------------------------------------------------------------------------- public Int32 DefaultWidth = 1280; public Int32 DefaultHeight = 720; //前端这里默认是none,只记录前端,不传给dll,dll自己有默认的旋转 public CameraMirror DefaultMirror = CameraMirror.NONE; protected UVCInterface _interface; /** * 保持正在使用的相机信息 */ public class CameraInfo { //internal readonly UVCDevice device; internal UVCInterface uvcInterface; internal Texture previewTexture; internal int frameType; internal volatile Int32 activeId; private Int32 currentWidth; private Int32 currentHeight; //校准时候使用的分辨率 Vector2 CalibrationResolution = new Vector2(1280, 720);//"1280x720"; //识别的最高分辨率 Vector2 HighResolution = new Vector2(320, 240);//"320x240"; //识别的最低分辨率 Vector2 LowResolution = new Vector2(160, 120);// "160x120"; //摄像机参数 private Dictionary ctrlInfos = new Dictionary(); //当前摄像机分辨率 private Dictionary resolutionInfos = new Dictionary(); //PC测试用 internal CameraInfo(Texture texture) { // this.device = null; activeId = 1; previewTexture = texture; SetSize(texture.width, texture.height); } internal CameraInfo(UVCInterface _uvcInterface) { this.uvcInterface = _uvcInterface; } /** * 是否正在获取图像 */ public bool IsPreviewing { get { return (activeId != 0) && (previewTexture != null); } } /** * 当前分辨率(宽度) * 如果不在预览中则为0 */ public Int32 CurrentWidth { get { return currentWidth; } } /** * 当前分辨率(高度) * 如果不在预览中则为0 */ public Int32 CurrentHeight { get { return currentHeight; } } /** * 返回一个尺寸 */ public Vector2 Size => new Vector2(currentWidth, currentHeight); public Vector2Int IndexToCoord(int i) { var y = i / currentWidth; var x = i % currentWidth; return new Vector2Int(x, y); } public int CoordToIndex(int x, int y) { return y * currentWidth + x; } /** * 修改当前分辨率 * @param width * @param height */ internal bool SetSize(Int32 width, Int32 height) { bool bChange = false; if (width != currentWidth || height != currentHeight) { bChange = true; currentWidth = width; currentHeight = height; } Debug.Log("CameraInfo设置SetSize,大小变化:" + bChange + ",Size:[" + width + "," + height + "]"); return bChange; } /** * 当前默认分辨率 */ public Vector2 CurrentCalibrationResolution { get { return CalibrationResolution; } } /** * 当前默认校准时候高分辨率 */ public Vector2 CurrentHighResolution { get { return HighResolution; } } /** * 当前默认最低分辨率 */ public Vector2 CurrentLowResolution { get { return LowResolution; } } /** * 修改相机的分辨率,相机分辨率修改成功回调后才修改 本地分辨率 * @param width * @param height */ internal bool SetCameraSize(Int32 width, Int32 height) { bool bChange = false; if (width != currentWidth || height != currentHeight) { bChange = true; uvcInterface?.ChangeCameraInfo(width, height); } return bChange; } /** * 更新支持的分辨率 */ public void UpdateResolution() { string[] resolutions = uvcInterface.GetSupportedResolutions(); resolutionInfos.Clear(); //resolutions 数组是从大到小 for (int i = 0; i < resolutions.Length; i++) { string resolution = resolutions[i]; string[] res = resolution.ToString().Split('x'); resolutionInfos.Add(resolution, new Vector2(int.Parse(res[0]), int.Parse(res[1]))); } } /** * 获取分辨率的key: 1280 * 720 */ public List GetResolutionsStrs() { return new List(resolutionInfos.Keys); } /** * 获取分辨率的values:Vector2(1280,720) */ public List GetResolutionsVec2s() { return new List(resolutionInfos.Values); } /** * 是否存在分辨率 */ public bool ContainsResulutionKey(string type) { return resolutionInfos.ContainsKey(type); } /** * 更新支持的 UVC 控制/处理功能信息 */ public void UpdateCtrls() { uvcInterface.GetUvcCtrlList(); ctrlInfos.Clear(); foreach (UVCCtrl ctrl in uvcInterface.UVCCtrls) { if (ctrl.name == "PU_BRIGHTNESS") Debug.Log($"name:{ctrl.name}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}, 转插件值后: {ctrl.value / 1000f}"); else if (ctrl.name == "PU_CONTRAST") Debug.Log($"name:{ctrl.name}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}, 转插件值后: {ctrl.value / 100f}"); ctrlInfos.Add(ctrl.name, new UVCCtrlInfo { name = ctrl.name, current = ctrl.value, min = ctrl.limit != null && ctrl.limit.Length > 0 ? ctrl.limit[0] : 0, max = ctrl.limit != null && ctrl.limit.Length > 1 ? ctrl.limit[1] : 0, def = ctrl.limit != null && ctrl.limit.Length > 2 ? ctrl.limit[2] : 0 }); } } /** * 获取支持的 UVC 控制/处理功能的类型列表 */ public List GetCtrls() { return new List(ctrlInfos.Keys); } /** * 获取指定 UVC 控制/处理功能的信息 * @param type * @return UVCCtrlInfo * @throws ArgumentOutOfRangeException */ public UVCCtrlInfo GetInfo(string type) { if (ctrlInfos.ContainsKey(type)) { return ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo()); } else { throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}"); } } public bool ContainsKey(string type) { return ctrlInfos.ContainsKey(type); } /** * 获取 UVC 控制/处理功能的设置值 * @param type * @return 变更后的值 * @throws ArgumentOutOfRangeException * @throws Exception */ public Int32 GetValue(string type) { if (ctrlInfos.ContainsKey(type)) { var r = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo()); if (r.name != null) { return r.current; } else { throw new Exception($"获取控制值失败,type={type},err={r}"); } } else { throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}"); } } /** * 修改 UVC 控制/处理功能的设置 * @param type * @param value * @return 变更后的值 * @throws ArgumentOutOfRangeException * @throws Exception */ public Int32 SetValue(string type, Int32 value) { if (ctrlInfos.ContainsKey(type)) { var r = uvcInterface.SetCtrlValue(type, value); if (r == 0) { UpdateCtrls(); // 同步刷列表 var info = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo()); info.current = value; ctrlInfos[type] = info; return value; } else { Debug.LogError($"设置控制值失败,type={type},err={r}"); } } else { Debug.LogError($"不支持的控制类型{type:X}"); } return 0; } public override string ToString() { return $"{base.ToString()}({currentWidth}x{currentHeight},activeId={activeId},IsPreviewing={IsPreviewing})"; } } // CameraInfo /** * 获取映像中的 UVC 设备映射 */ private CameraInfo cameraInfo; /// /// 开始事件 /// [HideInInspector] public UnityEvent startUVCManager; /// /// 更新事件 /// [HideInInspector] public UnityEvent updateUVCManager; private bool bInit = false; private void Awake() { // _interface = GetComponent(); #if UNITY_IOS _interface = gameObject.AddComponent(); #elif UNITY_ANDROID _interface = gameObject.AddComponent(); #else Debug.LogError("Unsupported platform!"); #endif _interface.systemCameraPermissionHandle += () => { //授权系统相机之后,初始化红外相机 initUVCManagerCamera(); }; } private void Start() { //initUVCManagerCamera(); } /// /// 初始化相机系统 /// public void initUVCManagerCamera() { _interface.cameraTextureHandle += () => { Debug.Log("cameraTextureHandle"); if (_interface.CameraTexture == null) { Debug.LogError("[Error] CameraTexture is NULL!"); return; } var info = GetCamera(); if (info == null) { Debug.LogError("[Error] GetCamera() returned NULL!"); return; } //bChange反馈是否变化宽高 bool bChange = info.SetSize(_interface.CameraTexture.width, _interface.CameraTexture.height); info.previewTexture = _interface.CameraTexture; info.activeId = 1; if (bInit) { //之后的触发的重新创建纹理更新 updateUVCManager?.Invoke(bChange); } else { /** * 第一次更新触发初始化 */ info.UpdateCtrls();//获取摄像机参数 info.UpdateResolution();//获取摄像机分辨率 startUVCManager?.Invoke(info); // StartCoroutine(DelayGetInfo(info)); } bInit = true; }; //初始化相机,连接设备时候自动开启渲染 if (DefaultMirror == CameraMirror.NONE) { _interface.InitCamera(DefaultWidth, DefaultHeight); } else { _interface.InitCamera(DefaultWidth, DefaultHeight, DefaultMirror); } } /// /// 延迟一下获取操作参数 /// /// /// //IEnumerator DelayGetInfo(CameraInfo info) //{ // yield return new WaitForSecondsRealtime(0.5f); //} /// /// 开启渲染 /// public void onStartPreview() { _interface.OpenCamera(); } /// /// 停止渲染 /// public void onStopPreview() { _interface.CloseCamera(); //重置cameraInfo的参数 var info = GetCamera(); info.SetSize(0, 0); info.previewTexture = null; info.activeId = 0; } /** * 获取与指定的 UVC 识别字符串对应的 CameraInfo * @param device * @return 如果已注册,则返回 CameraInfo;如果未注册,则返回 New CameraInfo */ /*Nullable*/ private CameraInfo GetCamera() { if (cameraInfo == null) cameraInfo = new CameraInfo(_interface); return cameraInfo; } /** * 水平翻转 */ public void FlipHorizontally() { _interface.FlipHorizontally(); } /** * 垂直翻转 */ public void FlipVertically() { _interface.FlipVertically(); } } }