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.

297 lines
7.0 KiB

  1. #include <win32.h>
  2. #include <mmsystem.h>
  3. #include "debug.h"
  4. #include "aviidx.h"
  5. #include "buffer.h"
  6. #include <vfw.h>
  7. #ifndef _WIN32
  8. LONG glDosBufUsage;
  9. LPVOID glpDosBuf;
  10. LONG glDosBufSize;
  11. #endif
  12. // Idea: keep a bunch (five, maybe) of buffers.
  13. PBUFSYSTEM PASCAL InitBuffered(int nBuffers,
  14. LONG lBufSize,
  15. HSHFILE hshfile,
  16. PAVIINDEX px)
  17. {
  18. PBUFSYSTEM pb = (PBUFSYSTEM)LocalAlloc(LPTR,
  19. sizeof(BUFSYSTEM) + sizeof(BUFFER) * nBuffers);
  20. int i;
  21. LONG l;
  22. if (!pb)
  23. return NULL;
  24. DPF("InitBuffered (%04x): %dx%ldK, pIndex = %p\n", pb, nBuffers, lBufSize / 1024, (DWORD_PTR) (LPVOID) px);
  25. pb->nBuffers = nBuffers;
  26. pb->lBufSize = lBufSize;
  27. pb->px = px;
  28. pb->lx = 0;
  29. pb->lpBufMem = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, lBufSize * nBuffers);
  30. if (!pb->lpBufMem) {
  31. DPF("Couldn't allocate buffer memory!\n");
  32. EndBuffered(pb);
  33. return NULL;
  34. }
  35. pb->hshfile = hshfile;
  36. l = shfileSeek(hshfile, 0, SEEK_CUR);
  37. pb->lFileLength = shfileSeek(hshfile, 0, SEEK_END);
  38. shfileSeek(hshfile, l, SEEK_SET);
  39. for (i = 0; i < nBuffers; i++) {
  40. pb->aBuf[i].lpBuffer = (BYTE _huge *) pb->lpBufMem + i * lBufSize;
  41. pb->aBuf[i].lOffset = -1;
  42. }
  43. return pb;
  44. }
  45. LONG FAR PASCAL BufferedRead(PBUFSYSTEM pb, LONG lPos, LONG cb, LPVOID lp)
  46. {
  47. int i;
  48. LPVOID lpCopy;
  49. LONG cbCopy;
  50. LONG cbRead = cb;
  51. LONG l;
  52. #if 0
  53. if (cb > pb->lBufSize) {
  54. if (shfileSeek(pb->hshfile, lPos, SEEK_SET) == -1)
  55. return 0;
  56. if (shfileRead(pb->hshfile, lp, cb) != cb)
  57. return 0;
  58. return cb;
  59. }
  60. #endif
  61. while (cb > 0) {
  62. if (lPos >= pb->lFileLength)
  63. break;
  64. // Find a buffer.
  65. for (i = 0; i < pb->nBuffers; i++) {
  66. if (pb->aBuf[i].lOffset < 0)
  67. continue;
  68. if (pb->aBuf[i].lOffset <= lPos &&
  69. pb->aBuf[i].lOffset + pb->aBuf[i].lLength > lPos)
  70. break;
  71. }
  72. // If we didn't find a buffer with valid data, read more.
  73. if (i >= pb->nBuffers) {
  74. i = pb->iNextBuf;
  75. if (pb->px) {
  76. LONG off,len;
  77. for (l = pb->lx; l>=0 && l<pb->px->nIndex; ) {
  78. off = IndexOffset(pb->px, l);
  79. len = IndexLength(pb->px, l) + 2*sizeof(DWORD);
  80. if (off <= lPos && lPos < off + len)
  81. break;
  82. if (lPos < off)
  83. l--;
  84. else
  85. l++;
  86. }
  87. if (l == pb->px->nIndex || l < 0) {
  88. DPF("Ran out of index!\n");
  89. goto ack;
  90. }
  91. if (len > pb->lBufSize) {
  92. DPF("Chunk is bigger than buffer.\n");
  93. goto ack;
  94. }
  95. pb->aBuf[i].lOffset = off;
  96. pb->aBuf[i].lLength = len;
  97. DPF2("Buffer: Reading %lx bytes at %lx\n", pb->aBuf[i].lLength, pb->aBuf[i].lOffset);
  98. //
  99. // read as many records that will fit in our buffer
  100. //
  101. // we should scan backward!
  102. //
  103. for (l++; l<pb->px->nIndex; l++) {
  104. off = IndexOffset(pb->px, l);
  105. len = IndexLength(pb->px, l) + 2*sizeof(DWORD);
  106. if (off < pb->aBuf[i].lOffset + pb->aBuf[i].lLength)
  107. continue;
  108. if (off != pb->aBuf[i].lOffset + pb->aBuf[i].lLength)
  109. break;
  110. if (pb->aBuf[i].lLength + len > pb->lBufSize)
  111. break;
  112. pb->aBuf[i].lLength += len;
  113. DPF2(" Reading %lx bytes at %lx\n", pb->aBuf[i].lLength, pb->aBuf[i].lOffset);
  114. }
  115. if (l < pb->px->nIndex)
  116. pb->lx = l; // save this for next time.
  117. } else
  118. {
  119. ack:
  120. // Always read aligned with the buffer size....
  121. pb->aBuf[i].lOffset = lPos - (lPos % pb->lBufSize);
  122. pb->aBuf[i].lLength =
  123. min(pb->lFileLength - pb->aBuf[i].lOffset,
  124. pb->lBufSize);
  125. DPF("Buffer: Reading %lx bytes at %lx\n", pb->aBuf[i].lLength, pb->aBuf[i].lOffset);
  126. }
  127. shfileSeek(pb->hshfile, pb->aBuf[i].lOffset, SEEK_SET);
  128. #ifndef _WIN32
  129. if (glpDosBuf) {
  130. if (shfileRead(pb->hshfile,
  131. glpDosBuf,
  132. pb->aBuf[i].lLength) != pb->aBuf[i].lLength)
  133. return 0;
  134. hmemcpy(pb->aBuf[i].lpBuffer, glpDosBuf, pb->aBuf[i].lLength);
  135. }
  136. else
  137. #endif
  138. {
  139. if (shfileRead(pb->hshfile,
  140. pb->aBuf[i].lpBuffer,
  141. pb->aBuf[i].lLength) != pb->aBuf[i].lLength)
  142. return 0;
  143. }
  144. // !!! We should use an LRU algorithm or something here....
  145. pb->iNextBuf = (i + 1) % pb->nBuffers;
  146. }
  147. lpCopy = (BYTE _huge *) pb->aBuf[i].lpBuffer + lPos - pb->aBuf[i].lOffset;
  148. cbCopy = min(cb, pb->aBuf[i].lLength - (lPos - pb->aBuf[i].lOffset));
  149. hmemcpy(lp, lpCopy, cbCopy);
  150. lp = (BYTE _huge *) lp + cbCopy;
  151. cb -= cbCopy;
  152. lPos += cbCopy;
  153. }
  154. return cbRead;
  155. }
  156. LONG FAR PASCAL BeginBufferedStreaming(PBUFSYSTEM pb, BOOL fForward)
  157. {
  158. if (pb->fStreaming++)
  159. return 0;
  160. DPF("Streaming....\n");
  161. #ifndef _WIN32
  162. if (pb->px) {
  163. if (glDosBufSize < pb->lBufSize
  164. #ifdef DEBUG
  165. && GetProfileInt("avifile", "dosbuffer", 1)
  166. #endif
  167. ) {
  168. LPVOID lpDosBuf;
  169. lpDosBuf = (LPVOID)MAKELONG(0, LOWORD(GlobalDosAlloc(pb->lBufSize)));
  170. if (!lpDosBuf) {
  171. DPF("Couldn't get DOS buffer!\n");
  172. } else {
  173. GlobalReAlloc((HANDLE)HIWORD(lpDosBuf), 0, GMEM_MODIFY|GMEM_SHARE);
  174. if (glpDosBuf)
  175. GlobalDosFree(HIWORD(glpDosBuf));
  176. glpDosBuf = lpDosBuf;
  177. glDosBufSize = pb->lBufSize;
  178. }
  179. }
  180. if (glpDosBuf && (glDosBufSize >= pb->lBufSize)) {
  181. pb->fUseDOSBuf = TRUE;
  182. glDosBufUsage++;
  183. } else
  184. pb->fUseDOSBuf = FALSE;
  185. }
  186. #endif
  187. return 0;
  188. }
  189. LONG FAR PASCAL EndBufferedStreaming(PBUFSYSTEM pb)
  190. {
  191. if (!pb->fStreaming)
  192. return AVIERR_INTERNAL;
  193. if (--pb->fStreaming)
  194. return 0;
  195. DPF("No longer streaming....\n");
  196. #ifndef _WIN32
  197. if (pb->fUseDOSBuf) {
  198. if (--glDosBufUsage == 0) {
  199. if (glpDosBuf)
  200. GlobalDosFree(HIWORD(glpDosBuf));
  201. glpDosBuf = NULL;
  202. }
  203. pb->fUseDOSBuf = FALSE;
  204. }
  205. #endif
  206. return 0;
  207. }
  208. void FAR PASCAL EndBuffered(PBUFSYSTEM pb)
  209. {
  210. DPF("Freeing bufsystem %04x....\n", pb);
  211. if (pb->lpBufMem)
  212. GlobalFreePtr(pb->lpBufMem);
  213. #ifndef _WIN32
  214. if (pb->fUseDOSBuf) {
  215. if (--glDosBufUsage == 0) {
  216. if (glpDosBuf)
  217. GlobalDosFree(HIWORD(glpDosBuf));
  218. glpDosBuf = NULL;
  219. glDosBufSize = 0;
  220. }
  221. }
  222. #endif
  223. LocalFree((HLOCAL)pb);
  224. }