DSUtils.cxx 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
  2. *
  3. * This file is part of Open Source Doubango Framework.
  4. *
  5. * DOUBANGO is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * DOUBANGO is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with DOUBANGO.
  17. */
  18. #include "internals/DSUtils.h"
  19. #if defined (_WIN32_WCE)
  20. #include <atlbase.h>
  21. #include <atlstr.h>
  22. #else
  23. #include <atlconv.h>
  24. #include <d3d9.h>
  25. #endif
  26. #include "tsk_debug.h"
  27. HWND GetMainWindow()
  28. {
  29. HWND hWnd;
  30. if (!(hWnd = GetActiveWindow())) {
  31. if (!(hWnd = GetForegroundWindow())) {
  32. #if !defined(_WIN32_WCE)
  33. if (!(hWnd = GetConsoleWindow())) {
  34. return NULL;
  35. }
  36. #endif
  37. }
  38. }
  39. return hWnd;
  40. }
  41. bool IsMainThread()
  42. {
  43. HWND hWnd = GetMainWindow();
  44. if (hWnd) {
  45. DWORD mainTid = GetWindowThreadProcessId(hWnd, NULL);
  46. DWORD currentTid = GetCurrentThreadId();
  47. return (mainTid == currentTid);
  48. }
  49. return false;
  50. }
  51. bool IsD3D9Supported()
  52. {
  53. #if defined(_WIN32_WCE)
  54. return false;
  55. #else
  56. static bool g_bChecked = false;
  57. static bool g_bSupported = false;
  58. if (g_bChecked) {
  59. return g_bSupported;
  60. }
  61. g_bChecked = true;
  62. HRESULT hr = S_OK;
  63. IDirect3D9* pD3D = NULL;
  64. D3DDISPLAYMODE mode = { 0 };
  65. D3DPRESENT_PARAMETERS pp = {0};
  66. IDirect3DDevice9* pDevice = NULL;
  67. if (!(pD3D = Direct3DCreate9(D3D_SDK_VERSION))) {
  68. hr = E_OUTOFMEMORY;
  69. goto bail;
  70. }
  71. hr = pD3D->GetAdapterDisplayMode(
  72. D3DADAPTER_DEFAULT,
  73. &mode
  74. );
  75. if (FAILED(hr)) {
  76. goto bail;
  77. }
  78. hr = pD3D->CheckDeviceType(
  79. D3DADAPTER_DEFAULT,
  80. D3DDEVTYPE_HAL,
  81. mode.Format,
  82. D3DFMT_X8R8G8B8,
  83. TRUE // windowed
  84. );
  85. if (FAILED(hr)) {
  86. goto bail;
  87. }
  88. pp.BackBufferFormat = D3DFMT_X8R8G8B8;
  89. pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  90. pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  91. pp.Windowed = TRUE;
  92. pp.hDeviceWindow = GetDesktopWindow();
  93. hr = pD3D->CreateDevice(
  94. D3DADAPTER_DEFAULT,
  95. D3DDEVTYPE_HAL,
  96. pp.hDeviceWindow,
  97. D3DCREATE_HARDWARE_VERTEXPROCESSING,
  98. &pp,
  99. &pDevice
  100. );
  101. if (FAILED(hr)) {
  102. goto bail;
  103. }
  104. // Everythings is OK
  105. g_bSupported = true;
  106. TSK_DEBUG_INFO("D3D9 supported");
  107. bail:
  108. if (!g_bSupported) {
  109. TSK_DEBUG_WARN("D3D9 not supported");
  110. }
  111. SAFE_RELEASE(pDevice);
  112. SAFE_RELEASE(pD3D);
  113. return g_bSupported;
  114. #endif /* _WIN32_WCE */
  115. }
  116. IPin *GetPin(IBaseFilter *filter, PIN_DIRECTION direction)
  117. {
  118. IEnumPins *enumPins = NULL;
  119. IPin *pin = NULL;
  120. HRESULT hr = filter->EnumPins(&enumPins);
  121. if(!enumPins) {
  122. return NULL;
  123. }
  124. for(;;) {
  125. ULONG fetched = 0;
  126. PIN_DIRECTION pinDir = PIN_DIRECTION(-1);
  127. pin = NULL;
  128. if (FAILED(enumPins->Next(1, &pin, &fetched))) {
  129. enumPins->Release();
  130. return NULL;
  131. }
  132. if (fetched == 1 && pin) {
  133. pin->QueryDirection(&pinDir);
  134. if(pinDir == direction) {
  135. break;
  136. }
  137. pin->Release();
  138. }
  139. }
  140. enumPins->Release();
  141. return pin;
  142. }
  143. HRESULT ConnectFilters(IGraphBuilder *graphBuilder, IBaseFilter *source, IBaseFilter *destination, AM_MEDIA_TYPE *mediaType)
  144. {
  145. HRESULT hr;
  146. IPin *outPin = GetPin(source, PINDIR_OUTPUT);
  147. IPin *inPin = GetPin(destination, PINDIR_INPUT);
  148. if (mediaType != NULL) {
  149. hr = graphBuilder->ConnectDirect(outPin, inPin, mediaType);
  150. }
  151. else {
  152. hr = graphBuilder->Connect(outPin, inPin);
  153. }
  154. SAFE_RELEASE(outPin);
  155. SAFE_RELEASE(inPin);
  156. return hr;
  157. }
  158. HRESULT DisconnectFilters(IGraphBuilder *graphBuilder, IBaseFilter *source, IBaseFilter *destination)
  159. {
  160. HRESULT hr;
  161. IPin *outPin = GetPin(source, PINDIR_OUTPUT);
  162. IPin *inPin = GetPin(destination, PINDIR_INPUT);
  163. if (inPin) {
  164. hr = graphBuilder->Disconnect(inPin);
  165. }
  166. if (outPin) {
  167. hr = graphBuilder->Disconnect(outPin);
  168. }
  169. SAFE_RELEASE(outPin);
  170. SAFE_RELEASE(inPin);
  171. return hr;
  172. }
  173. bool DisconnectAllFilters(IGraphBuilder *graphBuilder)
  174. {
  175. IEnumFilters* filterEnum = NULL;
  176. IBaseFilter* currentFilter = NULL;
  177. ULONG fetched;
  178. HRESULT hr;
  179. hr = graphBuilder->EnumFilters(&filterEnum);
  180. if (FAILED(hr)) {
  181. SAFE_RELEASE(filterEnum);
  182. return false;
  183. }
  184. while(filterEnum->Next(1, &currentFilter, &fetched) == S_OK) {
  185. hr = DisconnectFilters(graphBuilder, currentFilter, currentFilter);
  186. SAFE_RELEASE(currentFilter);
  187. }
  188. SAFE_RELEASE(filterEnum);
  189. SAFE_RELEASE(currentFilter);
  190. return true;
  191. }
  192. bool RemoveAllFilters(IGraphBuilder *graphBuilder)
  193. {
  194. IEnumFilters* filterEnum = NULL;
  195. IBaseFilter* currentFilter = NULL;
  196. ULONG fetched;
  197. HRESULT hr;
  198. hr = graphBuilder->EnumFilters(&filterEnum);
  199. if (FAILED(hr)) {
  200. return false;
  201. }
  202. while(filterEnum->Next(1, &currentFilter, &fetched) == S_OK) {
  203. hr = graphBuilder->RemoveFilter(currentFilter);
  204. if (FAILED(hr)) {
  205. SAFE_RELEASE(filterEnum);
  206. return false;
  207. }
  208. SAFE_RELEASE(currentFilter);
  209. filterEnum->Reset();
  210. }
  211. SAFE_RELEASE(filterEnum);
  212. SAFE_RELEASE(currentFilter);
  213. return true;
  214. }
  215. #include "internals/DSDisplay.h"
  216. #include "internals/DSGrabber.h"
  217. #define WM_CREATE_DISPLAY_ON_UI_THREAD (WM_USER + 101)
  218. #define WM_CREATE_GRABBER_ON_UI_THREAD (WM_CREATE_DISPLAY_ON_UI_THREAD + 1)
  219. #define WM_CREATE_ON_UI_THREAD_TIMEOUT 1000
  220. // C Callback that dispatch event to create display on UI thread
  221. static LRESULT CALLBACK __create__WndProcWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  222. {
  223. HANDLE* event = reinterpret_cast<HANDLE*>(wParam);
  224. BOOL* isScreenCast = reinterpret_cast<BOOL*>(GetProp(hWnd, TEXT("screnCast")));
  225. if(event && lParam) {
  226. switch(uMsg) {
  227. case WM_CREATE_DISPLAY_ON_UI_THREAD: {
  228. HRESULT hr;
  229. DSDisplay** ppDisplay = reinterpret_cast<DSDisplay**>(lParam);
  230. *ppDisplay = new DSDisplay(&hr);
  231. SetEvent(event);
  232. break;
  233. }
  234. case WM_CREATE_GRABBER_ON_UI_THREAD: {
  235. HRESULT hr;
  236. DSGrabber** ppGrabber = reinterpret_cast<DSGrabber**>(lParam);
  237. *ppGrabber = new DSGrabber(&hr, *isScreenCast);
  238. SetEvent(event);
  239. break;
  240. }
  241. }
  242. }
  243. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  244. }
  245. int createOnCurrentThead(HWND hWnd, void** ppRet, BOOL display, BOOL screnCast)
  246. {
  247. HRESULT hr;
  248. if(display) {
  249. *ppRet = new DSDisplay(&hr);
  250. }
  251. else {
  252. *ppRet = new DSGrabber(&hr, screnCast);
  253. }
  254. if(FAILED(hr)) {
  255. TSK_DEBUG_ERROR("Failed to created DirectShow %s", display ? "Display" : "Grabber");
  256. SAFE_DELETE_PTR(*ppRet);
  257. return -2;
  258. }
  259. return 0;
  260. }
  261. int createOnUIThead(HWND hWnd, void** ppRet, BOOL display, BOOL screnCast)
  262. {
  263. static BOOL __isScreenCastFalse = FALSE;
  264. static BOOL __isScreenCastTrue = TRUE;
  265. if(!ppRet) {
  266. TSK_DEBUG_ERROR("Invalid parameter");
  267. return -1;
  268. }
  269. if (IsMainThread()) {
  270. return createOnCurrentThead(hWnd, ppRet, display, screnCast);
  271. }
  272. else {
  273. TSK_DEBUG_INFO("Create DirectShow element on worker thread");
  274. HANDLE event = NULL;
  275. int ret = 0;
  276. DWORD retWait, retryCount = 3;
  277. if(!hWnd) {
  278. if (!(hWnd = FindWindow(NULL, TEXT("Boghe - IMS/RCS Client")))) {
  279. if(!(hWnd = GetMainWindow())) {
  280. TSK_DEBUG_ERROR("No Window handle could be used");
  281. return -2;
  282. }
  283. }
  284. }
  285. #if defined(_WIN32_WCE)
  286. WNDPROC wndProc = (WNDPROC) SetWindowLong(hWnd, GWL_WNDPROC, (LONG) __create__WndProcWindow);
  287. #else
  288. WNDPROC wndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR) __create__WndProcWindow);
  289. #endif
  290. if (!wndProc) {
  291. TSK_DEBUG_ERROR("SetWindowLongPtr() failed with errcode=%d", GetLastError());
  292. return createOnCurrentThead(hWnd, ppRet, display, screnCast);
  293. }
  294. if (!(event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
  295. TSK_DEBUG_ERROR("Failed to create new event");
  296. ret = -4;
  297. goto bail;
  298. }
  299. SetProp(hWnd, TEXT("screnCast"), screnCast ? &__isScreenCastTrue : &__isScreenCastFalse);
  300. if (!PostMessage(hWnd, display ? WM_CREATE_DISPLAY_ON_UI_THREAD : WM_CREATE_GRABBER_ON_UI_THREAD, reinterpret_cast<WPARAM>(event), reinterpret_cast<LPARAM>(ppRet))) {
  301. TSK_DEBUG_ERROR("PostMessageA() failed");
  302. ret = -5;
  303. goto bail;
  304. }
  305. do {
  306. retWait = WaitForSingleObject(event, WM_CREATE_ON_UI_THREAD_TIMEOUT);
  307. }
  308. while (retryCount-- > 0 && (retWait == WAIT_TIMEOUT));
  309. bail:
  310. // restore
  311. if (hWnd && wndProc) {
  312. #if defined(_WIN32_WCE)
  313. SetWindowLong(hWnd, GWL_WNDPROC, (LONG)wndProc);
  314. #else
  315. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc);
  316. #endif
  317. }
  318. if (event) {
  319. CloseHandle(event);
  320. }
  321. return ret;
  322. }
  323. }