www.pudn.com > mir112347628.rar > 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; 
}