@@ -45,6 +45,21 @@ namespace FFmpegInteropX
45
45
}
46
46
}
47
47
48
+ public:
49
+
50
+ virtual ~D3D11VideoSampleProvider ()
51
+ {
52
+ ReleaseTrackedSamples ();
53
+ }
54
+
55
+ virtual void Flush () override
56
+ {
57
+ UncompressedVideoSampleProvider::Flush ();
58
+ ReturnTrackedSamples ();
59
+ }
60
+
61
+ internal:
62
+
48
63
virtual HRESULT CreateBufferFromFrame (IBuffer^* pBuffer, IDirect3DSurface^* surface, AVFrame* avFrame, int64_t & framePts, int64_t & frameDuration) override
49
64
{
50
65
HRESULT hr = S_OK;
@@ -120,20 +135,46 @@ namespace FFmpegInteropX
120
135
{
121
136
if (sample->Direct3D11Surface )
122
137
{
123
- samples.insert (reinterpret_cast <IUnknown*>(sample));
124
- sample->Processed += ref new Windows::Foundation::TypedEventHandler<Windows::Media::Core::MediaStreamSample^, Platform::Object^>(this , &D3D11VideoSampleProvider::OnProcessed);
138
+ std::lock_guard<std::mutex> lock (samplesMutex);
139
+
140
+ // AddRef the sample on native interface to prevent it from being collected before Processed is called
141
+ auto sampleNative = reinterpret_cast <IUnknown*>(sample);
142
+ sampleNative->AddRef ();
143
+
144
+ // Attach Processed event and store in samples list
145
+ auto token = sample->Processed += ref new Windows::Foundation::TypedEventHandler<Windows::Media::Core::MediaStreamSample^, Platform::Object^>(this , &D3D11VideoSampleProvider::OnProcessed);
146
+ trackedSamples[sampleNative] = token;
125
147
}
126
148
127
149
return UncompressedVideoSampleProvider::SetSampleProperties (sample);
128
150
};
129
151
130
152
void OnProcessed (Windows::Media::Core::MediaStreamSample^ sender, Platform::Object^ args)
131
153
{
132
- auto unknown = reinterpret_cast <IUnknown*>(sender->Direct3D11Surface );
154
+ std::lock_guard<std::mutex> lock (samplesMutex);
155
+
156
+ auto sampleNative = reinterpret_cast <IUnknown*>(sender);
157
+ auto mapEntry = trackedSamples.find (sampleNative);
158
+ if (mapEntry == trackedSamples.end ())
159
+ {
160
+ // sample was already released during Flush() or destructor
161
+ }
162
+ else
163
+ {
164
+ // Release the sample's native interface and return texture to pool
165
+ sampleNative->Release ();
166
+ trackedSamples.erase (mapEntry);
167
+
168
+ ReturnTextureToPool (sender);
169
+ }
170
+ }
171
+
172
+ void ReturnTextureToPool (MediaStreamSample^ sample)
173
+ {
133
174
IDXGISurface* surface = NULL ;
134
175
ID3D11Texture2D* texture = NULL ;
135
176
136
- HRESULT hr = DirectXInteropHelper::GetDXGISurface (sender ->Direct3D11Surface , &surface);
177
+ HRESULT hr = DirectXInteropHelper::GetDXGISurface (sample ->Direct3D11Surface , &surface);
137
178
138
179
if (SUCCEEDED (hr))
139
180
{
@@ -145,12 +186,45 @@ namespace FFmpegInteropX
145
186
texturePool->ReturnTexture (texture);
146
187
}
147
188
148
- samples.erase (reinterpret_cast <IUnknown*>(sender));
149
-
150
189
SAFE_RELEASE (surface);
151
190
SAFE_RELEASE (texture);
152
191
}
153
192
193
+ void ReleaseTrackedSamples ()
194
+ {
195
+ std::lock_guard<std::mutex> lock (samplesMutex);
196
+ for (auto entry : trackedSamples)
197
+ {
198
+ // detach Processed event and release native interface
199
+ auto sampleNative = entry.first ;
200
+ auto sample = reinterpret_cast <MediaStreamSample^>(sampleNative);
201
+
202
+ sample->Processed -= entry.second ;
203
+ sampleNative->Release ();
204
+ }
205
+
206
+ trackedSamples.clear ();
207
+ }
208
+
209
+ void ReturnTrackedSamples ()
210
+ {
211
+ std::lock_guard<std::mutex> lock (samplesMutex);
212
+ for (auto entry : trackedSamples)
213
+ {
214
+ // detach Processed event and release native interface
215
+ auto sampleNative = entry.first ;
216
+ auto sample = reinterpret_cast <MediaStreamSample^>(sampleNative);
217
+
218
+ sample->Processed -= entry.second ;
219
+ sampleNative->Release ();
220
+
221
+ // return texture to pool
222
+ ReturnTextureToPool (sample);
223
+ }
224
+
225
+ trackedSamples.clear ();
226
+ }
227
+
154
228
virtual HRESULT SetHardwareDevice (ID3D11Device* device, ID3D11DeviceContext* context, AVBufferRef* avHardwareContext) override
155
229
{
156
230
HRESULT hr = S_OK;
@@ -379,8 +453,8 @@ namespace FFmpegInteropX
379
453
}
380
454
381
455
TexturePool^ texturePool;
382
- std::set <IUnknown*> samples ;
383
-
456
+ std::map <IUnknown*,EventRegistrationToken> trackedSamples ;
457
+ std::mutex samplesMutex;
384
458
};
385
459
}
386
460
0 commit comments