Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/samples/directx/d3d9_interop.cpp
16337 views
1
/*
2
// A sample program demonstrating interoperability of OpenCV cv::UMat with Direct X surface
3
// At first, the data obtained from video file or camera and placed onto Direct X surface,
4
// following mapping of this Direct X surface to OpenCV cv::UMat and call cv::Blur function.
5
// The result is mapped back to Direct X surface and rendered through Direct X API.
6
*/
7
8
#define WIN32_LEAN_AND_MEAN
9
#include <windows.h>
10
#include <d3d9.h>
11
12
#include "opencv2/core.hpp"
13
#include "opencv2/core/directx.hpp"
14
#include "opencv2/core/ocl.hpp"
15
#include "opencv2/imgproc.hpp"
16
#include "opencv2/videoio.hpp"
17
18
#include "d3dsample.hpp"
19
20
#pragma comment (lib, "d3d9.lib")
21
22
23
class D3D9WinApp : public D3DSample
24
{
25
public:
26
D3D9WinApp(int width, int height, std::string& window_name, cv::VideoCapture& cap) :
27
D3DSample(width, height, window_name, cap) {}
28
29
~D3D9WinApp() {}
30
31
int create(void)
32
{
33
// base initialization
34
D3DSample::create();
35
36
// initialize DirectX
37
HRESULT r;
38
39
m_pD3D9 = ::Direct3DCreate9(D3D_SDK_VERSION);
40
if (NULL == m_pD3D9)
41
{
42
return EXIT_FAILURE;
43
}
44
45
DWORD flags = D3DCREATE_HARDWARE_VERTEXPROCESSING |
46
D3DCREATE_PUREDEVICE |
47
D3DCREATE_NOWINDOWCHANGES |
48
D3DCREATE_MULTITHREADED |
49
D3DCREATE_FPU_PRESERVE;
50
51
D3DPRESENT_PARAMETERS d3dpp;
52
::ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
53
54
d3dpp.Windowed = true;
55
d3dpp.Flags = 0;
56
d3dpp.BackBufferCount = 0;
57
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
58
d3dpp.BackBufferHeight = m_height;
59
d3dpp.BackBufferWidth = m_width;
60
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
61
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
62
d3dpp.hDeviceWindow = m_hWnd;
63
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
64
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
65
66
r = m_pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, flags, &d3dpp, &m_pD3D9Dev);
67
if (FAILED(r))
68
{
69
return EXIT_FAILURE;
70
}
71
72
r = m_pD3D9Dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer);
73
if (FAILED(r))
74
{
75
return EXIT_FAILURE;
76
}
77
78
r = m_pD3D9Dev->CreateOffscreenPlainSurface(m_width, m_height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pSurface, NULL);
79
if (FAILED(r))
80
{
81
std::cerr << "Can't create surface for result" << std::endl;
82
return EXIT_FAILURE;
83
}
84
85
// initialize OpenCL context of OpenCV lib from DirectX
86
if (cv::ocl::haveOpenCL())
87
{
88
m_oclCtx = cv::directx::ocl::initializeContextFromDirect3DDevice9(m_pD3D9Dev);
89
}
90
91
m_oclDevName = cv::ocl::useOpenCL() ?
92
cv::ocl::Context::getDefault().device(0).name() :
93
"No OpenCL device";
94
95
return EXIT_SUCCESS;
96
} // create()
97
98
99
// get media data on DX surface for further processing
100
int get_surface(LPDIRECT3DSURFACE9* ppSurface)
101
{
102
HRESULT r;
103
104
if (!m_cap.read(m_frame_bgr))
105
return EXIT_FAILURE;
106
107
cv::cvtColor(m_frame_bgr, m_frame_rgba, cv::COLOR_BGR2BGRA);
108
109
D3DLOCKED_RECT memDesc = { 0, NULL };
110
RECT rc = { 0, 0, m_width, m_height };
111
112
r = m_pSurface->LockRect(&memDesc, &rc, 0);
113
if (FAILED(r))
114
{
115
return r;
116
}
117
118
cv::Mat m(m_height, m_width, CV_8UC4, memDesc.pBits, memDesc.Pitch);
119
// copy video frame data to surface
120
m_frame_rgba.copyTo(m);
121
122
r = m_pSurface->UnlockRect();
123
if (FAILED(r))
124
{
125
return r;
126
}
127
128
*ppSurface = m_pSurface;
129
130
return EXIT_SUCCESS;
131
} // get_surface()
132
133
134
// process and render media data
135
int render()
136
{
137
try
138
{
139
if (m_shutdown)
140
return EXIT_SUCCESS;
141
142
// capture user input once
143
MODE mode = (m_mode == MODE_GPU_NV12) ? MODE_GPU_RGBA : m_mode;
144
145
HRESULT r;
146
LPDIRECT3DSURFACE9 pSurface;
147
148
r = get_surface(&pSurface);
149
if (FAILED(r))
150
{
151
return EXIT_FAILURE;
152
}
153
154
m_timer.reset();
155
m_timer.start();
156
157
switch (mode)
158
{
159
case MODE_CPU:
160
{
161
// process video frame on CPU
162
D3DLOCKED_RECT memDesc = { 0, NULL };
163
RECT rc = { 0, 0, m_width, m_height };
164
165
r = pSurface->LockRect(&memDesc, &rc, 0);
166
if (FAILED(r))
167
{
168
return EXIT_FAILURE;
169
}
170
171
cv::Mat m(m_height, m_width, CV_8UC4, memDesc.pBits, memDesc.Pitch);
172
173
if (m_demo_processing)
174
{
175
// blur D3D9 surface with OpenCV on CPU
176
cv::blur(m, m, cv::Size(15, 15));
177
}
178
179
r = pSurface->UnlockRect();
180
if (FAILED(r))
181
{
182
return EXIT_FAILURE;
183
}
184
185
break;
186
}
187
188
case MODE_GPU_RGBA:
189
{
190
// process video frame on GPU
191
cv::UMat u;
192
193
cv::directx::convertFromDirect3DSurface9(pSurface, u);
194
195
if (m_demo_processing)
196
{
197
// blur D3D9 surface with OpenCV on GPU with OpenCL
198
cv::blur(u, u, cv::Size(15, 15));
199
}
200
201
cv::directx::convertToDirect3DSurface9(u, pSurface);
202
203
break;
204
}
205
206
} // switch
207
208
m_timer.stop();
209
210
print_info(pSurface, mode, m_timer.getTimeMilli(), m_oclDevName);
211
212
// traditional DX render pipeline:
213
// BitBlt surface to backBuffer and flip backBuffer to frontBuffer
214
r = m_pD3D9Dev->StretchRect(pSurface, NULL, m_pBackBuffer, NULL, D3DTEXF_NONE);
215
if (FAILED(r))
216
{
217
return EXIT_FAILURE;
218
}
219
220
// present the back buffer contents to the display
221
r = m_pD3D9Dev->Present(NULL, NULL, NULL, NULL);
222
if (FAILED(r))
223
{
224
return EXIT_FAILURE;
225
}
226
} // try
227
228
catch (cv::Exception& e)
229
{
230
std::cerr << "Exception: " << e.what() << std::endl;
231
return 10;
232
}
233
234
return EXIT_SUCCESS;
235
} // render()
236
237
238
void print_info(LPDIRECT3DSURFACE9 pSurface, int mode, double time, cv::String oclDevName)
239
{
240
HDC hDC;
241
242
HRESULT r = pSurface->GetDC(&hDC);
243
if (FAILED(r))
244
{
245
return;
246
}
247
248
HFONT hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
249
250
HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
251
252
if (hOldFont)
253
{
254
TEXTMETRIC tm;
255
::GetTextMetrics(hDC, &tm);
256
257
char buf[256];
258
int y = 0;
259
260
buf[0] = 0;
261
sprintf(buf, "mode: %s", m_modeStr[mode].c_str());
262
::TextOut(hDC, 0, y, buf, (int)strlen(buf));
263
264
y += tm.tmHeight;
265
buf[0] = 0;
266
sprintf(buf, m_demo_processing ? "blur frame" : "copy frame");
267
::TextOut(hDC, 0, y, buf, (int)strlen(buf));
268
269
y += tm.tmHeight;
270
buf[0] = 0;
271
sprintf(buf, "time: %4.1f msec", time);
272
::TextOut(hDC, 0, y, buf, (int)strlen(buf));
273
274
y += tm.tmHeight;
275
buf[0] = 0;
276
sprintf(buf, "OpenCL device: %s", oclDevName.c_str());
277
::TextOut(hDC, 0, y, buf, (int)strlen(buf));
278
279
::SelectObject(hDC, hOldFont);
280
}
281
282
r = pSurface->ReleaseDC(hDC);
283
284
return;
285
} // print_info()
286
287
288
int cleanup(void)
289
{
290
SAFE_RELEASE(m_pSurface);
291
SAFE_RELEASE(m_pBackBuffer);
292
SAFE_RELEASE(m_pD3D9Dev);
293
SAFE_RELEASE(m_pD3D9);
294
D3DSample::cleanup();
295
return EXIT_SUCCESS;
296
} // cleanup()
297
298
private:
299
LPDIRECT3D9 m_pD3D9;
300
LPDIRECT3DDEVICE9 m_pD3D9Dev;
301
LPDIRECT3DSURFACE9 m_pBackBuffer;
302
LPDIRECT3DSURFACE9 m_pSurface;
303
cv::ocl::Context m_oclCtx;
304
cv::String m_oclPlatformName;
305
cv::String m_oclDevName;
306
};
307
308
309
// main func
310
int main(int argc, char** argv)
311
{
312
std::string title = "D3D9 interop sample";
313
return d3d_app<D3D9WinApp>(argc, argv, title);
314
}
315
316