📄 avi.cpp
字号:
#include "StdAfx.h"
//////////////////////////////////////////////////////////////////////////////////
// CAvi Constructor
//////////////////////////////////////////////////////////////////////////////////
CAvi::CAvi(void)
{
m_AviFile = NULL;
m_lpDDS = NULL;
m_AviStream = NULL;
ZeroMemory(&m_StreamInfo, sizeof(m_StreamInfo));
m_Index = 0;
m_nFrames = 0;
m_Decompressor = 0;
m_Input = m_Output = 0;
m_AviSound = NULL;
ZeroMemory(&m_SoundInfo, sizeof(m_SoundInfo));
m_SoundFormat = 0;
m_LoadPos = 0;
m_LoadSize = 0;
m_SoundFramesAhead = 0;
m_nStopFrame = -1;
m_bIsPlaying = FALSE;
m_SoundBuffer = NULL;
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi Destructor
//////////////////////////////////////////////////////////////////////////////////
CAvi::~CAvi(void)
{
// CAvi::ReleaseAvi();
}
void CAvi::InitAvi(LPDIRECTSOUND lpDS)
{
m_lpDS = lpDS;
InitializeCriticalSection(&m_AccessBuffer);
}
void CAvi::ReleaseAvi( void )
{
CAvi::Stop( );
Sleep(1);
if(m_Decompressor)
{
ICDecompressEnd(m_Decompressor);
ICClose(m_Decompressor);
}
if( m_InputFormat ) FREE(m_InputFormat);
if( m_TargetFormat ) FREE(m_TargetFormat);
if( m_Input ) FREE(m_Input);
if( m_Output ) FREE(m_Output);
if( m_lpDDS )
AVIFileExit();
RELEASE( m_SoundBuffer );
RELEASE( m_lpDDS );
if( m_AviStream )
{
AVIStreamRelease(m_AviStream);
m_AviStream = NULL;
}
if( m_AviSound )
{
AVIStreamRelease(m_AviSound );
m_AviSound = NULL;
}
if( m_AviFile )
{
AVIFileRelease(m_AviFile);
m_AviFile = NULL;
}
if(m_SoundFormat)
{
FREE(m_SoundFormat);
m_SoundFormat = NULL;
}
DeleteCriticalSection(&m_AccessBuffer);
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi Create
//////////////////////////////////////////////////////////////////////////////////
BOOL CAvi::Create(const char* Filename, BOOL bLoop, BOOL bPlayBack)
{
if(Filename == NULL) return FALSE;
AVIFileInit();
m_bLoop = bLoop;
m_bPlayDirection = bPlayBack;
if( AVIFileOpen( &m_AviFile, Filename, OF_READ, 0 ) )
{
AVIFileExit( );
return FALSE;
}
if( AVIFileGetStream( m_AviFile, &m_AviStream, streamtypeVIDEO, 0 ) )
{
AVIFileExit( );
return FALSE;
}
LONG FmtLenght;
AVIStreamFormatSize(m_AviStream, 0, &FmtLenght);
m_InputFormat = (LPBITMAPINFOHEADER)malloc(FmtLenght);
m_TargetFormat = (LPBITMAPV4HEADER)malloc(max(FmtLenght, sizeof(BITMAPV4HEADER)));
ZeroMemory(m_TargetFormat, sizeof(BITMAPV4HEADER));
AVIStreamReadFormat(m_AviStream, 0, m_InputFormat, &FmtLenght);
m_nFrames = AVIStreamLength(m_AviStream);
AVIStreamInfo(m_AviStream, &m_StreamInfo, sizeof(AVISTREAMINFO));
HRESULT rval;
ZeroMemory(&m_DDSD, sizeof(m_DDSD));
m_DDSD.dwSize = sizeof(m_DDSD);
m_DDSD.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
m_DDSD.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
m_DDSD.dwWidth = m_InputFormat->biWidth;
m_DDSD.dwHeight = m_InputFormat->biHeight;
rval = g_xMainWnd.GetDirectDraw()->CreateSurface(&m_DDSD, &m_lpDDS, NULL);
if(rval != DD_OK)
{
AVIFileExit();
return FALSE;
}
m_lpDDS->GetSurfaceDesc(&m_DDSD);
memcpy(m_TargetFormat, m_InputFormat, FmtLenght);
m_TargetFormat->bV4Size = max(FmtLenght, sizeof(BITMAPV4HEADER));
m_TargetFormat->bV4BitCount = (WORD)m_DDSD.ddpfPixelFormat.dwRGBBitCount;
m_TargetFormat->bV4V4Compression = BI_BITFIELDS;
if(m_TargetFormat->bV4BitCount==24) m_TargetFormat->bV4V4Compression = BI_RGB;
m_TargetFormat->bV4ClrUsed = 0;
m_TargetFormat->bV4RedMask = m_DDSD.ddpfPixelFormat.dwRBitMask;
m_TargetFormat->bV4GreenMask = m_DDSD.ddpfPixelFormat.dwGBitMask;
m_TargetFormat->bV4BlueMask = m_DDSD.ddpfPixelFormat.dwBBitMask;
m_TargetFormat->bV4AlphaMask = m_DDSD.ddpfPixelFormat.dwRGBAlphaBitMask;
m_TargetFormat->bV4SizeImage = ((m_TargetFormat->bV4Width +3)&0xFFFFFFFC) *
m_TargetFormat->bV4Height * (m_TargetFormat->bV4BitCount>>3);
m_Length = m_InputFormat->biWidth * m_InputFormat->biHeight * (m_InputFormat->biBitCount >> 3);
if(m_StreamInfo.dwSuggestedBufferSize) m_Length = (LONG)m_StreamInfo.dwSuggestedBufferSize;
m_Decompressor = ICDecompressOpen(ICTYPE_VIDEO, m_StreamInfo.fccHandler, m_InputFormat,
(LPBITMAPINFOHEADER)m_TargetFormat);
m_Input = (BYTE *)calloc(m_Length, 1);
ZeroMemory(m_Input, m_Length);
m_Output = (BYTE *)calloc(m_TargetFormat->bV4SizeImage, 1);
ZeroMemory(m_Output, m_TargetFormat->bV4SizeImage);
if(!m_Decompressor) return FALSE;
m_LinePitch = m_TargetFormat->bV4Width * (m_TargetFormat->bV4BitCount >> 3);
ICDecompressBegin(m_Decompressor, m_InputFormat, (LPBITMAPINFOHEADER)m_TargetFormat);
m_Fps = m_StreamInfo.dwRate / m_StreamInfo.dwScale;
m_TimeTick = (1000 * m_StreamInfo.dwScale + (m_StreamInfo.dwRate >> 1)) / m_StreamInfo.dwRate;
m_SrcRect.top = 0;
m_SrcRect.left = 0;
m_SrcRect.bottom = m_TargetFormat->bV4Height;
m_SrcRect.right = m_TargetFormat->bV4Width;
m_DstRect.top = 0;
m_DstRect.left = 0;
m_DstRect.right = 800;
m_DstRect.bottom = 600;
if(m_lpDS)
{
UINT hResult = 0;
hResult = AVIFileGetStream( m_AviFile, &m_AviSound, streamtypeAUDIO, 0 );
if(hResult ==0 )
{
DSBUFFERDESC dsbd;
ZeroMemory((VOID*)&dsbd, sizeof(DSBUFFERDESC));
AVIStreamFormatSize(m_AviSound, 0, &FmtLenght);
m_SoundFormat = (WAVEFORMATEX *)malloc(FmtLenght);
AVIStreamReadFormat(m_AviSound, 0, m_SoundFormat, &FmtLenght);
AVIStreamInfo(m_AviSound, &m_SoundInfo, sizeof(AVISTREAMINFO));
m_LoadSize = (m_SoundInfo.dwSuggestedBufferSize)/(m_Fps);//(m_SoundFormat->nAvgBytesPerSec) / (m_Fps+1);
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
dsbd.dwBufferBytes = m_SoundInfo.dwSuggestedBufferSize;//m_LoadSize * (m_Fps)-2;
dsbd.dwReserved = 0;
dsbd.lpwfxFormat = m_SoundFormat;
hResult = m_lpDS->CreateSoundBuffer(&dsbd, &m_SoundBuffer, NULL);
if( hResult != DS_OK )
{
AVIFileExit();
return FALSE;
}
}
}
m_Index = (m_bPlayDirection ? 0 : m_nFrames);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi Start
//////////////////////////////////////////////////////////////////////////////////
void CAvi::Start(void)
{
if( !GetSound() ) return;
m_bPlaying = TRUE;
CAvi::ReadFrame(m_Index);
m_bIsPlaying = TRUE;
if( m_SoundBuffer )
{
m_SoundFramesAhead = m_SoundInfo.dwInitialFrames / m_SoundInfo.dwScale;
m_SoundBuffer->SetVolume(-200);
if(m_SoundBuffer->Play(0, 0, DSBPLAY_LOOPING) != DS_OK) return;
}
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi Stop
//////////////////////////////////////////////////////////////////////////////////
void CAvi::Stop(void)
{
m_bPlaying = FALSE;
if( m_SoundBuffer)
m_SoundBuffer->Stop();
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi NextFrame
//////////////////////////////////////////////////////////////////////////////////
void CAvi::NextFrame(void)
{
m_Index = m_Index + (m_bPlayDirection? 1 : -1);
if(m_Index == (m_bPlayDirection ? m_nFrames : 0) )
{
CAvi::Stop( );
if(m_bLoop)
{
m_Index = (m_bPlayDirection ? 0 : m_nFrames);
m_LoadPos = (m_bPlayDirection ? 0 : m_nFrames);
m_bPlaying = TRUE;
if( m_SoundBuffer )
{
m_SoundBuffer->SetCurrentPosition(0);
GetSound();
m_SoundBuffer->Play(0, 0, DSBPLAY_LOOPING);
}
}
else
{
m_bIsPlaying = FALSE;
}
}
if( (m_nStopFrame > 0 ) && ( m_Index == m_nStopFrame ))
{
m_bIsPlaying = FALSE;
m_nStopFrame = -1;
}
else
{
GetSound();
ReadFrame(m_Index);
}
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi ReadFrame
//////////////////////////////////////////////////////////////////////////////////
void CAvi::ReadFrame(LONG Frame)
{
Frame -= m_SoundFramesAhead;
if(Frame < 0) return;
if(Frame < m_nFrames)
{
AVIStreamRead(m_AviStream, Frame, 1, m_Input, m_Length, NULL, NULL);
EnterCriticalSection(&m_AccessBuffer);
ICDecompress(m_Decompressor, ICDECOMPRESS_HURRYUP, m_InputFormat, m_Input, (LPBITMAPINFOHEADER)m_TargetFormat, m_Output);
LeaveCriticalSection(&m_AccessBuffer);
}
}
//////////////////////////////////////////////////////////////////////////////////
// CDXAvi GetSound
//////////////////////////////////////////////////////////////////////////////////
BOOL CAvi::GetSound(VOID)
{
HRESULT rval;
DWORD dwSize,dwSize2;
LPVOID Data,Data2;
dwSize = 0;
dwSize2 = 0;
rval = 0;
Data = NULL;
Data2 = NULL;
if( m_SoundBuffer )
{
rval = m_SoundBuffer->Lock(m_LoadPos * m_LoadSize, m_LoadSize, &Data, &dwSize, 0, 0, 0);// &Data2, &dwSize2, 0);
if(rval != DS_OK) return FALSE;
AVIStreamRead(m_AviSound, m_Index * (m_LoadSize >> 2), m_LoadSize, Data, m_LoadSize, NULL, NULL);
rval = m_SoundBuffer->Unlock(Data, dwSize, 0, 0);// Data2, dwSize2);
m_LoadPos++;
m_LoadPos %= m_Fps;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi DrawBuffer
//////////////////////////////////////////////////////////////////////////////////
HRESULT CAvi::DrawBuffer(void)
{
HRESULT rval;
ZeroMemory(&m_DDSD, sizeof(m_DDSD));
m_DDSD.dwSize = sizeof(m_DDSD);
rval = m_lpDDS->Lock(NULL, &m_DDSD, DDLOCK_WAIT, NULL);
while(rval == DDERR_SURFACELOST)
{
// Restore();
ZeroMemory(&m_DDSD, sizeof(m_DDSD));
m_DDSD.dwSize = sizeof(m_DDSD);
rval = m_lpDDS->Lock(NULL, &m_DDSD, DDLOCK_WAIT, NULL);
}
if(rval == DD_OK)
{
BYTE *lpSource = m_Output + m_LinePitch * (m_TargetFormat->bV4Height - 1);
BYTE *lpDest = (LPBYTE)m_DDSD.lpSurface;
int xs = m_LinePitch>>2,
xm = m_LinePitch*2,
y = m_TargetFormat->bV4Height,
z = m_DDSD.lPitch-m_LinePitch;
EnterCriticalSection(&m_AccessBuffer);
// I was to lazy to do the optimaization for all sizes
// and all my AVI's are DWORD align i had no problem
// i just putted back the old part for the odd AVIS ;)
if( m_TargetFormat->bV4Width%4 )
{ for(int i = 0; i < (int)m_TargetFormat->bV4Height; i++)
{ memcpy(lpDest, lpSource, m_LinePitch);
lpDest += m_DDSD.lPitch;
lpSource -= m_LinePitch;
}
}
else
{
__asm
{ mov ebx, [y]
mov esi, lpSource
mov edi, lpDest
cld
lp: mov ecx, [xs]
rep movsd
sub esi, [xm]
add edi, [z]
dec ebx
jnz lp
}
}
LeaveCriticalSection(&m_AccessBuffer);
rval = m_lpDDS->Unlock(NULL);
while(rval == DDERR_SURFACELOST)
{
// Restore();
rval = m_lpDDS->Unlock(NULL);
}
}
return rval;
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi DrawBuffer
//////////////////////////////////////////////////////////////////////////////////
BOOL CAvi::Draw(INT nLoopTime)
{
BOOL rval = 0;
ReadDatas(nLoopTime);
rval = CAvi::DrawBuffer();
if(rval != DD_OK) return rval;
g_xMainWnd.GetBackBuffer()->Blt(&m_DstRect, m_lpDDS, &m_SrcRect, DDBLT_WAIT, NULL);
return m_bIsPlaying;
}
//////////////////////////////////////////////////////////////////////////////////
// CAvi DrawBuffer
//////////////////////////////////////////////////////////////////////////////////
HRESULT CAvi::DrawFast(INT nLoopTime,int X, int Y)
{
HRESULT rval;
ReadDatas(nLoopTime);
rval = CAvi::DrawBuffer();
if(rval != DD_OK) return rval;
rval = g_xMainWnd.GetBackBuffer()->BltFast(X, Y, m_lpDDS, &m_SrcRect, DDBLTFAST_WAIT|DDBLTFAST_NOCOLORKEY);
// if(rval == DDERR_SURFACELOST) Restore();
return rval;
}
BOOL CAvi::ReadDatas(INT nLoopTime)
{
static DWORD dwDelay = 0;
INT nDivider;
if(m_bPlaying)
{
dwDelay += nLoopTime;
nDivider = 1000/m_Fps;
if(dwDelay>nDivider)
{
NextFrame();
dwDelay = 0;
return TRUE;
}
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -