• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  2013, Cisco Systems
4  *     All rights reserved.
5  *
6  *     Redistribution and use in source and binary forms, with or without
7  *     modification, are permitted provided that the following conditions
8  *     are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *
13  *        * Redistributions in binary form must reproduce the above copyright
14  *          notice, this list of conditions and the following disclaimer in
15  *          the documentation and/or other materials provided with the
16  *          distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *     POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 #include "d3d9_utils.h"
34 
35 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36 void Write2File (FILE* pFp, unsigned char* pData[3], int iStride[2], int iWidth, int iHeight);
37 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38 
39 #ifdef ENABLE_DISPLAY_MODULE
40 
41 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
42 #define IDM_ABOUT                       104
43 #define IDM_EXIT                        105
44 #define IDI_TESTSHARESURFACE            107
45 #define IDI_SMALL                       108
46 #define IDC_TESTSHARESURFACE            109
47 
48 #define NV12_FORMAT  MAKEFOURCC('N','V','1','2')
49 
50 typedef struct {
51   UINT      uiWidth;
52   UINT      uiHeight;
53   D3DFORMAT D3Dformat;
54   D3DPOOL   D3DPool;
55 } SHandleInfo;
56 
57 #define SAFE_RELEASE(p) if(p) { (p)->Release(); (p) = NULL; }
58 #define SAFE_FREE(p)    if(p) { free (p); (p) = NULL; }
59 
60 HRESULT Dump2Surface (void* pDst[3], void* pSurface, int iWidth, int iHeight, int iStride[2]);
61 HRESULT InitWindow (HWND* hWnd);
62 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
63 
64 typedef HRESULT (WINAPI* pFnCreateD3D9Ex) (UINT SDKVersion, IDirect3D9Ex**);
65 typedef LPDIRECT3D9 (WINAPI* pFnCreateD3D9) (UINT SDKVersion);
66 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67 
CD3D9Utils()68 CD3D9Utils::CD3D9Utils() {
69   m_hDll        = NULL;
70   m_hWnd        = NULL;
71   m_pDumpYUV    = NULL;
72 
73   m_bInitDone   = FALSE;
74 
75   m_lpD3D9                = NULL;
76   m_lpD3D9Device          = NULL;
77   m_lpD3D9RawSurfaceShare = NULL;
78   m_nWidth  = 0;
79   m_nHeight = 0;
80   // coverity scan uninitial
81   ZeroMemory (&m_d3dpp, sizeof (m_d3dpp));
82 }
83 
~CD3D9Utils()84 CD3D9Utils::~CD3D9Utils() {
85   Uninit();
86 }
87 
Init(BOOL bWindowed)88 HRESULT CD3D9Utils::Init (BOOL bWindowed) {
89   if (m_bInitDone)
90     return S_OK;
91 
92   m_hDll = LoadLibrary (TEXT ("d3d9.dll"));
93   pFnCreateD3D9 pCreateD3D9 = NULL;
94   if (m_hDll)
95     pCreateD3D9 = (pFnCreateD3D9) GetProcAddress (m_hDll, TEXT ("Direct3DCreate9"));
96   else
97     return E_FAIL;
98 
99   m_lpD3D9 = pCreateD3D9 (D3D_SDK_VERSION);
100 
101   return bWindowed ? InitWindow (&m_hWnd) : S_OK;
102 }
103 
Uninit()104 HRESULT CD3D9Utils::Uninit() {
105   SAFE_RELEASE (m_lpD3D9RawSurfaceShare);
106   SAFE_RELEASE (m_lpD3D9Device);
107   SAFE_RELEASE (m_lpD3D9);
108   SAFE_FREE (m_pDumpYUV);
109 
110   if (m_hDll) {
111     FreeLibrary (m_hDll);
112     m_hDll = NULL;
113   }
114 
115   return S_OK;
116 }
117 
Process(void * pDst[3],SBufferInfo * pInfo,FILE * pFp)118 HRESULT CD3D9Utils::Process (void* pDst[3], SBufferInfo* pInfo, FILE* pFp) {
119   HRESULT hResult = E_FAIL;
120 
121   if (pDst == NULL || pInfo == NULL)
122     return hResult;
123 
124   BOOL bWindowed = pFp ? FALSE : TRUE;
125   BOOL bNeedD3D9 = ! (!bWindowed);
126   if (!m_bInitDone)
127     m_bInitDone = !bNeedD3D9;
128 
129   if (!m_bInitDone) {
130     hResult = Init (bWindowed);
131     if (SUCCEEDED (hResult))
132       m_bInitDone = TRUE;
133   }
134 
135   if (m_bInitDone) {
136     if (bWindowed) {
137       hResult = Render (pDst, pInfo);
138       Sleep (30);
139     } else if (pFp) {
140       hResult = Dump (pDst, pInfo, pFp);
141       Sleep (0);
142     }
143   }
144 
145   return hResult;
146 }
147 
Render(void * pDst[3],SBufferInfo * pInfo)148 HRESULT CD3D9Utils::Render (void* pDst[3], SBufferInfo* pInfo) {
149   HRESULT hResult = E_FAIL;
150 
151   if (!pInfo)
152     return E_FAIL;
153 
154   if (m_nWidth != pInfo->UsrData.sSystemBuffer.iWidth
155       || m_nHeight != pInfo->UsrData.sSystemBuffer.iHeight) {
156     m_nWidth = pInfo->UsrData.sSystemBuffer.iWidth;
157     m_nHeight = pInfo->UsrData.sSystemBuffer.iHeight;
158     SAFE_RELEASE (m_lpD3D9RawSurfaceShare);
159     SAFE_RELEASE (m_lpD3D9Device);
160   }
161   hResult = InitResource (NULL, pInfo);
162   if (SUCCEEDED (hResult))
163     hResult = Dump2Surface (pDst, m_lpD3D9RawSurfaceShare, pInfo->UsrData.sSystemBuffer.iWidth,
164                             pInfo->UsrData.sSystemBuffer.iHeight, pInfo->UsrData.sSystemBuffer.iStride);
165 
166   if (SUCCEEDED (hResult)) {
167     IDirect3DSurface9* pBackBuffer = NULL;
168     hResult = m_lpD3D9Device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
169     hResult = m_lpD3D9Device->StretchRect (m_lpD3D9RawSurfaceShare, NULL, pBackBuffer, NULL, D3DTEXF_NONE);
170     hResult = m_lpD3D9Device->Present (0, 0, NULL, NULL);
171   }
172 
173   return hResult;
174 }
175 
Dump(void * pDst[3],SBufferInfo * pInfo,FILE * pFp)176 HRESULT CD3D9Utils::Dump (void* pDst[3], SBufferInfo* pInfo, FILE* pFp) {
177   HRESULT hResult = E_FAIL;
178   int iStride[2];
179   int iWidth;
180   int iHeight;
181 
182   iWidth = pInfo->UsrData.sSystemBuffer.iWidth;
183   iHeight = pInfo->UsrData.sSystemBuffer.iHeight;
184   iStride[0] = pInfo->UsrData.sSystemBuffer.iStride[0];
185   iStride[1] = pInfo->UsrData.sSystemBuffer.iStride[1];
186 
187   if (pDst[0] && pDst[1] && pDst[2])
188     Write2File (pFp, (unsigned char**)pDst, iStride, iWidth, iHeight);
189 
190   return hResult;
191 }
192 
InitResource(void * pSharedHandle,SBufferInfo * pInfo)193 HRESULT CD3D9Utils::InitResource (void* pSharedHandle, SBufferInfo* pInfo) {
194   HRESULT hResult = S_OK;
195 
196   // coverity scan uninitial
197   int iWidth = 0;
198   int iHeight = 0;
199   D3DFORMAT D3Dformat = (D3DFORMAT)D3DFMT_UNKNOWN;
200   D3DPOOL D3Dpool = (D3DPOOL)D3DPOOL_DEFAULT;
201 
202   if (pInfo == NULL)
203     return E_FAIL;
204 
205   if (m_lpD3D9Device == NULL && m_lpD3D9RawSurfaceShare == NULL) {
206     HMONITOR hMonitorWnd = MonitorFromWindow (m_hWnd, MONITOR_DEFAULTTONULL);
207 
208     UINT uiAdapter = D3DADAPTER_DEFAULT;
209     UINT uiCnt = m_lpD3D9->GetAdapterCount();
210     for (UINT i = 0; i < uiCnt; i++) {
211       HMONITOR hMonitor = m_lpD3D9->GetAdapterMonitor (i);
212       if (hMonitor == hMonitorWnd) {
213         uiAdapter = i;
214         break;
215       }
216     }
217 
218     D3DDISPLAYMODE D3DDisplayMode;
219     hResult = m_lpD3D9->GetAdapterDisplayMode (uiAdapter, &D3DDisplayMode);
220 
221     D3DDEVTYPE D3DDevType = D3DDEVTYPE_HAL;
222     DWORD dwBehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
223 
224     ZeroMemory (&m_d3dpp, sizeof (m_d3dpp));
225     m_d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
226     m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
227     m_d3dpp.BackBufferFormat = D3DDisplayMode.Format;
228     m_d3dpp.Windowed = TRUE;
229     m_d3dpp.hDeviceWindow = m_hWnd;
230     m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
231     hResult = m_lpD3D9->CreateDevice (uiAdapter, D3DDevType, NULL, dwBehaviorFlags, &m_d3dpp, &m_lpD3D9Device);
232     iWidth = pInfo->UsrData.sSystemBuffer.iWidth;
233     iHeight = pInfo->UsrData.sSystemBuffer.iHeight;
234     D3Dformat = (D3DFORMAT)NV12_FORMAT;
235     D3Dpool = (D3DPOOL)D3DPOOL_DEFAULT;
236 
237     hResult = m_lpD3D9Device->CreateOffscreenPlainSurface (iWidth, iHeight, (D3DFORMAT)D3Dformat, (D3DPOOL)D3Dpool,
238               &m_lpD3D9RawSurfaceShare, NULL);
239 
240   }
241 
242   if (m_lpD3D9Device == NULL || m_lpD3D9RawSurfaceShare == NULL)
243     hResult = E_FAIL;
244 
245   return hResult;
246 }
247 
CD3D9ExUtils()248 CD3D9ExUtils::CD3D9ExUtils() {
249   m_hDll        = NULL;
250   m_hWnd        = NULL;
251   m_pDumpYUV    = NULL;
252 
253   m_bInitDone   = FALSE;
254 
255   m_lpD3D9                = NULL;
256   m_lpD3D9Device          = NULL;
257   m_lpD3D9RawSurfaceShare = NULL;
258 
259   m_nWidth = 0;
260   m_nHeight = 0;
261   // coverity scan uninitial
262   ZeroMemory (&m_d3dpp, sizeof (m_d3dpp));
263 }
264 
~CD3D9ExUtils()265 CD3D9ExUtils::~CD3D9ExUtils() {
266   Uninit();
267 }
268 
Init(BOOL bWindowed)269 HRESULT CD3D9ExUtils::Init (BOOL bWindowed) {
270   if (m_bInitDone)
271     return S_OK;
272 
273   m_hDll = LoadLibrary (TEXT ("d3d9.dll"));
274   pFnCreateD3D9Ex pCreateD3D9Ex = NULL;
275   if (m_hDll)
276     pCreateD3D9Ex = (pFnCreateD3D9Ex) GetProcAddress (m_hDll, TEXT ("Direct3DCreate9Ex"));
277   else
278     return E_FAIL;
279 
280   pCreateD3D9Ex (D3D_SDK_VERSION, &m_lpD3D9);
281 
282   return bWindowed ? InitWindow (&m_hWnd) : S_OK;
283 }
284 
Uninit()285 HRESULT CD3D9ExUtils::Uninit() {
286   SAFE_RELEASE (m_lpD3D9RawSurfaceShare);
287   SAFE_RELEASE (m_lpD3D9Device);
288   SAFE_RELEASE (m_lpD3D9);
289   SAFE_FREE (m_pDumpYUV);
290 
291   if (m_hDll) {
292     FreeLibrary (m_hDll);
293     m_hDll = NULL;
294   }
295 
296   return S_OK;
297 }
298 
Process(void * pDst[3],SBufferInfo * pInfo,FILE * pFp)299 HRESULT CD3D9ExUtils::Process (void* pDst[3], SBufferInfo* pInfo, FILE* pFp) {
300   HRESULT hResult = E_FAIL;
301 
302   if (pDst == NULL || pInfo == NULL)
303     return hResult;
304 
305   BOOL bWindowed = pFp ? FALSE : TRUE;
306   BOOL bNeedD3D9 = ! (!bWindowed);
307   if (!m_bInitDone)
308     m_bInitDone = !bNeedD3D9;
309 
310   if (!m_bInitDone) {
311     hResult = Init (bWindowed);
312     if (SUCCEEDED (hResult))
313       m_bInitDone = TRUE;
314   }
315 
316   if (m_bInitDone) {
317     if (bWindowed) {
318       hResult = Render (pDst, pInfo);
319       Sleep (30); // set a simple time controlling with default of 30fps
320     } else if (pFp) {
321       hResult = Dump (pDst, pInfo, pFp);
322       Sleep (0);
323     }
324   }
325 
326   return hResult;
327 }
328 
Render(void * pDst[3],SBufferInfo * pInfo)329 HRESULT CD3D9ExUtils::Render (void* pDst[3], SBufferInfo* pInfo) {
330   HRESULT hResult = E_FAIL;
331 
332   if (!pInfo)
333     return E_FAIL;
334 
335   if (m_nWidth != pInfo->UsrData.sSystemBuffer.iWidth
336       || m_nHeight != pInfo->UsrData.sSystemBuffer.iHeight) {
337     m_nWidth = pInfo->UsrData.sSystemBuffer.iWidth;
338     m_nHeight = pInfo->UsrData.sSystemBuffer.iHeight;
339     MoveWindow (m_hWnd, 0, 0, pInfo->UsrData.sSystemBuffer.iWidth, pInfo->UsrData.sSystemBuffer.iHeight, true);
340     SAFE_RELEASE (m_lpD3D9RawSurfaceShare);
341     SAFE_RELEASE (m_lpD3D9Device);
342   }
343   hResult = InitResource (NULL, pInfo);
344   if (SUCCEEDED (hResult))
345     hResult = Dump2Surface (pDst, m_lpD3D9RawSurfaceShare, pInfo->UsrData.sSystemBuffer.iWidth,
346                             pInfo->UsrData.sSystemBuffer.iHeight, pInfo->UsrData.sSystemBuffer.iStride);
347 
348   if (SUCCEEDED (hResult)) {
349     IDirect3DSurface9* pBackBuffer = NULL;
350     hResult = m_lpD3D9Device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
351     hResult = m_lpD3D9Device->StretchRect (m_lpD3D9RawSurfaceShare, NULL, pBackBuffer, NULL, D3DTEXF_NONE);
352     hResult = m_lpD3D9Device->PresentEx (0, 0, NULL, NULL, 0);
353   }
354 
355   return hResult;
356 }
357 
Dump(void * pDst[3],SBufferInfo * pInfo,FILE * pFp)358 HRESULT CD3D9ExUtils::Dump (void* pDst[3], SBufferInfo* pInfo, FILE* pFp) {
359   HRESULT hResult = E_FAIL;
360   int iStride[2];
361   int iWidth;
362   int iHeight;
363 
364   iWidth = pInfo->UsrData.sSystemBuffer.iWidth;
365   iHeight = pInfo->UsrData.sSystemBuffer.iHeight;
366   iStride[0] = pInfo->UsrData.sSystemBuffer.iStride[0];
367   iStride[1] = pInfo->UsrData.sSystemBuffer.iStride[1];
368 
369   if (pDst[0] && pDst[1] && pDst[2])
370     Write2File (pFp, (unsigned char**)pDst, iStride, iWidth, iHeight);
371 
372   return hResult;
373 }
374 
InitResource(void * pSharedHandle,SBufferInfo * pInfo)375 HRESULT CD3D9ExUtils::InitResource (void* pSharedHandle, SBufferInfo* pInfo) {
376   HRESULT hResult = S_OK;
377   int iWidth;
378   int iHeight;
379   D3DFORMAT D3Dformat;
380   D3DPOOL D3Dpool;
381 
382   if (pInfo == NULL)
383     return E_FAIL;
384 
385   if (m_lpD3D9Device == NULL && m_lpD3D9RawSurfaceShare == NULL) {
386     HMONITOR hMonitorWnd = MonitorFromWindow (m_hWnd, MONITOR_DEFAULTTONULL);
387 
388     UINT uiAdapter = D3DADAPTER_DEFAULT;
389     UINT uiCnt = m_lpD3D9->GetAdapterCount();
390     for (UINT i = 0; i < uiCnt; i++) {
391       HMONITOR hMonitor = m_lpD3D9->GetAdapterMonitor (i);
392       if (hMonitor == hMonitorWnd) {
393         uiAdapter = i;
394         break;
395       }
396     }
397 
398     D3DDISPLAYMODEEX D3DDisplayMode;
399     D3DDisplayMode.Size = sizeof (D3DDISPLAYMODEEX);
400     hResult = m_lpD3D9->GetAdapterDisplayModeEx (uiAdapter, &D3DDisplayMode, NULL);
401 
402     D3DDEVTYPE D3DDevType = D3DDEVTYPE_HAL;
403     DWORD dwBehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
404 
405     ZeroMemory (&m_d3dpp, sizeof (m_d3dpp));
406     m_d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
407     m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
408     m_d3dpp.BackBufferFormat = D3DDisplayMode.Format;
409     m_d3dpp.Windowed = TRUE;
410     m_d3dpp.hDeviceWindow = m_hWnd;
411     m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
412     hResult = m_lpD3D9->CreateDeviceEx (uiAdapter, D3DDevType, NULL, dwBehaviorFlags, &m_d3dpp, NULL, &m_lpD3D9Device);
413     if (FAILED (hResult)) {
414       return hResult;
415     }
416     iWidth = pInfo->UsrData.sSystemBuffer.iWidth;
417     iHeight = pInfo->UsrData.sSystemBuffer.iHeight;
418     D3Dformat = (D3DFORMAT)NV12_FORMAT;
419     D3Dpool = (D3DPOOL)D3DPOOL_DEFAULT;
420     hResult = m_lpD3D9Device->CreateOffscreenPlainSurface (iWidth, iHeight, (D3DFORMAT)D3Dformat, (D3DPOOL)D3Dpool,
421               &m_lpD3D9RawSurfaceShare, &pSharedHandle);
422   }
423 
424   if (m_lpD3D9Device == NULL || m_lpD3D9RawSurfaceShare == NULL)
425     hResult = E_FAIL;
426 
427   return hResult;
428 }
429 
430 
Dump2Surface(void * pDst[3],void * pSurface,int iWidth,int iHeight,int iStride[2])431 HRESULT Dump2Surface (void* pDst[3], void* pSurface, int iWidth, int iHeight, int iStride[2]) {
432   HRESULT hResult = E_FAIL;
433 
434   if (!pDst[0] || !pDst[1] || !pDst[2] || !pSurface)
435     return hResult;
436 
437   IDirect3DSurface9* pSurfaceData = (IDirect3DSurface9*)pSurface;
438   D3DLOCKED_RECT sD3DLockedRect = {0};
439   hResult = pSurfaceData->LockRect (&sD3DLockedRect, NULL, 0);
440 
441   unsigned char* pInY = (unsigned char*)pDst[0];
442   unsigned char* pOutY = (unsigned char*)sD3DLockedRect.pBits;
443   int iOutStride = sD3DLockedRect.Pitch;
444 
445   for (int j = 0; j < iHeight; j++)
446     memcpy (pOutY + j * iOutStride, pInY + j * iStride[0], iWidth); //confirmed_safe_unsafe_usage
447 
448   unsigned char* pInU = (unsigned char*)pDst[1];
449   unsigned char* pInV = (unsigned char*)pDst[2];
450   unsigned char* pOutC = pOutY + iOutStride * iHeight;
451   for (int i = 0; i < iHeight / 2; i++) {
452     for (int j = 0; j < iWidth; j += 2) {
453       pOutC[i * iOutStride + j  ] = pInU[i * iStride[1] + j / 2];
454       pOutC[i * iOutStride + j + 1] = pInV[i * iStride[1] + j / 2];
455     }
456   }
457 
458   pSurfaceData->UnlockRect();
459 
460   return hResult;
461 }
462 
InitWindow(HWND * hWnd)463 HRESULT InitWindow (HWND* hWnd) {
464   const TCHAR kszWindowTitle[] = TEXT ("Wels Decoder Application");
465   const TCHAR kszWindowClass[] = TEXT ("Wels Decoder Class");
466 
467   WNDCLASSEX sWndClassEx = {0};
468   sWndClassEx.cbSize            = sizeof (WNDCLASSEX);
469   sWndClassEx.style             = CS_HREDRAW | CS_VREDRAW;
470   sWndClassEx.lpfnWndProc       = (WNDPROC)WndProc;
471   sWndClassEx.cbClsExtra        = 0;
472   sWndClassEx.cbWndExtra        = 0;
473   sWndClassEx.hInstance         = GetModuleHandle (NULL);
474   sWndClassEx.hIcon             = LoadIcon (sWndClassEx.hInstance, (LPCTSTR)IDI_TESTSHARESURFACE);
475   sWndClassEx.hCursor           = LoadCursor (NULL, IDC_ARROW);
476   sWndClassEx.hbrBackground     = (HBRUSH) (COLOR_WINDOW + 1);
477   sWndClassEx.lpszMenuName      = (LPCSTR)IDC_TESTSHARESURFACE;
478   sWndClassEx.lpszClassName     = kszWindowClass;
479   sWndClassEx.hIconSm           = LoadIcon (sWndClassEx.hInstance, (LPCTSTR)IDI_SMALL);
480 
481   if (!RegisterClassEx (&sWndClassEx))
482     return E_FAIL;
483 
484   HWND hTmpWnd = CreateWindow (kszWindowClass, kszWindowTitle, WS_OVERLAPPEDWINDOW,
485                                CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, sWndClassEx.hInstance, NULL);
486 
487   *hWnd = hTmpWnd;
488   if (!hTmpWnd)
489     return E_FAIL;
490 
491   ShowWindow (hTmpWnd, SW_SHOWDEFAULT);
492   UpdateWindow (hTmpWnd);
493 
494   return S_OK;
495 }
496 
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)497 LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
498   INT wmId, wmEvent;
499 
500   switch (message) {
501   case WM_COMMAND:
502     wmId    = LOWORD (wParam);
503     wmEvent = HIWORD (wParam);
504     switch (wmId) {
505     case IDM_ABOUT:
506       break;
507     case IDM_EXIT:
508       DestroyWindow (hWnd);
509       break;
510     default:
511       return DefWindowProc (hWnd, message, wParam, lParam);
512     }
513     break;
514   case WM_PAINT:
515     ValidateRect (hWnd , NULL);
516     break;
517   case WM_DESTROY:
518     PostQuitMessage (0);
519     break;
520   default:
521     return DefWindowProc (hWnd, message, wParam, lParam);
522   }
523   return 0;
524 }
525 
526 #endif
527 
CUtils()528 CUtils::CUtils() {
529   hHandle = NULL;
530   iOSType = CheckOS();
531 
532 #ifdef ENABLE_DISPLAY_MODULE
533   if (iOSType == OS_XP)
534     hHandle = (void*) new CD3D9Utils;
535 
536   else if (iOSType == OS_VISTA_UPPER)
537     hHandle = (void*) new CD3D9ExUtils;
538 #endif
539 
540   if (hHandle == NULL)
541     iOSType = OS_UNSUPPORTED;
542 }
543 
~CUtils()544 CUtils::~CUtils() {
545 #ifdef ENABLE_DISPLAY_MODULE
546   if (hHandle) {
547     if (iOSType == OS_XP) {
548       CD3D9Utils* hTmp = (CD3D9Utils*) hHandle;
549       delete hTmp;
550     } else if (iOSType == OS_VISTA_UPPER) {
551       CD3D9ExUtils* hTmp = (CD3D9ExUtils*) hHandle;
552       delete hTmp;
553     }
554     hHandle = NULL;
555   }
556 #endif
557 }
558 
Process(void * pDst[3],SBufferInfo * pInfo,FILE * pFp)559 int CUtils::Process (void* pDst[3], SBufferInfo* pInfo, FILE* pFp) {
560 
561   int iRet = 0;
562 
563   if (iOSType == OS_UNSUPPORTED) {
564     if (pFp && pDst[0] && pDst[1] && pDst[2] && pInfo) {
565       int iStride[2];
566       int iWidth = pInfo->UsrData.sSystemBuffer.iWidth;
567       int iHeight = pInfo->UsrData.sSystemBuffer.iHeight;
568       iStride[0] = pInfo->UsrData.sSystemBuffer.iStride[0];
569       iStride[1] = pInfo->UsrData.sSystemBuffer.iStride[1];
570 
571       Write2File (pFp, (unsigned char**)pDst, iStride, iWidth, iHeight);
572     }
573   }
574 
575 #ifdef ENABLE_DISPLAY_MODULE
576   else {
577     MSG msg;
578     ZeroMemory (&msg, sizeof (msg));
579     while (msg.message != WM_QUIT) {
580       if (PeekMessage (&msg, NULL, 0U, 0U, PM_REMOVE)) {
581         TranslateMessage (&msg);
582         DispatchMessage (&msg);
583       } else {
584         HRESULT hResult = S_OK;
585         if (iOSType == OS_XP)
586           hResult = ((CD3D9Utils*)hHandle)->Process (pDst, pInfo, pFp);
587 
588         else if (iOSType == OS_VISTA_UPPER)
589           hResult = ((CD3D9ExUtils*)hHandle)->Process (pDst, pInfo, pFp);
590 
591         iRet = !SUCCEEDED (hResult);
592         break;
593       }
594     }
595   }
596 #endif
597 
598   return iRet;
599 }
600 
CheckOS()601 int CUtils::CheckOS() {
602   int iType = OS_UNSUPPORTED;
603 
604 #ifdef ENABLE_DISPLAY_MODULE
605   OSVERSIONINFOEX osvi;
606   ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
607   osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
608   osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
609   osvi.dwMajorVersion = 6; // Vista
610   DWORDLONG condmask = VerSetConditionMask (VerSetConditionMask (0, VER_MAJORVERSION, VER_GREATER_EQUAL),
611                        VER_PLATFORMID, VER_EQUAL);
612 
613   if (VerifyVersionInfo (&osvi, VER_MAJORVERSION | VER_PLATFORMID, condmask)) {
614     iType = OS_VISTA_UPPER;
615   } else {
616     osvi.dwMajorVersion = 5; // XP/2000
617     if (VerifyVersionInfo (&osvi, VER_MAJORVERSION | VER_PLATFORMID, condmask))
618       iType = OS_XP;
619   }
620 #endif
621 
622   return iType;
623 }
624 
Write2File(FILE * pFp,unsigned char * pData[3],int iStride[2],int iWidth,int iHeight)625 void Write2File (FILE* pFp, unsigned char* pData[3], int iStride[2], int iWidth, int iHeight) {
626   int   i;
627   unsigned char*  pPtr = NULL;
628 
629   pPtr = pData[0];
630   for (i = 0; i < iHeight; i++) {
631     fwrite (pPtr, 1, iWidth, pFp);
632     pPtr += iStride[0];
633   }
634 
635   iHeight = iHeight / 2;
636   iWidth = iWidth / 2;
637   pPtr = pData[1];
638   for (i = 0; i < iHeight; i++) {
639     fwrite (pPtr, 1, iWidth, pFp);
640     pPtr += iStride[1];
641   }
642 
643   pPtr = pData[2];
644   for (i = 0; i < iHeight; i++) {
645     fwrite (pPtr, 1, iWidth, pFp);
646     pPtr += iStride[1];
647   }
648 }
649