-
-
Notifications
You must be signed in to change notification settings - Fork 484
/
Copy pathTextureFramePool.cs
161 lines (138 loc) · 4.15 KB
/
TextureFramePool.cs
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
// Copyright (c) 2021 homuler
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Mediapipe.Unity
{
public class TextureFramePool : MonoBehaviour
{
private const string _TAG = nameof(TextureFramePool);
[SerializeField] private int _poolSize = 10;
private readonly object _formatLock = new object();
private int _textureWidth = 0;
private int _textureHeight = 0;
private TextureFormat _format = TextureFormat.RGBA32;
private Queue<TextureFrame> _availableTextureFrames;
/// <remarks>
/// key: TextureFrame's instance ID
/// </remarks>
private Dictionary<Guid, 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;
}
}
private void Start()
{
_availableTextureFrames = new Queue<TextureFrame>(_poolSize);
_textureFramesInUse = new Dictionary<Guid, TextureFrame>();
}
private void OnDestroy()
{
lock (((ICollection)_availableTextureFrames).SyncRoot)
{
_availableTextureFrames.Clear();
_availableTextureFrames = null;
}
lock (((ICollection)_textureFramesInUse).SyncRoot)
{
foreach (var textureFrame in _textureFramesInUse.Values)
{
textureFrame.OnRelease.RemoveListener(OnTextureFrameRelease);
}
_textureFramesInUse.Clear();
_textureFramesInUse = null;
}
}
public void ResizeTexture(int textureWidth, int textureHeight, TextureFormat format)
{
lock (_formatLock)
{
_textureWidth = textureWidth;
_textureHeight = textureHeight;
_format = format;
}
}
public void ResizeTexture(int textureWidth, int textureHeight)
{
ResizeTexture(textureWidth, textureHeight, _format);
}
public bool TryGetTextureFrame(out TextureFrame outFrame)
{
TextureFrame nextFrame = null;
lock (((ICollection)_availableTextureFrames).SyncRoot)
{
if (_poolSize <= frameCount)
{
while (_availableTextureFrames.Count > 0)
{
var textureFrame = _availableTextureFrames.Dequeue();
if (!IsStale(textureFrame))
{
nextFrame = textureFrame;
break;
}
}
}
else
{
nextFrame = CreateNewTextureFrame();
}
}
if (nextFrame == null)
{
outFrame = null;
return false;
}
lock (((ICollection)_textureFramesInUse).SyncRoot)
{
_textureFramesInUse.Add(nextFrame.GetInstanceID(), nextFrame);
}
nextFrame.WaitUntilReleased();
outFrame = nextFrame;
return true;
}
private void OnTextureFrameRelease(TextureFrame textureFrame)
{
lock (((ICollection)_textureFramesInUse).SyncRoot)
{
if (!_textureFramesInUse.Remove(textureFrame.GetInstanceID()))
{
// won't be run
Logger.LogWarning(_TAG, "The released texture does not belong to the pool");
return;
}
if (frameCount > _poolSize || IsStale(textureFrame))
{
return;
}
_availableTextureFrames.Enqueue(textureFrame);
}
}
private bool IsStale(TextureFrame textureFrame)
{
lock (_formatLock)
{
return textureFrame.width != _textureWidth || textureFrame.height != _textureHeight;
}
}
private TextureFrame CreateNewTextureFrame()
{
var textureFrame = new TextureFrame(_textureWidth, _textureHeight, _format);
textureFrame.OnRelease.AddListener(OnTextureFrameRelease);
return textureFrame;
}
}
}