Avi.cpp
上传用户:cydong117
上传日期:2009-11-10
资源大小:638k
文件大小:12k
- #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;
- }