733 lines
17 KiB
C++
733 lines
17 KiB
C++
/****************************************************************************
|
|
*
|
|
* ACMSTRM.C
|
|
*
|
|
* routine for compressing audio with the ACM
|
|
*
|
|
* Copyright (c) 1992 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* You have a royalty-free right to use, modify, reproduce and
|
|
* distribute the Sample Files (and/or any modified version) in
|
|
* any way you find useful, provided that you agree that
|
|
* Microsoft has no warranty obligations or liability for any
|
|
* Sample Application Files which are modified.
|
|
*
|
|
***************************************************************************/
|
|
|
|
|
|
//
|
|
// What this file does:
|
|
//
|
|
// Given an audio Stream (that is, essentially, a function that it can call
|
|
// to get audio samples), this presents the same sort of interface and allows
|
|
// other people to call it to get compressed audio.
|
|
//
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <win32.h>
|
|
#include <mmsystem.h>
|
|
#include <vfw.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <ctype.h>
|
|
#include <compobj.h>
|
|
#include <mmreg.h>
|
|
#include <msacm.h>
|
|
#include "handler.h"
|
|
|
|
#ifndef WIN32
|
|
extern "C" LONG FAR PASCAL muldiv32(LONG,LONG,LONG);
|
|
#endif
|
|
|
|
|
|
#ifdef DEBUG
|
|
static void CDECL dprintf(LPSTR, ...);
|
|
#define DPF dprintf
|
|
#else
|
|
#define DPF ; / ## /
|
|
#endif
|
|
|
|
#define WAVEFORMATSIZE(pwf) \
|
|
((((LPWAVEFORMAT)(pwf))->wFormatTag == WAVE_FORMAT_PCM) ? \
|
|
sizeof(PCMWAVEFORMAT) : \
|
|
sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)(pwf))->cbSize)
|
|
|
|
|
|
HRESULT CACMCmpStream::MakeInst(
|
|
IUnknown FAR* pUnknownOuter,
|
|
const IID FAR& riid,
|
|
void FAR* FAR* ppv)
|
|
{
|
|
IUnknown FAR* pUnknown;
|
|
CACMCmpStream FAR* pAVIStream;
|
|
HRESULT hresult;
|
|
|
|
pAVIStream = new FAR CACMCmpStream(pUnknownOuter, &pUnknown);
|
|
if (!pAVIStream)
|
|
return ResultFromScode(E_OUTOFMEMORY);
|
|
hresult = pUnknown->QueryInterface(riid, ppv);
|
|
if (FAILED(GetScode(hresult)))
|
|
delete pAVIStream;
|
|
return hresult;
|
|
}
|
|
|
|
/* - - - - - - - - */
|
|
|
|
CACMCmpStream::CACMCmpStream(
|
|
IUnknown FAR* pUnknownOuter,
|
|
IUnknown FAR* FAR* ppUnknown)
|
|
{
|
|
m_pavi = 0;
|
|
m_hs = 0;
|
|
m_lpFormat = 0;
|
|
m_lpFormatC = 0;
|
|
|
|
if (pUnknownOuter)
|
|
m_pUnknownOuter = pUnknownOuter;
|
|
else
|
|
m_pUnknownOuter = this;
|
|
*ppUnknown = this;
|
|
m_refs = 0;
|
|
}
|
|
|
|
/* - - - - - - - - */
|
|
|
|
STDMETHODIMP CACMCmpStream::QueryInterface(
|
|
const IID FAR& iid,
|
|
void FAR* FAR* ppv)
|
|
{
|
|
if (iid == IID_IUnknown)
|
|
*ppv = (IUnknown FAR *) this;
|
|
else if (iid == IID_IAVIStream)
|
|
*ppv = (IAVIStream FAR *) this;
|
|
else
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
AddRef();
|
|
return NULL;
|
|
}
|
|
|
|
/* - - - - - - - - */
|
|
|
|
STDMETHODIMP_(ULONG) CACMCmpStream::AddRef()
|
|
{
|
|
uUseCount++;
|
|
return ++m_refs;
|
|
}
|
|
|
|
/* - - - - - - - - */
|
|
|
|
LONG CACMCmpStream::SetUpCompression()
|
|
{
|
|
LONG lRet = AVIERR_OK;
|
|
|
|
// Get the initial format
|
|
AVIStreamFormatSize(m_pavi, AVIStreamStart(m_pavi), &m_cbFormat);
|
|
m_lpFormat = (LPWAVEFORMATEX) GlobalAllocPtr(GHND | GMEM_SHARE, m_cbFormat);
|
|
if (!m_lpFormat) {
|
|
lRet = AVIERR_MEMORY;
|
|
goto exit;
|
|
}
|
|
AVIStreamReadFormat(m_pavi, AVIStreamStart(m_pavi), m_lpFormat, &m_cbFormat);
|
|
|
|
if (m_lpFormatC != NULL) {
|
|
// we already have the format, let's hope it works...
|
|
|
|
// We could check if the format matches the original format....
|
|
if (m_cbFormat == m_cbFormatC &&
|
|
(_fmemcmp(m_lpFormat, m_lpFormatC, (int) m_cbFormat) == 0))
|
|
goto sameformat;
|
|
|
|
} else if (m_lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
|
|
acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&m_cbFormatC);
|
|
m_lpFormatC = (LPWAVEFORMATEX) GlobalAllocPtr(GHND | GMEM_SHARE, m_cbFormatC);
|
|
if (!m_lpFormatC) {
|
|
lRet = AVIERR_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
m_lpFormatC->wFormatTag = WAVE_FORMAT_PCM;
|
|
|
|
if (acmFormatSuggest(NULL, m_lpFormat, m_lpFormatC, m_cbFormatC, 0L) != 0)
|
|
goto sameformat;
|
|
} else {
|
|
sameformat:
|
|
DPF("Leaving the format unchanged....\n");
|
|
m_lpFormatC = m_lpFormat;
|
|
m_cbFormatC = m_cbFormat;
|
|
m_lpFormat = NULL;
|
|
m_cbFormat = 0;
|
|
|
|
m_hs = (HACMSTREAM) -1;
|
|
|
|
goto exit;
|
|
}
|
|
|
|
ACMFORMATDETAILS afdU;
|
|
ACMFORMATTAGDETAILS aftdU;
|
|
ACMFORMATDETAILS afdC;
|
|
ACMFORMATTAGDETAILS aftdC;
|
|
|
|
afdU.cbStruct = sizeof(afdU);
|
|
afdU.pwfx = m_lpFormat;
|
|
afdU.cbwfx = m_cbFormat;
|
|
afdU.fdwSupport = 0;
|
|
afdU.dwFormatTag = m_lpFormat->wFormatTag;
|
|
|
|
acmFormatDetails(NULL, &afdU, ACM_FORMATDETAILSF_FORMAT);
|
|
|
|
aftdU.cbStruct = sizeof(aftdU);
|
|
aftdU.dwFormatTag = m_lpFormat->wFormatTag;
|
|
aftdU.fdwSupport = 0;
|
|
|
|
acmFormatTagDetails(NULL,
|
|
&aftdU, ACM_FORMATTAGDETAILSF_FORMATTAG);
|
|
|
|
afdC.cbStruct = sizeof(afdC);
|
|
afdC.pwfx = m_lpFormatC;
|
|
afdC.cbwfx = m_cbFormatC;
|
|
afdC.dwFormatTag = m_lpFormatC->wFormatTag;
|
|
afdC.fdwSupport = 0;
|
|
|
|
acmFormatDetails(NULL, &afdC, ACM_FORMATDETAILSF_FORMAT);
|
|
|
|
aftdC.cbStruct = sizeof(aftdC);
|
|
aftdC.dwFormatTag = m_lpFormatC->wFormatTag;
|
|
aftdC.fdwSupport = 0;
|
|
|
|
acmFormatTagDetails(NULL,
|
|
&aftdC,
|
|
ACM_FORMATTAGDETAILSF_FORMATTAG);
|
|
|
|
DPF("Converting %s %s to %s %s\n", (LPSTR) &aftdU.szFormatTag, (LPSTR) &afdU.szFormat, (LPSTR) &aftdC.szFormatTag, (LPSTR) &afdC.szFormat);
|
|
|
|
// Open the compressor they asked for...
|
|
lRet = acmStreamOpen(&m_hs, // returned stream handle
|
|
NULL, // use any converter you want
|
|
m_lpFormat, // starting format
|
|
m_lpFormatC, // ending format
|
|
0L, // no filter
|
|
0L, // no callback
|
|
0L, // instance data for callback
|
|
ACM_STREAMOPENF_NONREALTIME);//emph. quality not speed
|
|
|
|
|
|
// !!! translate error code
|
|
|
|
if (!m_hs) {
|
|
TCHAR ach[ACMFORMATDETAILS_FORMAT_CHARS * 5];
|
|
TCHAR achTemp[128];
|
|
static int iEntered = 0;
|
|
|
|
LoadString(ghInst, IDS_CNVTERR, (LPTSTR)achTemp, sizeof(achTemp)/sizeof(TCHAR));
|
|
wsprintf(ach, achTemp,
|
|
(LPTSTR) &aftdU.szFormatTag,
|
|
(LPTSTR) &afdU.szFormat,
|
|
(LPTSTR) &aftdC.szFormatTag,
|
|
(LPTSTR) &afdC.szFormat);
|
|
|
|
LoadString(ghInst, IDS_ACMERR, (LPTSTR)achTemp, sizeof(achTemp)/sizeof(TCHAR));
|
|
|
|
if (iEntered++ == 0)
|
|
MessageBox(NULL, ach, achTemp, MB_OK);
|
|
iEntered--;
|
|
|
|
lRet = AVIERR_ERROR;
|
|
goto exit;
|
|
}
|
|
|
|
// Fix avistream header
|
|
m_avistream.dwSampleSize = m_lpFormatC->nBlockAlign;
|
|
m_avistream.dwScale = m_lpFormatC->nBlockAlign;
|
|
m_avistream.dwRate = m_lpFormatC->nAvgBytesPerSec;
|
|
|
|
acmStreamSize(m_hs,
|
|
AVIStreamLength(m_pavi) * m_lpFormat->nBlockAlign,
|
|
(LPDWORD) &m_avistream.dwLength,
|
|
ACM_STREAMSIZEF_SOURCE);
|
|
|
|
// !!! acmStreamSize rounds up here, do we need to compensate?
|
|
// !!! should we round off/up here?
|
|
m_avistream.dwLength /= m_lpFormatC->nBlockAlign;
|
|
|
|
m_avistream.dwQuality = 0; // !!!
|
|
|
|
exit:
|
|
if (lRet != AVIERR_OK) {
|
|
// !!! Don't release here!
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
/* - - - - - - - - */
|
|
|
|
//
|
|
// ACM stream:
|
|
//
|
|
// lParam1 should be a PAVISTREAM (an audio one!)
|
|
//
|
|
// lParam2 should be an LPWAVEFORMAT for the format you want converted
|
|
// to.
|
|
//
|
|
STDMETHODIMP CACMCmpStream::Create(LONG lParam1, LONG lParam2)
|
|
{
|
|
PAVISTREAM pavi = (PAVISTREAM) lParam1;
|
|
LPAVICOMPRESSOPTIONS lpOpts = (LPAVICOMPRESSOPTIONS) lParam2;
|
|
LPWAVEFORMAT lpwfNew = NULL;
|
|
LONG lRet = AVIERR_OK;
|
|
|
|
DPF("Creating ACM compression stream....\n");
|
|
// Get the stream header for future reference....
|
|
AVIStreamInfo(pavi, &m_avistream, sizeof(m_avistream));
|
|
m_avistream.fccHandler = 0;
|
|
if (m_avistream.fccType != streamtypeAUDIO) {
|
|
DPF("Stream isn't audio!\n");
|
|
lRet = AVIERR_INTERNAL;
|
|
goto exit;
|
|
}
|
|
|
|
if (acmGetVersion() < 0x02000000L) {
|
|
DPF("Bad ACM version!\n");
|
|
lRet = AVIERR_INTERNAL;
|
|
goto exit;
|
|
}
|
|
|
|
if (lpOpts && lpOpts->lpFormat) {
|
|
lpwfNew = (LPWAVEFORMAT) lpOpts->lpFormat;
|
|
|
|
if (lpOpts->cbFormat < WAVEFORMATSIZE(lpwfNew)) {
|
|
DPF("Bad format size!\n");
|
|
lRet = AVIERR_INTERNAL;
|
|
goto exit;
|
|
}
|
|
|
|
m_cbFormatC = WAVEFORMATSIZE(lpwfNew);
|
|
m_lpFormatC = (LPWAVEFORMATEX) GlobalAllocPtr(GMEM_MOVEABLE, m_cbFormatC);
|
|
if (m_lpFormatC == NULL) {
|
|
DPF("Out of memory for format!\n");
|
|
lRet = AVIERR_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
hmemcpy(m_lpFormatC, lpOpts->lpFormat, m_cbFormatC);
|
|
} else {
|
|
m_cbFormatC = 0;
|
|
m_lpFormatC = NULL;
|
|
}
|
|
|
|
// Make sure the uncompressed stream doesn't go away without our
|
|
// knowledge....
|
|
AVIStreamAddRef(pavi);
|
|
|
|
// Don't put this in the structure until we've done the AddRef....
|
|
m_pavi = pavi;
|
|
|
|
exit:
|
|
return ResultFromScode(lRet);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CACMCmpStream::Release()
|
|
{
|
|
if (--m_refs)
|
|
return m_refs;
|
|
|
|
if (m_lpFormat) {
|
|
GlobalFreePtr(m_lpFormat);
|
|
|
|
if (m_hs) {
|
|
acmStreamClose(m_hs, 0);
|
|
}
|
|
}
|
|
|
|
if (m_pavi) {
|
|
// Release our hold on the uncompressed stream....
|
|
AVIStreamClose(m_pavi);
|
|
}
|
|
|
|
if (m_lpFormatC)
|
|
GlobalFreePtr(m_lpFormatC);
|
|
|
|
delete this;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CACMCmpStream::Info(AVISTREAMINFO FAR * psi, LONG lSize)
|
|
{
|
|
if (m_hs == 0) {
|
|
LONG lRet;
|
|
|
|
// !!! If they ask for info before writing or setting the
|
|
// format, this will become a "read" stream!
|
|
lRet = SetUpCompression();
|
|
|
|
if (lRet != 0)
|
|
return ResultFromScode(lRet);
|
|
}
|
|
|
|
hmemcpy(psi, &m_avistream, min(lSize, sizeof(m_avistream)));
|
|
|
|
// return sizeof(m_avistream);
|
|
return 0;
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::ReadFormat(LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat)
|
|
{
|
|
LONG lRet;
|
|
|
|
if (m_hs == 0) {
|
|
lRet = SetUpCompression();
|
|
|
|
if (lRet != 0)
|
|
return ResultFromScode(lRet);
|
|
}
|
|
|
|
if (lpFormat)
|
|
hmemcpy(lpFormat,
|
|
m_lpFormatC,
|
|
min(*lpcbFormat, (LONG) m_cbFormatC));
|
|
|
|
*lpcbFormat = (LONG) m_cbFormatC;
|
|
return 0;
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Read(
|
|
LONG lStart,
|
|
LONG lSamples,
|
|
LPVOID lpBuffer,
|
|
LONG cbBuffer,
|
|
LONG FAR * plBytes,
|
|
LONG FAR * plSamples)
|
|
{
|
|
LONG lRet;
|
|
LONG cbTemp;
|
|
LPVOID lpTemp;
|
|
LONG lByteStart, lByteLen;
|
|
LONG lSampStart, lSampLen;
|
|
MMRESULT err;
|
|
|
|
ACMSTREAMHEADER acm;
|
|
HRESULT hr;
|
|
DWORD dwACMFlags;
|
|
|
|
if (m_hs == 0) {
|
|
lRet = SetUpCompression();
|
|
|
|
if (lRet != 0)
|
|
return ResultFromScode(lRet);
|
|
}
|
|
|
|
if (m_lpFormat == NULL) {
|
|
// Just return original format....
|
|
return AVIStreamRead(m_pavi, lStart, lSamples,
|
|
lpBuffer, cbBuffer, plBytes, plSamples);
|
|
}
|
|
|
|
if (lStart < 0 || lStart > (LONG) (m_avistream.dwStart + m_avistream.dwLength))
|
|
return ResultFromScode(AVIERR_BADPARAM);
|
|
|
|
if (lSamples == AVISTREAMREAD_CONVENIENT) {
|
|
// If they didn't specify a number of samples, fill their buffer....
|
|
lSamples = (cbBuffer ? cbBuffer : 32768L) / m_lpFormatC->nBlockAlign;
|
|
}
|
|
|
|
// Don't let anybody try to read past the end....
|
|
if (lSamples + lStart >
|
|
(LONG) (m_avistream.dwStart + m_avistream.dwLength))
|
|
lSamples = (LONG) (m_avistream.dwStart + m_avistream.dwLength) -
|
|
lStart;
|
|
|
|
if (lSamples <= 0)
|
|
return ResultFromScode(AVIERR_BADPARAM);
|
|
|
|
if (lpBuffer) {
|
|
LONG lDstBytes;
|
|
|
|
|
|
if (cbBuffer < lSamples * m_lpFormatC->nBlockAlign) {
|
|
DPF("Returning buffer too small\n");
|
|
if (plBytes)
|
|
*plBytes = lSamples * m_lpFormatC->nBlockAlign;
|
|
|
|
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
|
|
}
|
|
|
|
lDstBytes = lStart * m_lpFormatC->nBlockAlign;
|
|
|
|
if (lDstBytes)
|
|
acmStreamSize(m_hs, lDstBytes, (LPDWORD) &lByteStart,
|
|
ACM_STREAMSIZEF_DESTINATION);
|
|
else
|
|
lByteStart = 0;
|
|
|
|
lDstBytes = (lStart + lSamples) * m_lpFormatC->nBlockAlign;
|
|
|
|
acmStreamSize(m_hs, lDstBytes, (LPDWORD) &lByteLen,
|
|
ACM_STREAMSIZEF_DESTINATION);
|
|
lByteLen -= lByteStart;
|
|
|
|
lSampStart = lByteStart / m_lpFormat->nBlockAlign;
|
|
lSampLen = (lByteLen + m_lpFormat->nBlockAlign - 1) /
|
|
m_lpFormat->nBlockAlign;
|
|
lRet = 0;
|
|
|
|
cbTemp = lSampLen * m_lpFormat->nBlockAlign;
|
|
lpTemp = GlobalAllocPtr(GMEM_MOVEABLE, cbTemp);
|
|
|
|
if (!lpTemp)
|
|
return ResultFromScode(AVIERR_MEMORY);
|
|
|
|
hr = AVIStreamRead(m_pavi,
|
|
lSampStart, lSampLen,
|
|
lpTemp, cbTemp, NULL, &lRet);
|
|
|
|
if (lRet != lSampLen) {
|
|
DPF("AVIStreamRead: Asked for %lx samples at %lx, got %lx!\n", lSampLen, lSampStart, lRet);
|
|
|
|
if (lRet < lSampLen) {
|
|
// Fill buffer with silence, and hope....
|
|
BYTE _huge *hp;
|
|
LONG cb;
|
|
BYTE b;
|
|
|
|
cb = (lSampLen - lRet) * m_lpFormat->nBlockAlign;
|
|
hp = (BYTE _huge *) lpTemp + lRet * m_lpFormat->nBlockAlign;
|
|
|
|
if ((m_lpFormat->wFormatTag == WAVE_FORMAT_PCM) &&
|
|
(m_lpFormat->wBitsPerSample == 8))
|
|
b = 0x80;
|
|
else
|
|
b = 0;
|
|
|
|
while (cb-- > 0)
|
|
*hp++ = b;
|
|
}
|
|
|
|
// !!!
|
|
// lSampLen = lRet; // !!!
|
|
// lByteLen = lSampLen * m_lpFormat->nBlockAlign;
|
|
}
|
|
|
|
if (FAILED(GetScode(hr))) {
|
|
DPF("AVIStreamReadFailed! (start=%lx, len=%lx, err=%08lx)\n", lSampStart, lSampLen, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// !!! This is actually broken, if we want data that doesn't start
|
|
// on a block align boundary.
|
|
|
|
// To fix it, we need a second temporary buffer:
|
|
// Consider the case where the user wants to read one byte of PCM
|
|
// data from an ADPCM stream. We read a single block of ADPCM into
|
|
// lpBuffer, but we need 256 bytes (or whatever) to decompress
|
|
// it into, and the user's only given us a 1-byte buffer....
|
|
|
|
acm.cbStruct = sizeof(acm);
|
|
acm.fdwStatus = 0;
|
|
acm.dwUser = 0;
|
|
acm.pbSrc = (LPBYTE) lpTemp
|
|
// + (lByteStart - lSampStart * m_lpFormat->nBlockAlign)
|
|
;
|
|
acm.cbSrcLength = lByteLen;
|
|
acm.cbSrcLengthUsed = 0;
|
|
acm.pbDst = (LPBYTE) lpBuffer;
|
|
acm.cbDstLength = cbBuffer;
|
|
acm.cbDstLengthUsed = 0;
|
|
|
|
dwACMFlags = 0; // !!! ACM_STREAMCONVERTF_BLOCKALIGN;
|
|
|
|
// !!! add in start, end flags for ACM....
|
|
err = acmStreamPrepareHeader(m_hs, &acm, 0);
|
|
|
|
if (err != 0) {
|
|
DPF("acmStreamPrepareHeader returns %u\n", err);
|
|
|
|
return ResultFromScode(AVIERR_COMPRESSOR);
|
|
}
|
|
|
|
err = acmStreamConvert(m_hs, &acm, dwACMFlags);
|
|
|
|
GlobalFreePtr(lpTemp); // This should be a permanent buffer!
|
|
|
|
acmStreamUnprepareHeader(m_hs, &acm, 0);
|
|
|
|
if (err != 0) {
|
|
DPF("acmStreamConvert returns %u\n", err);
|
|
|
|
return ResultFromScode(AVIERR_COMPRESSOR);
|
|
}
|
|
|
|
DPF("Converted %lu of %lu bytes to %lu bytes (buffer size = %lu)\n", acm.cbSrcLengthUsed, acm.cbSrcLength, acm.cbDstLengthUsed, acm.cbDstLength);
|
|
|
|
// Lie: say that the ACM returned a full block....
|
|
acm.cbDstLengthUsed += m_lpFormatC->nBlockAlign - 1;
|
|
acm.cbDstLengthUsed -= acm.cbDstLengthUsed % m_lpFormatC->nBlockAlign;
|
|
|
|
if (plBytes)
|
|
*plBytes = (LONG) acm.cbDstLengthUsed;
|
|
|
|
if (plSamples)
|
|
*plSamples = (LONG) (acm.cbDstLengthUsed / m_lpFormatC->nBlockAlign);
|
|
} else {
|
|
// We always assume we could read whatever they asked for....
|
|
if (plBytes)
|
|
*plBytes = lSamples * m_lpFormatC->nBlockAlign;
|
|
|
|
if (plSamples)
|
|
*plSamples = lSamples;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
STDMETHODIMP_(LONG) CACMCmpStream::FindSample(LONG lPos, LONG lFlags)
|
|
{
|
|
if (lFlags & FIND_FORMAT) {
|
|
if (lFlags & FIND_PREV)
|
|
return 0;
|
|
else {
|
|
if (lPos > 0)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return lPos;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CACMCmpStream::SetFormat(LONG lPos,LPVOID lpFormat,LONG cbFormat)
|
|
{
|
|
// !!! It should really be possible to use SetFormat & Write on this
|
|
// stream.....
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Write(LONG lStart,
|
|
LONG lSamples,
|
|
LPVOID lpBuffer,
|
|
LONG cbBuffer,
|
|
DWORD dwFlags,
|
|
LONG FAR *plSampWritten,
|
|
LONG FAR *plBytesWritten)
|
|
{
|
|
// !!!
|
|
// Maybe this is the place to decompress data and write it to the original
|
|
// stream?
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Delete(LONG lStart,LONG lSamples)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::ReadData(DWORD fcc, LPVOID lp, LONG FAR *lpcb)
|
|
{
|
|
return AVIStreamReadData(m_pavi, fcc, lp, lpcb);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::WriteData(DWORD fcc, LPVOID lp, LONG cb)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
#if 0
|
|
STDMETHODIMP CACMCmpStream::Clone(PAVISTREAM FAR * ppaviNew)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
#endif
|
|
|
|
|
|
STDMETHODIMP CACMCmpStream::Reserved1(void)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Reserved2(void)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Reserved3(void)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Reserved4(void)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP CACMCmpStream::Reserved5(void)
|
|
{
|
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* dprintf() is called by the DPF macro if DEBUG is defined at compile time.
|
|
*
|
|
* The messages will be send to COM1: like any debug message. To
|
|
* enable debug output, add the following to WIN.INI :
|
|
*
|
|
* [debug]
|
|
* ICSAMPLE=1
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define MODNAME "ACMCMPRS"
|
|
static BOOL fDebug = -1;
|
|
|
|
static void cdecl dprintf(LPSTR szFormat, ...)
|
|
{
|
|
char ach[128];
|
|
|
|
#ifdef WIN32
|
|
va_list va;
|
|
if (fDebug == -1)
|
|
fDebug = GetProfileIntA("Debug",MODNAME, FALSE);
|
|
|
|
if (!fDebug)
|
|
return;
|
|
|
|
va_start(va, szFormat);
|
|
if (szFormat[0] == '!')
|
|
ach[0]=0, szFormat++;
|
|
else
|
|
lstrcpyA(ach, MODNAME ": ");
|
|
|
|
wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
|
|
va_end(va);
|
|
// lstrcatA(ach, "\r\r\n");
|
|
|
|
OutputDebugStringA(ach);
|
|
#else
|
|
if (fDebug == -1)
|
|
fDebug = GetProfileInt("Debug",MODNAME, FALSE);
|
|
|
|
if (!fDebug)
|
|
return;
|
|
|
|
if (szFormat[0] == '!')
|
|
ach[0]=0, szFormat++;
|
|
else
|
|
lstrcpy(ach, MODNAME ": ");
|
|
|
|
wvsprintf(ach+lstrlen(ach),szFormat,(LPSTR)(&szFormat+1));
|
|
// lstrcat(ach, "\r\r\n");
|
|
|
|
OutputDebugString(ach);
|
|
#endif
|
|
}
|
|
|
|
#endif
|