forked from homuler/MediaPipeUnityPlugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTextureFramePool.cs
More file actions
127 lines (102 loc) · 3.77 KB
/
Copy pathTextureFramePool.cs
File metadata and controls
127 lines (102 loc) · 3.77 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
using Mediapipe;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TextureFramePool : MonoSingleton<TextureFramePool> {
[SerializeField] readonly int poolSize = 10;
private readonly object dimensionLock = new object();
private int textureWidth = 0;
private int textureHeight = 0;
private Queue<TextureFrame> availableTextureFrames;
/// <remarks>
/// key: texture's native pointer (e.g. OpenGL texture name)
/// </remarks>
private Dictionary<UInt64, TextureFrame> textureFramesInUse;
/// <returns>
/// The total number of texture frames in the pool.
/// </returns>
public int frameCount {
get {
var availableTextureFramesCount = availableTextureFrames == null ? 0 : availableTextureFrames.Count;
var textureFramesInUseCount = textureFramesInUse == null ? 0 : textureFramesInUse.Count;
return availableTextureFramesCount + textureFramesInUseCount;
}
}
void Start() {
availableTextureFrames = new Queue<TextureFrame>(poolSize);
textureFramesInUse = new Dictionary<UInt64, TextureFrame>();
}
public void SetDimension(int textureWidth, int textureHeight) {
lock(dimensionLock) {
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
}
}
public TextureFrameRequest RequestNextTextureFrame(Action<TextureFrame> callback) {
return new TextureFrameRequest(this, callback);
}
private void OnTextureFrameRelease(UInt64 textureName, IntPtr syncTokenPtr) {
lock(((ICollection)textureFramesInUse).SyncRoot) {
if (!textureFramesInUse.TryGetValue(textureName, out var textureFrame)) {
Debug.LogWarning("The released texture does not belong to the pool");
return;
}
textureFramesInUse.Remove(textureName);
if (frameCount > poolSize || IsStale(textureFrame)) {
return;
}
if (syncTokenPtr != IntPtr.Zero) {
using (var glSyncToken = new GlSyncPoint(syncTokenPtr)) {
glSyncToken.Wait();
}
}
availableTextureFrames.Enqueue(textureFrame);
}
}
private bool IsStale(TextureFrame textureFrame) {
lock(dimensionLock) {
return textureFrame.width != textureWidth || textureFrame.height != textureHeight;
}
}
private TextureFrame CreateNewTextureFrame() {
lock(dimensionLock) {
return new TextureFrame(textureWidth, textureHeight, (GlTextureBuffer.DeletionCallback)OnTextureFrameRelease);
}
}
private IEnumerator WaitForTextureFrame(Action<TextureFrame> callback) {
TextureFrame nextFrame = null;
lock(((ICollection)availableTextureFrames).SyncRoot) {
yield return new WaitUntil(() => {
return poolSize > frameCount || availableTextureFrames.Count > 0;
});
while (availableTextureFrames.Count > 0) {
var textureFrame = availableTextureFrames.Dequeue();
if (!IsStale(textureFrame)) {
nextFrame = textureFrame;
break;
}
}
if (nextFrame == null) {
nextFrame = CreateNewTextureFrame();
}
}
callback(nextFrame);
lock(((ICollection)textureFramesInUse).SyncRoot) {
textureFramesInUse.Add((UInt64)nextFrame.GetNativeTexturePtr(false), nextFrame);
}
}
public class TextureFrameRequest : CustomYieldInstruction {
public TextureFrame textureFrame { get; private set; }
private TextureFramePool textureFramePool;
public override bool keepWaiting {
get { return textureFrame == null; }
}
public TextureFrameRequest(TextureFramePool textureFramePool, Action<TextureFrame> callback) : base() {
textureFramePool.StartCoroutine(textureFramePool.WaitForTextureFrame((TextureFrame textureFrame) => {
callback(textureFrame);
this.textureFrame = textureFrame;
}));
}
}
}