ссылку не помню, да простят меня авторы текста
Код:
static int nWaveOutHeadersCount = 0;
void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
if (uMsg != WOM_DONE)
return;
LPWAVEHDR pwh = (LPWAVEHDR)dwParam1;
char* pData = pwh->lpData;
waveOutUnprepareHeader(hwo, pwh, sizeof(WAVEHDR));
nWaveOutHeadersCount--;
free(pwh);
free(pData);
}
void PlayAviAudio(LPCSTR pszFile)
{
AVIFileInit();
PAVIFILE paf;
AVIFileOpen(&paf, pszFile, OF_READ, 0);
AVIFILEINFO afi;
AVIFileInfo(paf, &afi, sizeof(AVIFILEINFO));
PAVISTREAM pasAudio;
AVIFileGetStream(paf, &pasAudio, streamtypeAUDIO, 0);
AVISTREAMINFO asiAudio;
AVIStreamInfo(pasAudio, &asiAudio, sizeof(AVISTREAMINFO));
long nFormatSize;
AVIStreamReadFormat(pasAudio, asiAudio.dwStart, NULL, &nFormatSize);
WAVEFORMATEX* pwfxIn = (WAVEFORMATEX*)malloc(nFormatSize);
AVIStreamReadFormat(pasAudio, asiAudio.dwStart, pwfxIn, &nFormatSize);
WAVEFORMATEX wfxDec;
memcpy(&wfxDec, pwfxIn, min(nFormatSize, sizeof(WAVEFORMATEX)));
wfxDec.wFormatTag = WAVE_FORMAT_PCM;
wfxDec.wBitsPerSample = 16;
wfxDec.nBlockAlign = wfxDec.nChannels * wfxDec.wBitsPerSample / 8;
wfxDec.nAvgBytesPerSec = wfxDec.nSamplesPerSec * wfxDec.nBlockAlign;
HACMSTREAM has;
acmStreamOpen(&has, NULL, pwfxIn, &wfxDec, NULL, NULL, 0, ACM_STREAMOPENF_NONREALTIME);
HWAVEOUT hwo;
waveOutOpen(&hwo, WAVE_MAPPER, &wfxDec, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);
BYTE *pInData = NULL, *pDecData;
long nInBufSize = 0, nSampleSize = 0, nBytesCount = 0, nSamplesCount = 1;
DWORD nDecBufSize;
for (int nSample = asiAudio.dwStart; nSample <= asiAudio.dwStart + asiAudio.dwLength; nSample += nSamplesCount)
{
if (asiAudio.dwSampleSize == 0)
{
AVIStreamSampleSize(pasAudio, nSample, &nSampleSize);
nBytesCount = nSampleSize;
if (nBytesCount > nInBufSize)
{
pInData = (BYTE*)realloc(pInData, nBytesCount);
nInBufSize = nBytesCount;
}
AVIStreamRead(pasAudio, nSample, 1, pInData, nInBufSize, NULL, NULL);
}
else
{
nSamplesCount = 1152;
nBytesCount = nSamplesCount * asiAudio.dwSampleSize;
if (nBytesCount > nInBufSize)
{
pInData = (BYTE*)realloc(pInData, nBytesCount);
nInBufSize = nBytesCount;
}
AVIStreamRead(pasAudio, nSample, nSamplesCount, pInData, nInBufSize, &nBytesCount, &nSamplesCount);
}
acmStreamSize(has, nBytesCount, &nDecBufSize, ACM_STREAMSIZEF_SOURCE);
pDecData = (BYTE*)malloc(nDecBufSize);
ACMSTREAMHEADER ash;
memset(&ash, 0, sizeof(ACMSTREAMHEADER));
ash.cbStruct = sizeof(ACMSTREAMHEADER);
ash.pbSrc = pInData;
ash.cbSrcLength = nBytesCount;
ash.pbDst = pDecData;
ash.cbDstLength = nDecBufSize;
acmStreamPrepareHeader(has, &ash, 0);
acmStreamConvert(has, &ash, 0);
WAVEHDR* pwh = (WAVEHDR*)malloc(sizeof(WAVEHDR));
memset(pwh, 0, sizeof(WAVEHDR));
pwh->lpData = (LPSTR)ash.pbDst;
pwh->dwBufferLength = ash.cbDstLengthUsed;
waveOutPrepareHeader(hwo, pwh, sizeof(WAVEHDR));
waveOutWrite(hwo, pwh, sizeof(WAVEHDR));
nWaveOutHeadersCount++;
acmStreamUnprepareHeader(has, &ash, 0);
while (nWaveOutHeadersCount > 1)
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
}
}
waveOutReset(hwo);
waveOutClose(hwo);
acmStreamClose(has, 0);
AVIStreamRelease(pasAudio);
AVIFileRelease(paf);
AVIFileExit();
}
#include <vfw.h>
#ifndef DIBSIZE
#define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
#define DIBWIDTHBYTES(bi) (DWORD)WIDTHBYTES((DWORD)(bi).biWidth * (DWORD)(bi).biBitCount)
#define _DIBSIZE(bi) (DIBWIDTHBYTES(bi) * (DWORD)(bi).biHeight)
#define DIBSIZE(bi) ((bi).biHeight < 0 ? (-1)*(_DIBSIZE(bi)) : _DIBSIZE(bi))
#endif
void PlayAvi(LPCSTR pszFile, HWND hWndOutput)
{
AVIFileInit();
PAVIFILE paf;
AVIFileOpen(&paf, pszFile, OF_READ, 0);
AVIFILEINFO afi;
AVIFileInfo(paf, &afi, sizeof(AVIFILEINFO));
PAVISTREAM pas;
AVIFileGetStream(paf, &pas, streamtypeVIDEO, 0);
AVISTREAMINFO asi;
AVIStreamInfo(pas, &asi, sizeof(AVISTREAMINFO));
long nFormatSize;
AVIStreamReadFormat(pas, asi.dwStart, NULL, &nFormatSize);
BITMAPINFOHEADER* pbihIn = (BITMAPINFOHEADER*)malloc(nFormatSize);
AVIStreamReadFormat(pas, asi.dwStart, pbihIn, &nFormatSize);
BITMAPINFOHEADER bihDec;
memcpy(&bihDec, pbihIn, sizeof(BITMAPINFOHEADER));
bihDec.biCompression = BI_RGB;
bihDec.biBitCount = 24;
bihDec.biSizeImage = DIBSIZE(bihDec);
BYTE* pDecData = (BYTE*)malloc(bihDec.biSizeImage);
memset(pDecData, 0, bihDec.biSizeImage);
HIC hic = ICDecompressOpen(ICTYPE_VIDEO, pbihIn->biCompression, pbihIn, &bihDec);
ICDecompressBegin(hic, pbihIn, &bihDec);
HDC hdc = GetDC(hWndOutput);
RECT rc;
GetClientRect(hWndOutput, &rc);
HDRAWDIB hdd = DrawDibOpen();
BYTE* pInData = NULL;
long nBufSize = 0, nSampleSize = 0;
for (int nSample = asi.dwStart; nSample <= asi.dwStart + asi.dwLength; nSample++)
{
AVIStreamSampleSize(pas, nSample, &nSampleSize);
if (nSampleSize > nBufSize)
{
pInData = (BYTE*)realloc(pInData, nSampleSize);
nBufSize = nSampleSize;
}
AVIStreamRead(pas, nSample, 1, pInData, nBufSize, NULL, NULL);
ICDecompress(hic, 0, pbihIn, pInData, &bihDec, pDecData);
// сейчас в pDecData текущий кадр в виде битмапки, рисуем его
DrawDibDraw(hdd, hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, &bihDec, pDecData, 0, 0, bihDec.biWidth, bihDec.biHeight, 0);
}
DrawDibClose(hdd);
ReleaseDC(hWndOutput, hdc);
ICDecompressEnd(hic);
ICClose(hic);
AVIStreamRelease(pas);
AVIFileRelease(paf);
AVIFileExit();
free(pInData);
free(pDecData);
free(pbihIn);
}
|