AsyncConversion.cs
7.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace UnityEngine.XR.ARSubsystems
{
public partial struct XRCpuImage
{
/// <summary>
/// Holds information related to an asynchronous camera image conversion request. Returned by
/// <see cref="XRCpuImage.ConvertAsync(ConversionParams)"/>.
/// </summary>
public struct AsyncConversion : IDisposable, IEquatable<AsyncConversion>
{
XRCpuImage.Api m_Api;
int m_RequestId;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle m_SafetyHandle;
#endif
/// <summary>
/// The <see cref="ConversionParams"/> used during the conversion.
/// </summary>
/// <value>
/// The parameters used during the conversion.
/// </value>
public ConversionParams conversionParams { get; private set; }
/// <summary>
/// The status of the request.
/// </summary>
/// <value>
/// The status of the request.
/// </value>
public AsyncConversionStatus status => m_Api?.GetAsyncRequestStatus(m_RequestId) ?? AsyncConversionStatus.Disposed;
/// <summary>
/// Start the image conversion using this class to interact with the asynchronous conversion and results.
/// </summary>
/// <param name="api">The cpu image api performing the image conversion.</param>
/// <param name="nativeHandle">The native handle for the camera image.</param>
/// <param name="conversionParams">The parameters for image conversion.</param>
internal AsyncConversion(XRCpuImage.Api api, int nativeHandle, ConversionParams conversionParams)
{
m_Api = api;
m_RequestId = m_Api.ConvertAsync(nativeHandle, conversionParams);
this.conversionParams = conversionParams;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
m_SafetyHandle = AtomicSafetyHandle.Create();
#endif
}
/// <summary>
/// Get the raw image data. The returned <c>NativeArray</c> is a direct "view" into the native memory. The
/// memory is only valid until this <see cref="AsyncConversion"/> is disposed.
/// </summary>
/// <typeparam name="T">The type of data to return. No conversion is performed based on the type; this is
/// merely for access convenience.</typeparam>
/// <returns>
/// A new <c>NativeArray</c> representing the raw image data. This method may fail; use
/// <c>NativeArray.IsCreated</c> to determine the validity of the data.
/// </returns>
/// <exception cref="System.InvalidOperationException">Thrown if the asynchronous conversion
/// <see cref="status"/> is not <see cref="AsyncConversionStatus.Ready"/> or if the conversion is
/// invalid.</exception>
public unsafe NativeArray<T> GetData<T>() where T : struct
{
if (status != AsyncConversionStatus.Ready)
throw new InvalidOperationException("Async request is not ready.");
IntPtr dataPtr;
int dataLength;
if (m_Api.TryGetAsyncRequestData(m_RequestId, out dataPtr, out dataLength))
{
int stride = UnsafeUtility.SizeOf<T>();
var array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<T>(
(void*)dataPtr, dataLength / stride, Allocator.None);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, m_SafetyHandle);
#endif
return array;
}
throw new InvalidOperationException("The XRAsyncCameraImageConversion is not valid.");
}
/// <summary>
/// Dispose native resources associated with this request, including the raw image data. The `NativeArray`
/// returned by <see cref="GetData{T}"/> is invalidated immediately after calling <see cref="Dispose"/>.
/// </summary>
public void Dispose()
{
if (m_Api == null || m_RequestId == 0)
return;
m_Api.DisposeAsyncRequest(m_RequestId);
m_Api = null;
m_RequestId = 0;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.Release(m_SafetyHandle);
#endif
}
/// <summary>
/// Generates a hash suitable for use with containers like `HashSet` and `Dictionary`.
/// </summary>
/// <returns>A hash code generated from this object's fields.</returns>
public override int GetHashCode() => HashCode.Combine(
conversionParams.GetHashCode(),
m_RequestId.GetHashCode(),
HashCode.ReferenceHash(m_Api));
/// <summary>
/// Tests for equality.
/// </summary>
/// <param name="obj">The `object` to compare against.</param>
/// <returns>`True` if <paramref name="obj"/> is of type <see cref="AsyncConversion"/> and
/// <see cref="Equals(AsyncConversion)"/> also returns `true`; otherwise `false`.</returns>
public override bool Equals(object obj)
{
return ((obj is AsyncConversion) && Equals((AsyncConversion)obj));
}
/// <summary>
/// Tests for equality.
/// </summary>
/// <param name="other">The other <see cref="AsyncConversion"/> to compare against.</param>
/// <returns>`True` if every field in <paramref name="other"/> is equal to this <see cref="AsyncConversion"/>, otherwise false.</returns>
public bool Equals(AsyncConversion other)
{
return
(conversionParams.Equals(other.conversionParams)) &&
(m_RequestId == other.m_RequestId) &&
(m_Api == other.m_Api);
}
/// <summary>
/// Tests for equality. Same as <see cref="Equals(AsyncConversion)"/>.
/// </summary>
/// <param name="lhs">The <see cref="AsyncConversion"/> to compare with <paramref name="rhs"/>.</param>
/// <param name="rhs">The <see cref="AsyncConversion"/> to compare with <paramref name="lhs"/>.</param>
/// <returns>`True` if <paramref name="lhs"/> is equal to <paramref name="rhs"/>, otherwise `false`.</returns>
public static bool operator ==(AsyncConversion lhs, AsyncConversion rhs) => lhs.Equals(rhs);
/// <summary>
/// Tests for inequality. Same as `!`<see cref="Equals(AsyncConversion)"/>.
/// </summary>
/// <param name="lhs">The <see cref="AsyncConversion"/> to compare with <paramref name="rhs"/>.</param>
/// <param name="rhs">The <see cref="AsyncConversion"/> to compare with <paramref name="lhs"/>.</param>
/// <returns>`True` if <paramref name="lhs"/> is not equal to <paramref name="rhs"/>, otherwise `false`.</returns>
public static bool operator !=(AsyncConversion lhs, AsyncConversion rhs) => !lhs.Equals(rhs);
/// <summary>
/// Generates a string representation of this <see cref="AsyncConversion"/>.
/// </summary>
/// <returns>A string representation of the conversion parameters.</returns>
public override string ToString() => $"ConversionParams: {conversionParams}";
}
}
}