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.

759 lines
19 KiB

  1. /****************************************************************************
  2. *
  3. * ACMSTRM.C
  4. *
  5. * routine for compressing audio with the ACM
  6. *
  7. * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved.
  8. *
  9. * You have a royalty-free right to use, modify, reproduce and
  10. * distribute the Sample Files (and/or any modified version) in
  11. * any way you find useful, provided that you agree that
  12. * Microsoft has no warranty obligations or liability for any
  13. * Sample Application Files which are modified.
  14. *
  15. ***************************************************************************/
  16. //
  17. // What this file does:
  18. //
  19. // Given an audio Stream (that is, essentially, a function that it can call
  20. // to get audio samples), this presents the same sort of interface and allows
  21. // other people to call it to get compressed audio.
  22. //
  23. #include <win32.h>
  24. #include <vfw.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <malloc.h>
  28. #include <ctype.h>
  29. #include <mmreg.h>
  30. #include <msacm.h>
  31. #include "avifilei.h" // uUseCount
  32. #include "acmcmprs.h"
  33. #include "avifile.rc" // for resource ids
  34. #include "debug.h"
  35. EXTERN_C HINSTANCE ghMod;
  36. #define WAVEFORMATSIZE(pwf) \
  37. ((((LPWAVEFORMAT)(pwf))->wFormatTag == WAVE_FORMAT_PCM) ? \
  38. sizeof(PCMWAVEFORMAT) : \
  39. sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)(pwf))->cbSize)
  40. HRESULT CACMCmpStream::MakeInst(
  41. IUnknown FAR* pUnknownOuter,
  42. const IID FAR& riid,
  43. void FAR* FAR* ppv)
  44. {
  45. IUnknown FAR* pUnknown;
  46. CACMCmpStream FAR* pAVIStream;
  47. HRESULT hresult;
  48. pAVIStream = new FAR CACMCmpStream(pUnknownOuter, &pUnknown);
  49. if (!pAVIStream)
  50. return ResultFromScode(E_OUTOFMEMORY);
  51. hresult = pUnknown->QueryInterface(riid, ppv);
  52. if (FAILED(GetScode(hresult)))
  53. delete pAVIStream;
  54. return hresult;
  55. }
  56. /* - - - - - - - - */
  57. CACMCmpStream::CACMCmpStream(
  58. IUnknown FAR* pUnknownOuter,
  59. IUnknown FAR* FAR* ppUnknown)
  60. {
  61. m_pavi = 0;
  62. m_hs = 0;
  63. m_lpFormat = 0;
  64. m_lpFormatC = 0;
  65. m_lpIn = 0;
  66. m_lpOut = 0;
  67. if (pUnknownOuter)
  68. m_pUnknownOuter = pUnknownOuter;
  69. else
  70. m_pUnknownOuter = this;
  71. *ppUnknown = this;
  72. m_refs = 0;
  73. }
  74. /* - - - - - - - - */
  75. STDMETHODIMP CACMCmpStream::QueryInterface(
  76. const IID FAR& iid,
  77. void FAR* FAR* ppv)
  78. {
  79. if (iid == IID_IUnknown)
  80. *ppv = (IUnknown FAR *) this;
  81. else if (iid == IID_IAVIStream)
  82. *ppv = (IAVIStream FAR *) this;
  83. else {
  84. *ppv = NULL;
  85. return ResultFromScode(E_NOINTERFACE);
  86. }
  87. AddRef();
  88. return NULL;
  89. }
  90. /* - - - - - - - - */
  91. STDMETHODIMP_(ULONG) CACMCmpStream::AddRef()
  92. {
  93. uUseCount++;
  94. return ++m_refs;
  95. }
  96. /* - - - - - - - - */
  97. LONG CACMCmpStream::SetUpCompression()
  98. {
  99. LONG lRet = AVIERR_OK;
  100. MMRESULT err;
  101. // Get the initial format
  102. AVIStreamFormatSize(m_pavi, AVIStreamStart(m_pavi), &m_cbFormat);
  103. m_lpFormat = (LPWAVEFORMATEX) GlobalAllocPtr(GHND | GMEM_SHARE, m_cbFormat);
  104. if (!m_lpFormat) {
  105. lRet = AVIERR_MEMORY;
  106. goto exit;
  107. }
  108. AVIStreamReadFormat(m_pavi, AVIStreamStart(m_pavi), m_lpFormat, &m_cbFormat);
  109. if (m_lpFormatC != NULL) {
  110. // we already have the format, let's hope it works...
  111. // We could check if the format matches the original format....
  112. if (m_cbFormat == m_cbFormatC &&
  113. (_fmemcmp(m_lpFormat, m_lpFormatC, (int) m_cbFormat) == 0))
  114. goto sameformat;
  115. } else if (m_lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
  116. acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&m_cbFormatC);
  117. m_lpFormatC = (LPWAVEFORMATEX) GlobalAllocPtr(GHND | GMEM_SHARE, m_cbFormatC);
  118. if (!m_lpFormatC) {
  119. lRet = AVIERR_MEMORY;
  120. goto exit;
  121. }
  122. m_lpFormatC->wFormatTag = WAVE_FORMAT_PCM;
  123. if (acmFormatSuggest(NULL, m_lpFormat, m_lpFormatC, m_cbFormatC, 0L) != 0)
  124. goto sameformat;
  125. } else {
  126. sameformat:
  127. DPF("Leaving the format unchanged....\n");
  128. m_lpFormatC = m_lpFormat;
  129. m_cbFormatC = m_cbFormat;
  130. m_lpFormat = NULL;
  131. m_cbFormat = 0;
  132. m_hs = (HACMSTREAM) -1;
  133. goto exit;
  134. }
  135. ACMFORMATDETAILS afdU;
  136. ACMFORMATTAGDETAILS aftdU;
  137. ACMFORMATDETAILS afdC;
  138. ACMFORMATTAGDETAILS aftdC;
  139. afdU.cbStruct = sizeof(afdU);
  140. afdU.pwfx = m_lpFormat;
  141. afdU.cbwfx = m_cbFormat;
  142. afdU.fdwSupport = 0;
  143. afdU.dwFormatTag = m_lpFormat->wFormatTag;
  144. acmFormatDetails(NULL, &afdU, ACM_FORMATDETAILSF_FORMAT);
  145. aftdU.cbStruct = sizeof(aftdU);
  146. aftdU.dwFormatTag = m_lpFormat->wFormatTag;
  147. aftdU.fdwSupport = 0;
  148. acmFormatTagDetails(NULL,
  149. &aftdU, ACM_FORMATTAGDETAILSF_FORMATTAG);
  150. afdC.cbStruct = sizeof(afdC);
  151. afdC.pwfx = m_lpFormatC;
  152. afdC.cbwfx = m_cbFormatC;
  153. afdC.dwFormatTag = m_lpFormatC->wFormatTag;
  154. afdC.fdwSupport = 0;
  155. acmFormatDetails(NULL, &afdC, ACM_FORMATDETAILSF_FORMAT);
  156. aftdC.cbStruct = sizeof(aftdC);
  157. aftdC.dwFormatTag = m_lpFormatC->wFormatTag;
  158. aftdC.fdwSupport = 0;
  159. acmFormatTagDetails(NULL,
  160. &aftdC,
  161. ACM_FORMATTAGDETAILSF_FORMATTAG);
  162. DPF("Converting %s %s to %s %s\n", (LPSTR) &aftdU.szFormatTag, (LPSTR) &afdU.szFormat, (LPSTR) &aftdC.szFormatTag, (LPSTR) &afdC.szFormat);
  163. // Open the compressor they asked for...
  164. lRet = acmStreamOpen(&m_hs, // returned stream handle
  165. NULL, // use any converter you want
  166. m_lpFormat, // starting format
  167. m_lpFormatC, // ending format
  168. 0L, // no filter
  169. 0L, // no callback
  170. 0L, // instance data for callback
  171. ACM_STREAMOPENF_NONREALTIME);//emph. quality not speed
  172. // !!! translate error code
  173. if (!m_hs) {
  174. DPF("Unable to convert!\n");
  175. #if 0
  176. TCHAR * pachMessage;
  177. TCHAR achTemp[128];
  178. static int iEntered = 0;
  179. LPTSTR aStrings[4];
  180. // !!! This isn't defined in dev\inc\windows.h. I don't understand why.
  181. #ifndef FORMAT_MESSAGE_ARGUMENT_ARRAY
  182. #define FORMAT_MESSAGE_ARGUMENT_ARRAY 0
  183. #endif
  184. aStrings[0] = (LPTSTR) &aftdU.szFormatTag;
  185. aStrings[1] = (LPTSTR) &afdU.szFormat;
  186. aStrings[2] = (LPTSTR) &aftdC.szFormatTag;
  187. aStrings[3] = (LPTSTR) &afdC.szFormat;
  188. FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
  189. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  190. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  191. (LPVOID) ghInst,
  192. IDS_CNVTERR,
  193. 0, // !!! GetSystemDefaultLanguage?
  194. (LPTSTR) &pachMessage,
  195. 999,
  196. (LPDWORD) &aStrings); // !!! needs to be va_list for NT?
  197. LoadString(ghInst, IDS_ACMERR, (LPTSTR)achTemp, sizeof(achTemp)/sizeof(TCHAR));
  198. if (iEntered++ == 0)
  199. MessageBox(NULL, pachMessage, achTemp, MB_OK);
  200. iEntered--;
  201. LocalFree((HLOCAL) pachMessage);
  202. #endif
  203. lRet = AVIERR_ERROR;
  204. goto exit;
  205. }
  206. // Fix avistream header
  207. m_avistream.dwSampleSize = m_lpFormatC->nBlockAlign;
  208. m_avistream.dwScale = m_lpFormatC->nBlockAlign;
  209. m_avistream.dwRate = m_lpFormatC->nAvgBytesPerSec;
  210. acmStreamSize(m_hs,
  211. AVIStreamLength(m_pavi) * m_lpFormat->nBlockAlign,
  212. (LPDWORD) &m_avistream.dwLength,
  213. ACM_STREAMSIZEF_SOURCE);
  214. // !!! acmStreamSize rounds up here, do we need to compensate?
  215. // !!! should we round off/up here?
  216. m_avistream.dwLength /= m_lpFormatC->nBlockAlign;
  217. m_avistream.dwQuality = 0; // !!!
  218. m_cbIn = 4096; // !!!
  219. m_cbIn -= m_cbIn % m_lpFormat->nBlockAlign; // round down to block aligned
  220. acmStreamSize(m_hs,
  221. m_cbIn,
  222. (LPDWORD) &m_cbOut,
  223. ACM_STREAMSIZEF_SOURCE);
  224. DPF("ACM conversion: input %ld bytes, output %ld bytes\n", m_cbIn, m_cbOut);
  225. m_lpIn = (BYTE _huge *) GlobalAllocPtr(GHND, m_cbIn);
  226. m_lpOut = (BYTE _huge *) GlobalAllocPtr(GHND, m_cbOut);
  227. if (!m_lpIn || !m_lpOut) {
  228. lRet = AVIERR_MEMORY;
  229. goto exit;
  230. }
  231. m_acm.cbStruct = sizeof(m_acm);
  232. m_acm.fdwStatus = 0;
  233. m_acm.dwUser = 0;
  234. m_acm.pbSrc = m_lpIn;
  235. m_acm.cbSrcLength = m_cbIn;
  236. m_acm.cbSrcLengthUsed = 0;
  237. m_acm.pbDst = m_lpOut;
  238. m_acm.cbDstLength = m_cbOut;
  239. m_acm.cbDstLengthUsed = 0;
  240. // !!! add in start, end flags for ACM....
  241. err = acmStreamPrepareHeader(m_hs, &m_acm, 0);
  242. if (err != 0) {
  243. DPF("acmStreamPrepareHeader returns %u\n", err);
  244. return AVIERR_COMPRESSOR;
  245. }
  246. m_dwPosIn = m_dwPosOut = 0;
  247. m_dwSamplesLeft = 0;
  248. exit:
  249. if (lRet != AVIERR_OK) {
  250. // Don't release here!
  251. }
  252. return lRet;
  253. }
  254. /* - - - - - - - - */
  255. //
  256. // ACM stream:
  257. //
  258. // lParam1 should be a PAVISTREAM (an audio one!)
  259. //
  260. // lParam2 should be an LPWAVEFORMAT for the format you want converted
  261. // to.
  262. //
  263. STDMETHODIMP CACMCmpStream::Create(LPARAM lParam1, LPARAM lParam2)
  264. {
  265. PAVISTREAM pavi = (PAVISTREAM) lParam1;
  266. LPAVICOMPRESSOPTIONS lpOpts = (LPAVICOMPRESSOPTIONS) lParam2;
  267. LPWAVEFORMAT lpwfNew = NULL;
  268. LONG lRet = AVIERR_OK;
  269. DPF("Creating ACM compression stream....\n");
  270. // Get the stream header for future reference....
  271. pavi->Info(&m_avistream, sizeof(m_avistream));
  272. m_avistream.fccHandler = 0;
  273. if (m_avistream.fccType != streamtypeAUDIO) {
  274. DPF("Stream isn't audio!\n");
  275. lRet = AVIERR_INTERNAL;
  276. goto exit;
  277. }
  278. if (acmGetVersion() < 0x02000000L) {
  279. DPF("Bad ACM version!\n");
  280. lRet = AVIERR_INTERNAL;
  281. goto exit;
  282. }
  283. if (lpOpts && lpOpts->lpFormat) {
  284. lpwfNew = (LPWAVEFORMAT) lpOpts->lpFormat;
  285. if (lpOpts->cbFormat < WAVEFORMATSIZE(lpwfNew)) {
  286. DPF("Bad format size!\n");
  287. lRet = AVIERR_INTERNAL;
  288. goto exit;
  289. }
  290. m_cbFormatC = WAVEFORMATSIZE(lpwfNew);
  291. m_lpFormatC = (LPWAVEFORMATEX) GlobalAllocPtr(GMEM_MOVEABLE, m_cbFormatC);
  292. if (m_lpFormatC == NULL) {
  293. DPF("Out of memory for format!\n");
  294. lRet = AVIERR_MEMORY;
  295. goto exit;
  296. }
  297. hmemcpy(m_lpFormatC, lpOpts->lpFormat, m_cbFormatC);
  298. } else {
  299. m_cbFormatC = 0;
  300. m_lpFormatC = NULL;
  301. }
  302. // Make sure the uncompressed stream doesn't go away without our
  303. // knowledge....
  304. AVIStreamAddRef(pavi);
  305. // Don't put this in the structure until we've done the AddRef....
  306. m_pavi = pavi;
  307. exit:
  308. return ResultFromScode(lRet);
  309. }
  310. STDMETHODIMP_(ULONG) CACMCmpStream::Release()
  311. {
  312. uUseCount--;
  313. if (--m_refs)
  314. return m_refs;
  315. if (m_lpFormat) {
  316. GlobalFreePtr(m_lpFormat);
  317. if (m_hs) {
  318. m_acm.cbSrcLength = m_cbIn;
  319. acmStreamUnprepareHeader(m_hs, &m_acm, 0);
  320. acmStreamClose(m_hs, 0);
  321. }
  322. }
  323. if (m_lpIn) {
  324. GlobalFreePtr(m_lpIn);
  325. }
  326. if (m_lpOut) {
  327. GlobalFreePtr(m_lpOut);
  328. }
  329. if (m_pavi) {
  330. // Release our hold on the uncompressed stream....
  331. AVIStreamClose(m_pavi);
  332. }
  333. if (m_lpFormatC)
  334. GlobalFreePtr(m_lpFormatC);
  335. delete this;
  336. return 0;
  337. }
  338. STDMETHODIMP CACMCmpStream::Info(AVISTREAMINFOW FAR * psi, LONG lSize)
  339. {
  340. if (m_hs == 0) {
  341. LONG lRet;
  342. // !!! If they ask for info before writing or setting the
  343. // format, this will become a "read" stream!
  344. lRet = SetUpCompression();
  345. if (lRet != 0)
  346. return ResultFromScode(lRet);
  347. }
  348. hmemcpy(psi, &m_avistream, min(lSize, sizeof(m_avistream)));
  349. // return sizeof(m_avistream);
  350. return 0;
  351. }
  352. STDMETHODIMP CACMCmpStream::ReadFormat(LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat)
  353. {
  354. LONG lRet;
  355. if (m_hs == 0) {
  356. lRet = SetUpCompression();
  357. if (lRet != 0)
  358. return ResultFromScode(lRet);
  359. }
  360. if (lpFormat)
  361. hmemcpy(lpFormat,
  362. m_lpFormatC,
  363. min(*lpcbFormat, (LONG) m_cbFormatC));
  364. *lpcbFormat = (LONG) m_cbFormatC;
  365. return 0;
  366. }
  367. STDMETHODIMP CACMCmpStream::Read(
  368. LONG lStart,
  369. LONG lSamples,
  370. LPVOID lpBuffer,
  371. LONG cbBuffer,
  372. LONG FAR * plBytes,
  373. LONG FAR * plSamples)
  374. {
  375. LONG lRet;
  376. MMRESULT err;
  377. HRESULT hr;
  378. if (plBytes)
  379. *plBytes = 0;
  380. if (plSamples)
  381. *plSamples = 0;
  382. if (m_hs == 0) {
  383. lRet = SetUpCompression();
  384. if (lRet != 0)
  385. return ResultFromScode(lRet);
  386. }
  387. if (m_lpFormat == NULL) {
  388. // Just return original format....
  389. return AVIStreamRead(m_pavi, lStart, lSamples,
  390. lpBuffer, cbBuffer, plBytes, plSamples);
  391. }
  392. if (lStart < 0 || lStart > (LONG) (m_avistream.dwStart + m_avistream.dwLength))
  393. return ResultFromScode(AVIERR_BADPARAM);
  394. if (lSamples == AVISTREAMREAD_CONVENIENT) {
  395. // If they didn't specify a number of samples, fill their buffer....
  396. lSamples = (cbBuffer ? cbBuffer : 32768L) / m_lpFormatC->nBlockAlign;
  397. }
  398. // Don't let anybody try to read past the end....
  399. if (lSamples + lStart >
  400. (LONG) (m_avistream.dwStart + m_avistream.dwLength))
  401. lSamples = (LONG) (m_avistream.dwStart + m_avistream.dwLength) -
  402. lStart;
  403. if (lSamples <= 0)
  404. return ResultFromScode(AVIERR_BADPARAM);
  405. if (lpBuffer) {
  406. LONG lBytes;
  407. if (cbBuffer < lSamples * m_lpFormatC->nBlockAlign) {
  408. DPF("Returning buffer too small\n");
  409. if (plBytes)
  410. *plBytes = lSamples * m_lpFormatC->nBlockAlign;
  411. return ResultFromScode(AVIERR_BUFFERTOOSMALL);
  412. }
  413. if (lStart < m_dwPosOut) {
  414. // !!! return to beginning!
  415. m_dwPosOut = 0;
  416. m_dwPosIn = AVIStreamStart(m_pavi);
  417. m_dwSamplesLeft = 0;
  418. }
  419. while (lSamples > 0) {
  420. DPF("Want %ld samples at %ld (PosOut=%ld, SamplesLeft=%ld)\n", lSamples, lStart, m_dwPosOut, m_dwSamplesLeft);
  421. if (lStart >= m_dwPosOut + m_dwSamplesLeft) {
  422. // Throw away current converted buffer....
  423. m_dwPosOut += m_dwSamplesLeft;
  424. hr = AVIStreamRead(m_pavi,
  425. m_dwPosIn, m_cbIn / m_lpFormat->nBlockAlign,
  426. m_lpIn, m_cbIn, &lBytes, &lRet);
  427. if (lBytes != m_cbIn) {
  428. DPF("AVIStreamRead: Asked for %lx bytes at %lx, got %lx!\n", m_cbIn, m_dwPosIn, lBytes);
  429. if (lBytes < m_cbIn) {
  430. // Fill buffer with silence, and hope....
  431. BYTE _huge *hp;
  432. LONG cb;
  433. BYTE b;
  434. cb = (m_cbIn - lBytes);
  435. hp = (BYTE _huge *) m_lpIn + lBytes;
  436. if ((m_lpFormat->wFormatTag == WAVE_FORMAT_PCM) &&
  437. (m_lpFormat->wBitsPerSample == 8))
  438. b = 0x80;
  439. else
  440. b = 0;
  441. while (cb-- > 0)
  442. *hp++ = b;
  443. // If we couldn't read anything, pretend we
  444. // really read enough.
  445. if (lBytes == 0 && m_dwPosIn >= AVIStreamLength(m_pavi)) {
  446. lBytes = m_cbIn;
  447. hr = NOERROR;
  448. }
  449. }
  450. // !!!
  451. // lSampLen = lRet; // !!!
  452. // lByteLen = lSampLen * m_lpFormat->nBlockAlign;
  453. }
  454. if (FAILED(GetScode(hr))) {
  455. DPF("AVIStreamReadFailed! (start=%lx, len=%lx, err=%08lx)\n", m_dwPosIn, m_cbIn / m_lpFormat->nBlockAlign, hr);
  456. return hr;
  457. }
  458. m_acm.cbSrcLength = lBytes;
  459. err = acmStreamConvert(m_hs, &m_acm, ACM_STREAMCONVERTF_BLOCKALIGN);
  460. if (err != 0) {
  461. DPF("acmStreamConvert returns %u\n", err);
  462. return ResultFromScode(AVIERR_COMPRESSOR);
  463. }
  464. DPF("Converted %lu of %lu bytes to %lu bytes (buffer size = %lu)\n", m_acm.cbSrcLengthUsed, m_acm.cbSrcLength, m_acm.cbDstLengthUsed, m_acm.cbDstLength);
  465. if (m_acm.cbSrcLengthUsed == 0) {
  466. err = acmStreamConvert(m_hs, &m_acm, 0);
  467. if (err != 0) {
  468. DPF("acmStreamConvert returns %u\n", err);
  469. return ResultFromScode(AVIERR_COMPRESSOR);
  470. }
  471. DPF("Converted (non-blockalign) %lu of %lu bytes to %lu bytes (buffer size = %lu)\n", m_acm.cbSrcLengthUsed, m_acm.cbSrcLength, m_acm.cbDstLengthUsed, m_acm.cbDstLength);
  472. }
  473. // Lie: say that the ACM returned a full block....
  474. // !!! acm.cbDstLengthUsed += m_lpFormatC->nBlockAlign - 1;
  475. // acm.cbDstLengthUsed -= acm.cbDstLengthUsed % m_lpFormatC->nBlockAlign;
  476. m_dwPosIn += m_acm.cbSrcLengthUsed / m_lpFormat->nBlockAlign;
  477. m_dwSamplesLeft = (m_acm.cbDstLengthUsed + m_lpFormatC->nBlockAlign - 1) / m_lpFormatC->nBlockAlign;
  478. if (m_dwSamplesLeft == 0) {
  479. // Instead, say that we got one block back, 0 bytes long.
  480. DPF("ACM returned no data at all! Ack!\n");
  481. m_dwSamplesLeft = 1;
  482. }
  483. m_dwBytesMissing = m_dwSamplesLeft * m_lpFormatC->nBlockAlign - m_acm.cbDstLengthUsed;
  484. }
  485. if (lStart >= m_dwPosOut) {
  486. LONG lSamplesRead;
  487. LONG lBytesRead;
  488. lSamplesRead = min(m_dwSamplesLeft - (lStart - m_dwPosOut),
  489. lSamples);
  490. lBytesRead = lSamplesRead * m_lpFormatC->nBlockAlign;
  491. if (m_dwBytesMissing &&
  492. (lStart - m_dwPosOut + lSamplesRead == m_dwSamplesLeft)) {
  493. DPF("Not copying %ld missing bytes....\n", m_dwBytesMissing);
  494. lBytesRead -= m_dwBytesMissing;
  495. }
  496. DPF("Copying %ld samples... (%ld bytes)\n", lSamplesRead, lBytesRead);
  497. hmemcpy(lpBuffer,
  498. (BYTE _huge *) m_lpOut +
  499. (lStart - m_dwPosOut) * m_lpFormatC->nBlockAlign,
  500. lBytesRead);
  501. if (plBytes)
  502. *plBytes += lBytesRead;
  503. if (plSamples)
  504. *plSamples += lSamplesRead;
  505. lSamples -= lSamplesRead;
  506. lpBuffer = (BYTE _huge *) lpBuffer +
  507. lSamplesRead * m_lpFormatC->nBlockAlign;
  508. lStart += lSamplesRead;
  509. }
  510. }
  511. } else {
  512. // We always assume we could read whatever they asked for....
  513. if (plBytes)
  514. *plBytes = lSamples * m_lpFormatC->nBlockAlign;
  515. if (plSamples)
  516. *plSamples = lSamples;
  517. }
  518. return 0;
  519. }
  520. STDMETHODIMP_(LONG) CACMCmpStream::FindSample(LONG lPos, LONG lFlags)
  521. {
  522. if (lFlags & FIND_FORMAT) {
  523. if (lFlags & FIND_PREV)
  524. return 0;
  525. else {
  526. if (lPos > 0)
  527. return -1;
  528. else
  529. return 0;
  530. }
  531. }
  532. return lPos;
  533. }
  534. STDMETHODIMP CACMCmpStream::SetFormat(LONG lPos,LPVOID lpFormat,LONG cbFormat)
  535. {
  536. // !!! It should really be possible to use SetFormat & Write on this
  537. // stream.....
  538. return ResultFromScode(AVIERR_UNSUPPORTED);
  539. }
  540. STDMETHODIMP CACMCmpStream::Write(LONG lStart,
  541. LONG lSamples,
  542. LPVOID lpBuffer,
  543. LONG cbBuffer,
  544. DWORD dwFlags,
  545. LONG FAR *plSampWritten,
  546. LONG FAR *plBytesWritten)
  547. {
  548. // !!!
  549. // Maybe this is the place to decompress data and write it to the original
  550. // stream?
  551. return ResultFromScode(AVIERR_UNSUPPORTED);
  552. }
  553. STDMETHODIMP CACMCmpStream::Delete(LONG lStart,LONG lSamples)
  554. {
  555. return ResultFromScode(AVIERR_UNSUPPORTED);
  556. }
  557. STDMETHODIMP CACMCmpStream::ReadData(DWORD fcc, LPVOID lp, LONG FAR *lpcb)
  558. {
  559. return AVIStreamReadData(m_pavi, fcc, lp, lpcb);
  560. }
  561. STDMETHODIMP CACMCmpStream::WriteData(DWORD fcc, LPVOID lp, LONG cb)
  562. {
  563. return ResultFromScode(AVIERR_UNSUPPORTED);
  564. }
  565. #if 0
  566. STDMETHODIMP CACMCmpStream::Clone(PAVISTREAM FAR * ppaviNew)
  567. {
  568. return ResultFromScode(AVIERR_UNSUPPORTED);
  569. }
  570. #endif
  571. #ifdef _WIN32
  572. STDMETHODIMP CACMCmpStream::SetInfo(AVISTREAMINFOW FAR *lpInfo, LONG cbInfo)
  573. {
  574. return ResultFromScode(AVIERR_UNSUPPORTED);
  575. }
  576. #else
  577. STDMETHODIMP CACMCmpStream::Reserved1(void)
  578. {
  579. return ResultFromScode(AVIERR_UNSUPPORTED);
  580. }
  581. STDMETHODIMP CACMCmpStream::Reserved2(void)
  582. {
  583. return ResultFromScode(AVIERR_UNSUPPORTED);
  584. }
  585. STDMETHODIMP CACMCmpStream::Reserved3(void)
  586. {
  587. return ResultFromScode(AVIERR_UNSUPPORTED);
  588. }
  589. STDMETHODIMP CACMCmpStream::Reserved4(void)
  590. {
  591. return ResultFromScode(AVIERR_UNSUPPORTED);
  592. }
  593. STDMETHODIMP CACMCmpStream::Reserved5(void)
  594. {
  595. return ResultFromScode(AVIERR_UNSUPPORTED);
  596. }
  597. #endif