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.

292 lines
6.8 KiB

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