Leaked source code of windows server 2003
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.

288 lines
9.0 KiB

  1. //
  2. // Created 5-Nov-96 [RichP]
  3. #include "Precomp.h"
  4. DWORD
  5. _GetVideoFormatSize(
  6. HDRVR hvideo
  7. )
  8. {
  9. DWORD bufsize;
  10. VIDEOCONFIGPARMS vcp;
  11. vcp.lpdwReturn = &bufsize;
  12. vcp.lpData1 = NULL;
  13. vcp.dwSize1 = 0;
  14. vcp.lpData2 = NULL;
  15. vcp.dwSize2 = 0L;
  16. #if 0
  17. // it makes sense to query if DVM_FORMAT is available, but not all drivers support it!
  18. if (SendDriverMessage(hvideo, DVM_FORMAT,
  19. (LPARAM)(DWORD)(VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_QUERY),
  20. (LPARAM)(LPVOID)&vcp) == DV_ERR_OK) {
  21. #endif
  22. SendDriverMessage(hvideo, DVM_FORMAT,
  23. (LPARAM)(DWORD)(VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_QUERYSIZE),
  24. (LPARAM)(LPVOID)&vcp);
  25. if (!bufsize)
  26. bufsize = sizeof(BITMAPINFOHEADER);
  27. return bufsize;
  28. #if 0
  29. } else
  30. return sizeof(BITMAPINFOHEADER);
  31. #endif
  32. }
  33. BOOL
  34. _GetVideoFormat(
  35. HVIDEO hvideo,
  36. LPBITMAPINFOHEADER lpbmih
  37. )
  38. {
  39. BOOL res;
  40. VIDEOCONFIGPARMS vcp;
  41. vcp.lpdwReturn = NULL;
  42. vcp.lpData1 = lpbmih;
  43. vcp.dwSize1 = lpbmih->biSize;
  44. vcp.lpData2 = NULL;
  45. vcp.dwSize2 = 0L;
  46. res = !SendDriverMessage((HDRVR)hvideo, DVM_FORMAT,
  47. (LPARAM)(DWORD)(VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_CURRENT),
  48. (LPARAM)(LPVOID)&vcp);
  49. if (res) {
  50. // hack for Connectix QuickCam - set format needs to be called
  51. // to set internal globals so that streaming can be enabled
  52. SendDriverMessage((HDRVR)hvideo, DVM_FORMAT,
  53. (LPARAM)(DWORD)VIDEO_CONFIGURE_SET, (LPARAM)(LPVOID)&vcp);
  54. }
  55. return res;
  56. }
  57. BOOL
  58. _SetVideoFormat(
  59. HVIDEO hvideoExtIn,
  60. HVIDEO hvideoIn,
  61. LPBITMAPINFOHEADER lpbmih
  62. )
  63. {
  64. RECT rect;
  65. VIDEOCONFIGPARMS vcp;
  66. vcp.lpdwReturn = NULL;
  67. vcp.lpData1 = lpbmih;
  68. vcp.dwSize1 = lpbmih->biSize;
  69. vcp.lpData2 = NULL;
  70. vcp.dwSize2 = 0L;
  71. // See if the driver likes the format
  72. if (SendDriverMessage((HDRVR)hvideoIn, DVM_FORMAT, (LPARAM)(DWORD)VIDEO_CONFIGURE_SET,
  73. (LPARAM)(LPVOID)&vcp))
  74. return FALSE;
  75. // Set the rectangles
  76. rect.left = rect.top = 0;
  77. rect.right = (WORD)lpbmih->biWidth;
  78. rect.bottom = (WORD)lpbmih->biHeight;
  79. SendDriverMessage((HDRVR)hvideoExtIn, DVM_DST_RECT, (LPARAM)(LPVOID)&rect, VIDEO_CONFIGURE_SET);
  80. SendDriverMessage((HDRVR)hvideoIn, DVM_SRC_RECT, (LPARAM)(LPVOID)&rect, VIDEO_CONFIGURE_SET);
  81. return TRUE;
  82. }
  83. BOOL
  84. _GetVideoPalette(
  85. HVIDEO hvideo,
  86. LPCAPTUREPALETTE lpcp,
  87. DWORD dwcbSize
  88. )
  89. {
  90. VIDEOCONFIGPARMS vcp;
  91. vcp.lpdwReturn = NULL;
  92. vcp.lpData1 = (LPVOID)lpcp;
  93. vcp.dwSize1 = dwcbSize;
  94. vcp.lpData2 = NULL;
  95. vcp.dwSize2 = 0;
  96. return !SendDriverMessage((HDRVR)hvideo, DVM_PALETTE,
  97. (DWORD)(VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_CURRENT),
  98. (DWORD_PTR)&vcp);
  99. }
  100. void
  101. FrameCallback(
  102. HVIDEO hvideo,
  103. WORD wMsg,
  104. HCAPDEV hcd, // (Actually refdata)
  105. LPCAPBUFFER lpcbuf, // (Actually LPVIDEOHDR) Only returned from MM_DRVM_DATA!
  106. DWORD dwParam2
  107. )
  108. {
  109. FX_ENTRY("FrameCallback");
  110. DEBUGMSG(ZONE_CALLBACK, ("%s: wMsg=%s, hcd=0x%08lX, lpcbuf=0x%08lX, hcd->hevWait=0x%08lX\r\n", _fx_, (wMsg == MM_DRVM_OPEN) ? "MM_DRVM_OPEN" : (wMsg == MM_DRVM_CLOSE) ? "MM_DRVM_CLOSE" : (wMsg == MM_DRVM_ERROR) ? "MM_DRVM_ERROR" : (wMsg == MM_DRVM_DATA) ? "MM_DRVM_DATA" : "MM_DRVM_?????", hcd, lpcbuf, hcd->hevWait));
  111. // If it's not a data ready message, just set the event and get out.
  112. // The reason we do this is that if we get behind and start getting a stream
  113. // of MM_DRVM_ERROR messages (usually because we're stopped in the debugger),
  114. // we want to make sure we are getting events so we get restarted to handle
  115. // the frames that are 'stuck.'
  116. if (wMsg != MM_DRVM_DATA)
  117. {
  118. DEBUGMSG(ZONE_CALLBACK, ("%s: Setting hcd->hevWait - no data\r\n", _fx_));
  119. SetEvent(hcd->hevWait);
  120. return;
  121. }
  122. //--------------------
  123. // Buffer ready queue:
  124. // We maintain a doubly-linked list of our buffers so that we can buffer up
  125. // multiple ready frames when the app isn't ready to handle them. Two things
  126. // complicate what ought to be a very simple thing: (1) Thunking issues: the pointers
  127. // used on the 16-bit side are 16:16 (2) Interrupt time issues: the FrameCallback
  128. // gets called at interrupt time. GetNextReadyBuffer must handle the fact that
  129. // buffers get added to the list asynchronously.
  130. //
  131. // To handle this, the scheme implemented here is to have a double-linked list
  132. // of buffers with all insertions and deletions happening in FrameCallback
  133. // (interrupt time). This allows the GetNextReadyBuffer routine to simply
  134. // find the previous block on the list any time it needs a new buffer without
  135. // fear of getting tromped (as would be the case if it had to dequeue buffers).
  136. // The FrameCallback routine is responsible to dequeue blocks that GetNextReadyBuffer
  137. // is done with. Dequeueing is simple since we don't need to unlink the blocks:
  138. // no code ever walks the list! All we have to do is move the tail pointer back up
  139. // the list. All the pointers, head, tail, next, prev, are all 16:16 pointers
  140. // since all the list manipulation is on the 16-bit side AND because MapSL is
  141. // much more efficient and safer than MapLS since MapLS has to allocate selectors.
  142. //--------------------
  143. // Move the tail back to skip all buffers already used.
  144. // Note that there is no need to actually unhook the buffer pointers since no one
  145. // ever walks the list!
  146. // This makes STRICT assumptions that the current pointer will always be earlier in
  147. // the list than the tail and that the tail will never be NULL unless the
  148. // current pointer is too.
  149. while (hcd->lpTail != hcd->lpCurrent)
  150. hcd->lpTail = hcd->lpTail->lpPrev;
  151. // If all buffers have been used, then the tail pointer will fall off the list.
  152. // This is normal and the most common code path. In this event, just set the head
  153. // to NULL as the list is now empty.
  154. if (!hcd->lpTail)
  155. hcd->lpHead = NULL;
  156. // Add the new buffer to the ready queue
  157. lpcbuf->lpNext = hcd->lpHead;
  158. lpcbuf->lpPrev = NULL;
  159. if (hcd->lpHead)
  160. hcd->lpHead->lpPrev = lpcbuf;
  161. else
  162. hcd->lpTail = lpcbuf;
  163. hcd->lpHead = lpcbuf;
  164. #if 1
  165. if (hcd->lpCurrent) {
  166. if (!(hcd->dwFlags & HCAPDEV_STREAMING_PAUSED)) {
  167. // if client hasn't consumed last frame, then release it
  168. lpcbuf = hcd->lpCurrent;
  169. hcd->lpCurrent = hcd->lpCurrent->lpPrev;
  170. DEBUGMSG(ZONE_CALLBACK, ("%s: We already have current buffer (lpcbuf=0x%08lX). Returning this buffer to driver. Set new current buffer hcd->lpCurrent=0x%08lX\r\n", _fx_, lpcbuf, hcd->lpCurrent));
  171. // Signal that the application is done with the buffer
  172. lpcbuf->vh.dwFlags &= ~VHDR_DONE;
  173. if (SendDriverMessage(reinterpret_cast<HDRVR>(hvideo), DVM_STREAM_ADDBUFFER, (DWORD_PTR)lpcbuf, sizeof(VIDEOHDR)) != 0)
  174. {
  175. ERRORMESSAGE(("%s: Attempt to reuse unconsumed buffer failed\r\n", _fx_));
  176. }
  177. }
  178. }
  179. else {
  180. #else
  181. if (!hcd->lpCurrent) {
  182. // If there was no current buffer before, we have one now, so set it to the end.
  183. #endif
  184. hcd->lpCurrent = hcd->lpTail;
  185. }
  186. // Now set the event saying it's time to process the ready frame
  187. DEBUGMSG(ZONE_CALLBACK, ("%s: Setting hcd->hevWait - some data\r\n", _fx_));
  188. SetEvent(hcd->hevWait);
  189. }
  190. BOOL
  191. _InitializeVideoStream(
  192. HVIDEO hvideo,
  193. DWORD dwMicroSecPerFrame,
  194. DWORD_PTR hcd
  195. )
  196. {
  197. VIDEO_STREAM_INIT_PARMS vsip;
  198. ZeroMemory((LPSTR)&vsip, sizeof (VIDEO_STREAM_INIT_PARMS));
  199. vsip.dwMicroSecPerFrame = dwMicroSecPerFrame;
  200. vsip.dwCallback = (DWORD_PTR)FrameCallback;
  201. vsip.dwCallbackInst = hcd;
  202. vsip.dwFlags = CALLBACK_FUNCTION;
  203. vsip.hVideo = (DWORD_PTR)hvideo;
  204. return !SendDriverMessage((HDRVR)hvideo, DVM_STREAM_INIT,
  205. (DWORD_PTR)&vsip,
  206. (DWORD) sizeof (VIDEO_STREAM_INIT_PARMS));
  207. }
  208. BOOL
  209. _UninitializeVideoStream(
  210. HVIDEO hvideo
  211. )
  212. {
  213. return !SendDriverMessage((HDRVR)hvideo, DVM_STREAM_FINI, 0L, 0L);
  214. }
  215. BOOL
  216. _InitializeExternalVideoStream(
  217. HVIDEO hvideo
  218. )
  219. {
  220. VIDEO_STREAM_INIT_PARMS vsip;
  221. vsip.dwMicroSecPerFrame = 0; // Ignored by driver for this channel
  222. vsip.dwCallback = 0L; // No callback for now
  223. vsip.dwCallbackInst = 0L;
  224. vsip.dwFlags = 0;
  225. vsip.hVideo = (DWORD_PTR)hvideo;
  226. return !SendDriverMessage((HDRVR)hvideo, DVM_STREAM_INIT,
  227. (DWORD_PTR)&vsip,
  228. (DWORD) sizeof (VIDEO_STREAM_INIT_PARMS));
  229. }
  230. BOOL
  231. _PrepareHeader(
  232. HANDLE hvideo,
  233. VIDEOHDR *vh
  234. )
  235. {
  236. return (SendDriverMessage((HDRVR)hvideo, DVM_STREAM_PREPAREHEADER,
  237. (DWORD_PTR)vh, (DWORD) sizeof (VIDEOHDR)) == DV_ERR_OK);
  238. }
  239. LRESULT
  240. _UnprepareHeader(
  241. HANDLE hvideo,
  242. VIDEOHDR *vh
  243. )
  244. {
  245. return SendDriverMessage((HDRVR)hvideo, DVM_STREAM_UNPREPAREHEADER,
  246. (DWORD_PTR)vh, (DWORD) sizeof (VIDEOHDR));
  247. }
  248.