Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
8.6 KiB

  1. /* Test AM streams stuff */
  2. #include <windows.h>
  3. #include <uuids.h>
  4. #include <ddraw.h>
  5. #include <atlbase.h>
  6. CComModule _Module;
  7. #include <atlcom.h>
  8. #include <atlimpl.cpp>
  9. #include <initguid.h>
  10. #include <amstream.h>
  11. #include <mmstream.h>
  12. #include <ddstream.h>
  13. #include <austream.h>
  14. #include <wave.h>
  15. #define CHECK_RESULT(_x_) \
  16. { \
  17. HRESULT hr = check_result(_x_, #_x_); \
  18. if (FAILED(hr)) { \
  19. return hr; \
  20. } \
  21. }
  22. inline check_result(HRESULT _x_, LPCTSTR sz)
  23. {
  24. if (FAILED(_x_)) {
  25. AtlTrace(_T("%s failed code %8.8X\n"), sz);
  26. }
  27. return _x_;
  28. }
  29. HRESULT FindCaptureDevice(IMoniker **ppMoniker)
  30. {
  31. CComPtr<ICreateDevEnum> pCreateDevEnum;
  32. HRESULT hr = CoCreateInstance(
  33. CLSID_SystemDeviceEnum,
  34. NULL,
  35. CLSCTX_INPROC_SERVER,
  36. IID_ICreateDevEnum,
  37. (void**)&pCreateDevEnum);
  38. if (hr != NOERROR)
  39. return FALSE;
  40. CComPtr<IEnumMoniker> pEm;
  41. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_CVidCapClassManager,
  42. &pEm,
  43. 0);
  44. if (hr != NOERROR)
  45. return hr;
  46. ULONG cFetched;
  47. return pEm->Next(1, ppMoniker, &cFetched);
  48. }
  49. HRESULT LoadCapture(DWORD dwFlags, IAMMultiMediaStream *pMMStream)
  50. {
  51. CComPtr<IMoniker> pMoniker;
  52. HRESULT hr = FindCaptureDevice(&pMoniker);
  53. AtlTrace(_T("FindCaptureDevice returned %8.8X\n"), hr);
  54. if (S_OK != hr) {
  55. return E_FAIL;
  56. }
  57. hr = pMMStream->OpenMoniker(
  58. pMoniker,
  59. dwFlags
  60. );
  61. AtlTrace("OpenMoniker returned 0x%8.8X\n", hr);
  62. return hr;
  63. }
  64. HRESULT LoadFile(LPCSTR lpsz, DWORD dwFlags, IAMMultiMediaStream *pMMStream)
  65. {
  66. /* Load our file */
  67. WCHAR wsz[MAX_PATH];
  68. MultiByteToWideChar(CP_ACP, 0, lpsz, -1, wsz, MAX_PATH);
  69. HRESULT hr = pMMStream->OpenFile(
  70. wsz,
  71. dwFlags
  72. );
  73. AtlTrace("OpenFile returned 0x%8.8X\n", hr);
  74. return hr;
  75. }
  76. HRESULT CreateAMMMStream(IAMMultiMediaStream **ppMMStream)
  77. {
  78. /* Create the mmstream object */
  79. HRESULT hr = CoCreateInstance(
  80. CLSID_AMMultiMediaStream,
  81. NULL,
  82. CLSCTX_INPROC_SERVER,
  83. IID_IAMMultiMediaStream,
  84. (void **)ppMMStream
  85. );
  86. AtlTrace(_T("CreateAMMMStream returned 0x%8.8X\n"), hr);
  87. return hr;
  88. }
  89. HRESULT AddAudioStream(IAMMultiMediaStream *pAMMStream)
  90. {
  91. return pAMMStream->AddMediaStream(
  92. NULL,
  93. MSPID_PrimaryAudio,
  94. 0,
  95. NULL);
  96. }
  97. HRESULT AddDDStream(IAMMultiMediaStream *pAMMStream)
  98. {
  99. CComPtr<IDirectDraw> pDDraw;
  100. HRESULT hr = DirectDrawCreate(NULL, &pDDraw, NULL);
  101. if (FAILED(hr)) {
  102. return hr;
  103. }
  104. hr = pDDraw->SetCooperativeLevel(HWND_DESKTOP, DDSCL_NORMAL);
  105. if (FAILED(hr)) {
  106. return hr;
  107. }
  108. return pAMMStream->AddMediaStream(
  109. pDDraw,
  110. MSPID_PrimaryVideo,
  111. 0,
  112. NULL);
  113. }
  114. // Create a random surface
  115. HRESULT CreateARandomSurface(
  116. IDirectDraw *pDDraw,
  117. LPDDSURFACEDESC pDesc,
  118. IDirectDrawSurface **ppSurface
  119. )
  120. {
  121. return pDDraw->CreateSurface(pDesc, ppSurface, NULL);
  122. }
  123. HRESULT PlayAudio(IMultiMediaStream *pMMStream)
  124. {
  125. // Find the audio stream
  126. CComPtr<IMediaStream> pMediaStream;
  127. _ASSERTE(S_OK == pMMStream->GetMediaStream(MSPID_PrimaryAudio, &pMediaStream));
  128. // Get the audio interface and create our sample
  129. CComPtr<IAudioMediaStream> pAudioStream;
  130. CHECK_RESULT(pMediaStream->QueryInterface(IID_IAudioMediaStream, (void**)&pAudioStream));
  131. WAVEFORMATEX wfx;
  132. CHECK_RESULT(pAudioStream->GetFormat(&wfx));
  133. #define NBUFFERS 1
  134. CComPtr<IAudioData> pAudioData[NBUFFERS];
  135. CComPtr<IAudioStreamSample> pSample[NBUFFERS];
  136. PBYTE pBuffer[NBUFFERS];
  137. HANDLE hEvent[NBUFFERS];
  138. for (int i = 0; i < NBUFFERS; i++) {
  139. #define DATA_SIZE 5000
  140. pBuffer[i] = new BYTE[DATA_SIZE];
  141. CHECK_RESULT(CoCreateInstance(CLSID_AMAudioData,
  142. NULL,
  143. CLSCTX_INPROC_SERVER,
  144. IID_IAudioData,
  145. (void**)&pAudioData[i]));
  146. CHECK_RESULT(pAudioData[i]->Init(DATA_SIZE, pBuffer[i], 0));
  147. CHECK_RESULT(pAudioData[i]->SetFormat(&wfx));
  148. CHECK_RESULT(pAudioStream->CreateSample(
  149. pAudioData[i],
  150. 0,
  151. &pSample[i]));
  152. hEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
  153. }
  154. // Make a player
  155. CWaveOut WaveOut(&wfx, 4, 2048);
  156. #define MAX_PLAY_TIME 3
  157. for (int Times = 0; Times < 3; Times++) {
  158. DWORD dwStart = timeGetTime();
  159. for (; ; ) {
  160. HRESULT hr = pSample[0]->Update(0, hEvent[0], NULL, 0);
  161. if (FAILED(hr) || hr == MS_S_ENDOFSTREAM) {
  162. break;
  163. }
  164. WaitForSingleObject(hEvent[0], INFINITE);
  165. CHECK_RESULT(pSample[0]->CompletionStatus(0, 0));
  166. if ((LONG)(timeGetTime() - dwStart) > MAX_PLAY_TIME * 1000) {
  167. break;
  168. }
  169. DWORD dwLength;
  170. CHECK_RESULT(pAudioData[0]->GetInfo(NULL, NULL, &dwLength));
  171. _ASSERTE(dwLength == DATA_SIZE || S_OK != hr);
  172. WaveOut.Write(pBuffer[0], dwLength);
  173. #if 0
  174. if (S_OK != hr) {
  175. _ASSERTE(hr == MS_S_ENDOFSTREAM || hr == S_FALSE);
  176. break;
  177. }
  178. #endif
  179. }
  180. pMMStream->Seek(0);
  181. }
  182. WaveOut.Wait();
  183. return S_OK;
  184. }
  185. // Play a multimedia stream
  186. HRESULT PlayVideo(IMultiMediaStream *pMMStream)
  187. {
  188. // First get the video stream
  189. CComPtr<IMediaStream> pMediaStream;
  190. HRESULT hr = pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pMediaStream);
  191. if (FAILED(hr)) {
  192. return hr;
  193. }
  194. CComPtr<IDirectDrawMediaStream> pDDStream;
  195. // Get the dd stream
  196. hr = pMediaStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&pDDStream);
  197. if (FAILED(hr)) {
  198. return hr;
  199. }
  200. // Now create our surface and play with it
  201. CComPtr<IDirectDraw> pDDraw;
  202. hr = pDDStream->GetDirectDraw(&pDDraw);
  203. if (FAILED(hr)) {
  204. return hr;
  205. }
  206. // Find out the movie size
  207. DDSURFACEDESC ddFormat;
  208. ddFormat.dwSize = sizeof(ddFormat);
  209. hr = pDDStream->GetFormat(&ddFormat, NULL, NULL);
  210. if (FAILED(hr)) {
  211. return hr;
  212. }
  213. CComPtr<IDirectDrawSurface> pSurface;
  214. hr = CreateARandomSurface(pDDraw, &ddFormat, &pSurface);
  215. if (FAILED(hr)) {
  216. return hr;
  217. }
  218. CComPtr<IDirectDrawStreamSample> pSample;
  219. hr = pDDStream->CreateSample(pSurface, NULL, NULL, &pSample);
  220. if (FAILED(hr)) {
  221. return hr;
  222. }
  223. for (; ; ) {
  224. HRESULT hr = pSample->Update(0, NULL, NULL, 0);
  225. if (S_OK != hr) {
  226. AtlTrace(_T("Update returned 0x%8.8X\n"), hr);
  227. return S_OK;
  228. }
  229. Sleep(10);
  230. hr = pSample->CompletionStatus(COMPSTAT_NOUPDATEOK |
  231. COMPSTAT_WAIT,
  232. 0);
  233. }
  234. }
  235. void DoTests(LPSTR lpszFileName)
  236. {
  237. CComPtr<IAMMultiMediaStream> pAMMStream;
  238. // Create an AMStream
  239. HRESULT hr = CreateAMMMStream(&pAMMStream);
  240. // Now try to create a stream
  241. CComPtr<IAMMediaStream> pDDStream;
  242. hr = AddAudioStream(pAMMStream);
  243. AtlTrace(_T("CreateDDStream returned 0x%8.8X\n"), hr);
  244. hr = lpszFileName ?
  245. LoadFile(lpszFileName, AMMSF_RENDERTOEXISTING, pAMMStream) :
  246. LoadCapture(AMMSF_RENDERTOEXISTING, pAMMStream);
  247. if (SUCCEEDED(hr)) {
  248. HRESULT hr = pAMMStream->Initialize(STREAMTYPE_READ, NULL);
  249. CComQIPtr<IMultiMediaStream, &IID_IMultiMediaStream> pMMStream(
  250. pAMMStream);
  251. DWORD dwFlags;
  252. STREAM_TYPE Type;
  253. hr = pMMStream->GetInformation(&dwFlags, &Type);
  254. _ASSERTE(Type == STREAMTYPE_READ);
  255. CComPtr<IMediaStream> pStream;
  256. hr = pMMStream->GetMediaStream(MSPID_PrimaryAudio, &pStream);
  257. pStream = NULL;
  258. hr = pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pStream);
  259. hr = pMMStream->SetState(STREAMSTATE_RUN);
  260. AtlTrace(_T("SetState(STREAMSTATE_RUN) returned 0x%8.8X\n"), hr);
  261. hr = PlayAudio(pMMStream);
  262. Sleep(5000);
  263. hr = pMMStream->SetState(STREAMSTATE_STOP);
  264. AtlTrace(_T("SetState(STREAMSTATE_STOP) returned 0x%8.8X\n"), hr);
  265. }
  266. }
  267. int _CRTAPI1 main(int argc, char *argv[])
  268. {
  269. CoInitialize(NULL);
  270. DoTests(argc < 2 ? NULL : argv[1]);
  271. CoUninitialize();
  272. return 0;
  273. }