2020-09-29 17:01:18 +02:00
|
|
|
using System;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
// To use this, add the following entry to the dependencies in Packages\manifest.json:
|
|
|
|
|
// "com.unity.nuget.newtonsoft-json": "2.0.0"
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
|
|
|
|
namespace OpenSee {
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
public enum OpenSeeWebcamType { Unknown = -1, DirectShow, Blackmagic };
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
public enum OpenSeeWebcamFormat { Any = 0, Unknown = 1, ARGB = 100, XRGB, I420 = 200, NV12, YV12, Y800, YVYU = 300, YUY2, UYVY, HDYC, MJPEG = 400, H264 };
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
public struct OpenSeeWebcamCapability {
|
|
|
|
|
public int id;
|
|
|
|
|
|
|
|
|
|
// DirectShow
|
|
|
|
|
public int minCX;
|
|
|
|
|
public int minCY;
|
|
|
|
|
public int maxCX;
|
|
|
|
|
public int maxCY;
|
|
|
|
|
public int granularityCX;
|
|
|
|
|
public int granularityCY;
|
|
|
|
|
public int minInterval;
|
|
|
|
|
public int maxInterval;
|
|
|
|
|
public int rating;
|
|
|
|
|
public OpenSeeWebcamFormat format;
|
|
|
|
|
|
|
|
|
|
// Blackmagic
|
|
|
|
|
public int bmTimescale;
|
|
|
|
|
public int bmFrameduration;
|
|
|
|
|
public int bmModecode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
public class OpenSeeWebcam {
|
|
|
|
|
public OpenSeeWebcamType type = OpenSeeWebcamType.Unknown;
|
|
|
|
|
public int id;
|
|
|
|
|
public string name;
|
|
|
|
|
|
|
|
|
|
// DirectShow
|
|
|
|
|
public string path;
|
|
|
|
|
|
|
|
|
|
// Blackmagic
|
|
|
|
|
public long bmId;
|
|
|
|
|
public int bmFlags;
|
|
|
|
|
|
|
|
|
|
// General
|
|
|
|
|
public OpenSeeWebcamCapability[] caps;
|
|
|
|
|
|
|
|
|
|
public List<string> prettyCaps = null;
|
|
|
|
|
|
|
|
|
|
private List<Tuple<OpenSeeWebcamCapability, int>> splitCaps = null;
|
|
|
|
|
|
|
|
|
|
private int CompareCaps(OpenSeeWebcamCapability a, OpenSeeWebcamCapability b) {
|
2020-09-30 01:03:04 +02:00
|
|
|
if (a.rating < b.rating)
|
|
|
|
|
return -1;
|
|
|
|
|
if (a.rating > b.rating)
|
|
|
|
|
return 1;
|
2020-10-06 23:44:23 +02:00
|
|
|
if (a.minCX * a.minCY > b.minCX * b.minCY)
|
|
|
|
|
return -1;
|
|
|
|
|
if (a.minCX * a.minCY < b.minCX * b.minCY)
|
|
|
|
|
return 1;
|
2020-09-29 17:01:18 +02:00
|
|
|
if (a.minInterval < b.minInterval)
|
|
|
|
|
return -1;
|
|
|
|
|
if (a.minInterval > b.minInterval)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetPrettyCapability(OpenSeeWebcamCapability cap) {
|
|
|
|
|
float fps = 10000000f / (float)cap.minInterval;
|
|
|
|
|
string prettyCap = cap.minCX + "x" + cap.minCY + ", " + fps.ToString("0.##") + "fps (" + cap.format.ToString() + ")";
|
|
|
|
|
return prettyCap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<string> GetPrettyCapabilities() {
|
|
|
|
|
if (splitCaps != null && prettyCaps != null)
|
|
|
|
|
return prettyCaps;
|
|
|
|
|
|
|
|
|
|
splitCaps = new List<Tuple<OpenSeeWebcamCapability, int>>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < caps.Length; i++) {
|
|
|
|
|
if (caps[i].minCX == caps[i].maxCX && caps[i].minCY == caps[i].maxCY)
|
|
|
|
|
splitCaps.Add(new Tuple<OpenSeeWebcamCapability, int>(caps[i], i));
|
|
|
|
|
else {
|
|
|
|
|
OpenSeeWebcamCapability min = caps[i];
|
|
|
|
|
OpenSeeWebcamCapability max = caps[i];
|
|
|
|
|
min.maxCX = min.minCX;
|
|
|
|
|
min.maxCY = min.minCY;
|
|
|
|
|
max.minCX = max.maxCX;
|
|
|
|
|
max.minCY = max.maxCY;
|
|
|
|
|
splitCaps.Add(new Tuple<OpenSeeWebcamCapability, int>(min, i));
|
|
|
|
|
splitCaps.Add(new Tuple<OpenSeeWebcamCapability, int>(max, i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
splitCaps.Sort((a, b) => CompareCaps(a.Item1, b.Item1));
|
|
|
|
|
|
|
|
|
|
prettyCaps = new List<string>();
|
2020-09-29 17:14:55 +02:00
|
|
|
if (type == OpenSeeWebcamType.DirectShow)
|
|
|
|
|
prettyCaps.Add("Default settings");
|
2020-09-29 17:01:18 +02:00
|
|
|
foreach (var cap in splitCaps) {
|
|
|
|
|
prettyCaps.Add(GetPrettyCapability(cap.Item1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return prettyCaps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public OpenSeeWebcamCapability GetCapabilityByPrettyIndex(int index) {
|
2020-09-29 17:14:55 +02:00
|
|
|
int dshowOffset = 0;
|
|
|
|
|
if (type == OpenSeeWebcamType.DirectShow) {
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
OpenSeeWebcamCapability cap = new OpenSeeWebcamCapability();
|
|
|
|
|
cap.id = -1;
|
|
|
|
|
cap.format = OpenSeeWebcamFormat.Any;
|
2020-09-30 01:03:04 +02:00
|
|
|
cap.minInterval = 10000000 / 60;
|
2020-09-29 17:14:55 +02:00
|
|
|
return cap;
|
|
|
|
|
}
|
|
|
|
|
dshowOffset = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (splitCaps == null || index >= splitCaps.Count + dshowOffset || index < 0)
|
2020-09-29 17:01:18 +02:00
|
|
|
throw new InvalidOperationException("Invalid capability index.");
|
2020-09-29 17:14:55 +02:00
|
|
|
|
|
|
|
|
return caps[splitCaps[index - dshowOffset].Item2];
|
2020-09-29 17:01:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[DefaultExecutionOrder(-50)]
|
|
|
|
|
public class OpenSeeWebcamInfo : MonoBehaviour {
|
|
|
|
|
#region DllImport
|
2020-09-29 17:14:55 +02:00
|
|
|
// DirectShow
|
2020-09-29 17:01:18 +02:00
|
|
|
[DllImport("dshowcapture_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "create_capture")]
|
|
|
|
|
private static extern System.IntPtr create_capture_x64();
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json_length")]
|
|
|
|
|
private static extern int get_json_length_x64(System.IntPtr cap);
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json")]
|
|
|
|
|
private static extern void get_json_x64(System.IntPtr cap, [Out] StringBuilder namebuffer, int bufferlength);
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "destroy_capture")]
|
|
|
|
|
private static extern void destroy_capture_x64(System.IntPtr cap);
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "create_capture")]
|
|
|
|
|
private static extern System.IntPtr create_capture_x86();
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json_length")]
|
|
|
|
|
private static extern int get_json_length_x86(System.IntPtr cap);
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json")]
|
|
|
|
|
private static extern void get_json_x86(System.IntPtr cap, [Out] StringBuilder namebuffer, int bufferlength);
|
|
|
|
|
|
|
|
|
|
[DllImport("dshowcapture_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "destroy_capture")]
|
|
|
|
|
private static extern void destroy_capture_x86(System.IntPtr cap);
|
|
|
|
|
|
2020-09-29 17:14:55 +02:00
|
|
|
// Blackmagic
|
2020-09-29 17:01:18 +02:00
|
|
|
[DllImport("libminibmcapture64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json_length")]
|
|
|
|
|
private static extern int bm_get_json_length_x64();
|
|
|
|
|
|
|
|
|
|
[DllImport("libminibmcapture64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json")]
|
|
|
|
|
private static extern void bm_get_json_x64([Out] StringBuilder namebuffer, int bufferlength);
|
|
|
|
|
|
|
|
|
|
[DllImport("libminibmcapture32", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json_length")]
|
|
|
|
|
private static extern int bm_get_json_length_x86();
|
|
|
|
|
|
|
|
|
|
[DllImport("libminibmcapture32", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_json")]
|
|
|
|
|
private static extern void bm_get_json_x86([Out] StringBuilder namebuffer, int bufferlength);
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public List<OpenSeeWebcam> cameras;
|
|
|
|
|
|
|
|
|
|
static private string ListCameraDetails_x64() {
|
|
|
|
|
System.IntPtr cap = create_capture_x64();
|
|
|
|
|
int length = get_json_length_x64(cap);
|
|
|
|
|
StringBuilder buffer = new StringBuilder(length);
|
|
|
|
|
get_json_x64(cap, buffer, length);
|
|
|
|
|
destroy_capture_x64(cap);
|
|
|
|
|
return buffer.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static private string ListCameraDetails_x86() {
|
|
|
|
|
System.IntPtr cap = create_capture_x86();
|
|
|
|
|
int length = get_json_length_x86(cap);
|
|
|
|
|
StringBuilder buffer = new StringBuilder(length);
|
|
|
|
|
get_json_x86(cap, buffer, length);
|
|
|
|
|
destroy_capture_x86(cap);
|
|
|
|
|
return buffer.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static private string ListBlackMagicDetails_x64() {
|
|
|
|
|
int length = bm_get_json_length_x64();
|
|
|
|
|
StringBuilder buffer = new StringBuilder(length);
|
|
|
|
|
bm_get_json_x64(buffer, length);
|
|
|
|
|
return buffer.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static private string ListBlackMagicDetails_x86() {
|
|
|
|
|
int length = bm_get_json_length_x86();
|
|
|
|
|
StringBuilder buffer = new StringBuilder(length);
|
|
|
|
|
bm_get_json_x86(buffer, length);
|
|
|
|
|
return buffer.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-04 23:14:43 +02:00
|
|
|
static public List<OpenSeeWebcam> ListCameraDetails(bool includeBlackMagic) {
|
|
|
|
|
string jsonData = null;
|
|
|
|
|
string bmJsonData = null;
|
2020-09-29 17:01:18 +02:00
|
|
|
if (Environment.Is64BitProcess) {
|
|
|
|
|
jsonData = ListCameraDetails_x64();
|
2020-10-04 23:14:43 +02:00
|
|
|
if (includeBlackMagic)
|
|
|
|
|
bmJsonData = ListBlackMagicDetails_x64();
|
2020-09-29 17:01:18 +02:00
|
|
|
} else {
|
|
|
|
|
jsonData = ListCameraDetails_x86();
|
2020-10-04 23:14:43 +02:00
|
|
|
if (includeBlackMagic)
|
|
|
|
|
bmJsonData = ListBlackMagicDetails_x86();
|
2020-09-29 17:01:18 +02:00
|
|
|
}
|
|
|
|
|
List<OpenSeeWebcam> details = JsonConvert.DeserializeObject<List<OpenSeeWebcam>>(jsonData);
|
|
|
|
|
foreach (var cam in details)
|
|
|
|
|
cam.type = OpenSeeWebcamType.DirectShow;
|
2020-10-04 23:14:43 +02:00
|
|
|
if (includeBlackMagic) {
|
|
|
|
|
List<OpenSeeWebcam> bmDetails = JsonConvert.DeserializeObject<List<OpenSeeWebcam>>(bmJsonData);
|
|
|
|
|
foreach (var cam in bmDetails)
|
|
|
|
|
cam.type = OpenSeeWebcamType.Blackmagic;
|
|
|
|
|
details.AddRange(bmDetails);
|
|
|
|
|
}
|
2020-09-29 17:01:18 +02:00
|
|
|
return details;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Start() {
|
2020-10-04 23:14:43 +02:00
|
|
|
Initialize(false);
|
2020-09-29 17:01:18 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-04 23:14:43 +02:00
|
|
|
public void Initialize(bool includeBlackMagic) {
|
|
|
|
|
cameras = ListCameraDetails(includeBlackMagic);
|
2020-09-29 17:01:18 +02:00
|
|
|
foreach (var camera in cameras)
|
|
|
|
|
camera.GetPrettyCapabilities();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|