2025-04-27 07:49:33 -04:00

216 lines
6.1 KiB
C++

#include <windows.h>
#include <mmreg.h>
#include "uuids.h"
#include "dmo.h"
#include "appstrm.h"
#include "initguid.h"
DEFINE_GUID(CLSID_Simple,0xCE13AE3C,0x097B,0x11D3,0xB3,0x0B,0x44,0x45,0x53,0x54,0x00,0x01);
HRESULT CreateAndInitializeObject(IMediaObject **ppObject) {
WAVEFORMATEX WaveFmt = {
WAVE_FORMAT_PCM,
1, // nChannels
22050, // nSamplesPerSec
44100, // nAvgBytesPerSec
2, // nBlockAlign
16, // wBitsPerSample
0 // size of additional stuff at the end of this structure
};
/* // Why did the compiler not like these GUID initializations ?
DMO_MEDIA_TYPE mt = {MEDIATYPE_Audio, // majortype
MEDIASUBTYPE_PCM, // subtype
FALSE, // bFixedSizeSamples - ignored by media objects
FALSE, // bTemporalCompression - ignored by media objects
0, // lSampleSize - ignored by media objects
FORMAT_WaveFormatEx, // format guid
NULL, // IUnknown pointer - not used
sizeof (WAVEFORMATEX),
&WaveFmt // our WAVEFORMATEX
};
*/
DMO_MEDIA_TYPE mt;
mt.majortype = MEDIATYPE_Audio;
mt.subtype = MEDIASUBTYPE_PCM;
mt.formattype = FORMAT_WaveFormatEx;
mt.cbFormat = sizeof(WAVEFORMATEX);
mt.pbFormat = (BYTE*)(&WaveFmt);
mt.pUnk = NULL; // CopyMediaType will crash if we don't intialize this
HRESULT hr = CoCreateInstance(CLSID_Simple,
NULL,
CLSCTX_INPROC,
IID_IMediaObject,
(void **) ppObject);
if (FAILED(hr))
return hr;
hr = (*ppObject)->SetInputType(0, &mt, 0);
if (FAILED(hr))
return hr;
hr = (*ppObject)->SetOutputType(0, &mt, 0);
if (FAILED(hr))
return hr;
return NOERROR;
}
//
// CMyStream - streams data from one hFile to another using a CLSID_Simple media object
//
class CMyStream : public CAppStream {
public:
CMyStream(HRESULT *phr) :
CAppStream(phr)
{
m_pObject = NULL;
m_pInBuffer = NULL;
m_pOutBuffer = NULL;
}
~CMyStream() {
if (m_pObject)
m_pObject->Release();
if (m_pInBuffer)
delete m_pInBuffer;
if (m_pOutBuffer)
delete m_pOutBuffer;
}
HRESULT Init(HANDLE hFileInput, HANDLE hFileOutput) {
HRESULT hr;
m_hInFile = hFileInput;
m_hOutFile = hFileOutput;
// some odd numbers to stress the code in CAppStream::Stream()
m_ulInBufferSize = 65317;
m_ulOutBufferSize = 29311;
hr = CreateAndInitializeObject(&m_pObject);
if (FAILED(hr))
return hr;
m_pInBuffer = new BYTE[m_ulInBufferSize];
m_pOutBuffer = new BYTE[m_ulOutBufferSize];
if (!(m_pInBuffer && m_pOutBuffer))
return E_OUTOFMEMORY;
return CAppStream::Init(m_pInBuffer, m_ulInBufferSize, m_pOutBuffer, m_ulOutBufferSize, m_pObject);
}
//
// CAppStream::Stream() calls this to get data from us
//
HRESULT GetInputData(BYTE *pBuffer, DWORD dwBytesWanted, DWORD *pdwBytesSupplied, DWORD *pdwStatus) {
*pdwStatus = 0;
if (ReadFile(m_hInFile, pBuffer, dwBytesWanted, pdwBytesSupplied, NULL)) {
// Non-zero return indicates success
if (!*pdwBytesSupplied)
*pdwStatus |= APPSTRM_STATUSF_END_OF_STREAM;
return NOERROR;
}
else {
*pdwBytesSupplied = 0;
*pdwStatus |= APPSTRM_STATUSF_END_OF_STREAM;
return E_FAIL;
}
}
//
// CAppStream::Stream() calls this to let us pick up output data.
// We must do something with it before returning from here, since
// the buffer will be reused as soon as we return.
//
HRESULT AcceptOutputData(BYTE *pBuffer, DWORD dwBytesProduced) {
if (dwBytesProduced == 0)
return NOERROR;
DWORD dwWritten;
if (WriteFile(m_hOutFile, pBuffer, dwBytesProduced, &dwWritten, NULL)) {
// Non-zero return indicates success
if (dwWritten == dwBytesProduced)
return NOERROR;
else
return E_FAIL;
}
else
return E_FAIL;
}
private:
IMediaObject *m_pObject;
HANDLE m_hInFile;
HANDLE m_hOutFile;
BYTE *m_pInBuffer;
BYTE *m_pOutBuffer;
ULONG m_ulInBufferSize;
ULONG m_ulOutBufferSize;
};
HRESULT StreamData(HANDLE hFileInput, HANDLE hFileOutput)
{
HRESULT hr;
CMyStream *pStream = new CMyStream(&hr);
if (!pStream)
return E_OUTOFMEMORY;
if (FAILED(hr)) {
delete pStream;
return hr;
}
hr = pStream->Init(hFileInput, hFileOutput);
if (FAILED(hr)) {
delete pStream;
return hr;
}
hr = pStream->Stream();
delete pStream;
return hr;
}
/* Use our object */
HRESULT StreamFile(LPSTR lpszFileInput, LPSTR lpszFileOutput)
{
HANDLE hFileInput = CreateFile(lpszFileInput,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hFileInput) {
return E_FAIL;
}
HANDLE hFileOutput = CreateFile(lpszFileOutput,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
0,
NULL);
if (INVALID_HANDLE_VALUE == hFileInput) {
CloseHandle(hFileInput);
return E_FAIL;
}
HRESULT hr = StreamData(hFileInput, hFileOutput);
CloseHandle(hFileInput);
CloseHandle(hFileOutput);
return hr;
}
int __cdecl main(int argc, char *argv[])
{
CoInitialize(NULL);
StreamFile(argv[1], argv[2]);
CoUninitialize();
return(1);
}