From 16fe6b1b1a17aca1a0094971264f81067562012b Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 8 Dec 2024 16:16:15 +0300 Subject: [PATCH] engine: client: avi: remove VFW-based player --- engine/client/avi/avi_win.c | 735 ------------------------------------ 1 file changed, 735 deletions(-) delete mode 100644 engine/client/avi/avi_win.c diff --git a/engine/client/avi/avi_win.c b/engine/client/avi/avi_win.c deleted file mode 100644 index 85370712..00000000 --- a/engine/client/avi/avi_win.c +++ /dev/null @@ -1,735 +0,0 @@ -/* -avi_win.c - playing AVI files (based on original AVIKit code, Win32 version) -Copyright (c) 2003-2004, Ruari O'Sullivan -Copyright (C) 2010 Uncle Mike - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ - -#include "defaults.h" -#if XASH_AVI == AVI_WIN32 -#include "common.h" -#include "client.h" -#include // video for windows - -// msvfw32.dll exports -static HDRAWDIB (_stdcall *pDrawDibOpen)( void ); -static BOOL (_stdcall *pDrawDibClose)( HDRAWDIB hdd ); -static BOOL (_stdcall *pDrawDibDraw)( HDRAWDIB, HDC, int, int, int, int, LPBITMAPINFOHEADER, void*, int, int, int, int, uint ); - -static dllfunc_t msvfw_funcs[] = -{ -{ "DrawDibOpen", (void **) &pDrawDibOpen }, -{ "DrawDibDraw", (void **) &pDrawDibDraw }, -{ "DrawDibClose", (void **) &pDrawDibClose }, -{ NULL, NULL } -}; - -dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, false }; - -// msacm32.dll exports -static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD ); -static MMRESULT (_stdcall *pacmStreamPrepareHeader)( HACMSTREAM, LPACMSTREAMHEADER, DWORD ); -static MMRESULT (_stdcall *pacmStreamUnprepareHeader)( HACMSTREAM, LPACMSTREAMHEADER, DWORD ); -static MMRESULT (_stdcall *pacmStreamConvert)( HACMSTREAM, LPACMSTREAMHEADER, DWORD ); -static MMRESULT (_stdcall *pacmStreamSize)( HACMSTREAM, DWORD, LPDWORD, DWORD ); -static MMRESULT (_stdcall *pacmStreamClose)( HACMSTREAM, DWORD ); - -static dllfunc_t msacm_funcs[] = -{ -{ "acmStreamOpen", (void **) &pacmStreamOpen }, -{ "acmStreamPrepareHeader", (void **) &pacmStreamPrepareHeader }, -{ "acmStreamUnprepareHeader", (void **) &pacmStreamUnprepareHeader }, -{ "acmStreamConvert", (void **) &pacmStreamConvert }, -{ "acmStreamSize", (void **) &pacmStreamSize }, -{ "acmStreamClose", (void **) &pacmStreamClose }, -{ NULL, NULL } -}; - -dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, false }; - -// avifil32.dll exports -static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize ); -static int (_stdcall *pAVIStreamRead)( PAVISTREAM pavi, LONG lStart, LONG lSamples, void *lpBuffer, LONG cbBuffer, LONG *plBytes, LONG *plSamples ); -static PGETFRAME (_stdcall *pAVIStreamGetFrameOpen)( PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted ); -static int (_stdcall *pAVIStreamTimeToSample)( PAVISTREAM pavi, LONG lTime ); -static void* (_stdcall *pAVIStreamGetFrame)( PGETFRAME pg, LONG lPos ); -static int (_stdcall *pAVIStreamGetFrameClose)( PGETFRAME pg ); -static dword (_stdcall *pAVIStreamRelease)( PAVISTREAM pavi ); -static int (_stdcall *pAVIFileOpenW)( PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode, LPCLSID lpHandler ); -static int (_stdcall *pAVIFileGetStream)( PAVIFILE pfile, PAVISTREAM *ppavi, DWORD fccType, LONG lParam ); -static int (_stdcall *pAVIStreamReadFormat)( PAVISTREAM pavi, LONG lPos,LPVOID lpFormat, LONG *lpcbFormat ); -static int (_stdcall *pAVIStreamStart)( PAVISTREAM pavi ); -static dword (_stdcall *pAVIFileRelease)( PAVIFILE pfile ); -static void (_stdcall *pAVIFileInit)( void ); -static void (_stdcall *pAVIFileExit)( void ); - -static dllfunc_t avifile_funcs[] = -{ -{ "AVIFileExit", (void **) &pAVIFileExit }, -{ "AVIFileGetStream", (void **) &pAVIFileGetStream }, -{ "AVIFileInit", (void **) &pAVIFileInit }, -{ "AVIFileOpenW", (void **) &pAVIFileOpenW }, -{ "AVIFileRelease", (void **) &pAVIFileRelease }, -{ "AVIStreamGetFrame", (void **) &pAVIStreamGetFrame }, -{ "AVIStreamGetFrameClose", (void **) &pAVIStreamGetFrameClose }, -{ "AVIStreamGetFrameOpen", (void **) &pAVIStreamGetFrameOpen }, -{ "AVIStreamInfoA", (void **) &pAVIStreamInfo }, -{ "AVIStreamRead", (void **) &pAVIStreamRead }, -{ "AVIStreamReadFormat", (void **) &pAVIStreamReadFormat }, -{ "AVIStreamRelease", (void **) &pAVIStreamRelease }, -{ "AVIStreamStart", (void **) &pAVIStreamStart }, -{ "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample }, -{ NULL, NULL } -}; - -dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, false }; - -typedef struct movie_state_s -{ - qboolean active; - qboolean quiet; // ignore error messages - - PAVIFILE pfile; // avi file pointer - PAVISTREAM video_stream; // video stream pointer - PGETFRAME video_getframe; // pointer to getframe object for video stream - int video_frames; // total frames - int video_xres; // video stream resolution - int video_yres; - float video_fps; // video stream fps - - PAVISTREAM audio_stream; // audio stream pointer - WAVEFORMAT *audio_header; // audio stream header - int audio_header_size; // WAVEFORMAT is returned for PCM data; WAVEFORMATEX for others - int audio_codec; // WAVE_FORMAT_PCM is oldstyle: anything else needs conversion - int audio_length; // in converted samples - int audio_bytes_per_sample; // guess. - - // compressed audio specific data - dword cpa_blockalign; // block size to read - HACMSTREAM cpa_conversion_stream; - ACMSTREAMHEADER cpa_conversion_header; - byte *cpa_srcbuffer; // maintained buffer for raw data - byte *cpa_dstbuffer; - - dword cpa_blocknum; // current block - dword cpa_blockpos; // read position in current block - dword cpa_blockoffset; // corresponding offset in bytes in the output stream - - // for additional unpack Ms-RLE codecs etc - HDC hDC; // compatible DC - HDRAWDIB hDD; // DrawDib handler - HBITMAP hBitmap; // for DIB conversions - byte *pframe_data; // converted framedata -} movie_state_t; - -static qboolean avi_initialized = false; -static movie_state_t avi[2]; - -// Converts a compressed audio stream into uncompressed PCM. -qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) -{ - WAVEFORMATEX dest_header, *sh, *dh; - AVISTREAMINFO stream_info; - dword dest_length; - short bits; - - // WMA codecs, both versions - they simply don't work. - if( Avi->audio_header->wFormatTag == 0x160 || Avi->audio_header->wFormatTag == 0x161 ) - { - if( !Avi->quiet ) - Con_Reportf( S_ERROR "ACM does not support this audio codec.\n" ); - return false; - } - - // get audio stream info to work with - pAVIStreamInfo( Avi->audio_stream, &stream_info, sizeof( stream_info )); - - if( Avi->audio_header_size < sizeof( WAVEFORMATEX )) - { - if( !Avi->quiet ) - Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" ); - return false; - } - - sh = (WAVEFORMATEX *)Avi->audio_header; - bits = 16; // predict state - - // how much of this is actually required? - dest_header.wFormatTag = WAVE_FORMAT_PCM; // yay - dest_header.wBitsPerSample = bits; // 16bit - dest_header.nChannels = sh->nChannels; - dest_header.nSamplesPerSec = sh->nSamplesPerSec; // take straight from the source stream - dest_header.nAvgBytesPerSec = (bits >> 3) * sh->nChannels * sh->nSamplesPerSec; - dest_header.nBlockAlign = (bits >> 3) * sh->nChannels; - dest_header.cbSize = 0; // no more data. - - dh = &dest_header; - - // open the stream - if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR ) - { - // try with 8 bit destination instead - bits = 8; - - dest_header.wBitsPerSample = bits; // 8bit - dest_header.nAvgBytesPerSec = ( bits >> 3 ) * sh->nChannels * sh->nSamplesPerSec; - dest_header.nBlockAlign = ( bits >> 3 ) * sh->nChannels; // 1 sample at a time - - if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR ) - { - if( !Avi->quiet ) - Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" ); - return false; - } - } - - Avi->cpa_blockalign = sh->nBlockAlign; - dest_length = 0; - - // mp3 specific fix - if( sh->wFormatTag == 0x55 ) - { - LPMPEGLAYER3WAVEFORMAT k; - - k = (LPMPEGLAYER3WAVEFORMAT)sh; - Avi->cpa_blockalign = k->nBlockSize; - } - - // get the size of the output buffer for streaming the compressed audio - if( pacmStreamSize( Avi->cpa_conversion_stream, Avi->cpa_blockalign, &dest_length, ACM_STREAMSIZEF_SOURCE ) != MMSYSERR_NOERROR ) - { - if( !Avi->quiet ) - Con_Reportf( S_ERROR "Couldn't get ACM conversion stream size.\n" ); - pacmStreamClose( Avi->cpa_conversion_stream, 0 ); - return false; - } - - Avi->cpa_srcbuffer = (byte *)Mem_Malloc( cls.mempool, Avi->cpa_blockalign ); - Avi->cpa_dstbuffer = (byte *)Mem_Malloc( cls.mempool, dest_length ); // maintained buffer for raw data - - // prep the headers! - Avi->cpa_conversion_header.cbStruct = sizeof( ACMSTREAMHEADER ); - Avi->cpa_conversion_header.fdwStatus = 0; - Avi->cpa_conversion_header.dwUser = 0; // no user data - Avi->cpa_conversion_header.pbSrc = Avi->cpa_srcbuffer; // source buffer - Avi->cpa_conversion_header.cbSrcLength = Avi->cpa_blockalign; // source buffer size - Avi->cpa_conversion_header.cbSrcLengthUsed = 0; - Avi->cpa_conversion_header.dwSrcUser = 0; // no user data - Avi->cpa_conversion_header.pbDst = Avi->cpa_dstbuffer; // dest buffer - Avi->cpa_conversion_header.cbDstLength = dest_length; // dest buffer size - Avi->cpa_conversion_header.cbDstLengthUsed = 0; - Avi->cpa_conversion_header.dwDstUser = 0; // no user data - - if( pacmStreamPrepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 ) != MMSYSERR_NOERROR ) - { - if( !Avi->quiet ) - Con_Reportf( S_ERROR "couldn't prepare stream headers.\n" ); - pacmStreamClose( Avi->cpa_conversion_stream, 0 ); - return false; - } - - Avi->cpa_blocknum = 0; // start at 0. - Avi->cpa_blockpos = 0; - Avi->cpa_blockoffset = 0; - - pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL ); - pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN|ACM_STREAMCONVERTF_START ); - - // convert first chunk twice. it often fails the first time. BLACK MAGIC. - pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL ); - pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN ); - - Avi->audio_bytes_per_sample = (bits >> 3 ) * Avi->audio_header->nChannels; - - return true; -} - -qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration ) -{ - if( !Avi->active ) - return false; - - if( xres != NULL ) - *xres = Avi->video_xres; - - if( yres != NULL ) - *yres = Avi->video_yres; - - if( duration != NULL ) - *duration = (float)Avi->video_frames / Avi->video_fps; - - return true; -} - -// returns a unique frame identifier -int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time ) -{ - if( !Avi->active ) - return 0; - - return (time * Avi->video_fps); -} - -int AVI_TimeToSoundPosition( movie_state_t *Avi, int time ) -{ - if( !Avi->active || !Avi->audio_stream ) - return 0; - - // UNDONE: what about compressed audio? - return pAVIStreamTimeToSample( Avi->audio_stream, time ) * Avi->audio_bytes_per_sample; -} - -// gets the raw frame data -byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame ) -{ - LPBITMAPINFOHEADER frame_info; - byte *frame_raw; - - if( !Avi->active ) return NULL; - - if( frame >= Avi->video_frames ) - frame = Avi->video_frames - 1; - - frame_info = (LPBITMAPINFOHEADER)pAVIStreamGetFrame( Avi->video_getframe, frame ); - frame_raw = (byte *)frame_info + frame_info->biSize + frame_info->biClrUsed * sizeof( RGBQUAD ); - pDrawDibDraw( Avi->hDD, Avi->hDC, 0, 0, Avi->video_xres, Avi->video_yres, frame_info, frame_raw, 0, 0, Avi->video_xres, Avi->video_yres, 0 ); - - return Avi->pframe_data; -} - -qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info ) -{ - if( !Avi->active || Avi->audio_stream == NULL || snd_info == NULL ) - { - return false; - } - - snd_info->rate = Avi->audio_header->nSamplesPerSec; - snd_info->channels = Avi->audio_header->nChannels; - - if( Avi->audio_codec == WAVE_FORMAT_PCM ) // uncompressed audio! - snd_info->width = ( Avi->audio_bytes_per_sample > Avi->audio_header->nChannels ) ? 2 : 1; - else snd_info->width = 2; // assume compressed audio is always 16 bit - - snd_info->size = snd_info->rate * snd_info->width * snd_info->channels; - snd_info->loopStart = 0; // using loopStart as streampos - - return true; -} - -// sync the current audio read to a specific offset -qboolean AVI_SeekPosition( movie_state_t *Avi, dword offset ) -{ - int breaker; - - if( offset < Avi->cpa_blockoffset ) // well, shit. we can't seek backwards... restart - { - if( Avi->cpa_blockoffset - offset < 500000 ) - return false; // don't bother if it's gonna catch up soon - - Avi->cpa_blocknum = 0; // start at 0, eh. - Avi->cpa_blockpos = 0; - Avi->cpa_blockoffset = 0; - - pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL ); - pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN|ACM_STREAMCONVERTF_START ); - - // convert first chunk twice. it often fails the first time. BLACK MAGIC. - pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL ); - pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN ); - } - - // now then: seek forwards to the required block - breaker = 30; // maximum zero blocks: anti-freeze protection - - while( Avi->cpa_blockoffset + Avi->cpa_conversion_header.cbDstLengthUsed < offset ) - { - Avi->cpa_blocknum++; - Avi->cpa_blockoffset += Avi->cpa_conversion_header.cbDstLengthUsed; - - pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL ); - pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN ); - - if( Avi->cpa_conversion_header.cbDstLengthUsed == 0 ) - breaker--; - else breaker = 30; - - if( breaker <= 0 ) - return false; - - Avi->cpa_blockpos = 0; - } - - // seek to the right position inside the block - Avi->cpa_blockpos = offset - Avi->cpa_blockoffset; - - return true; -} - -// get a chunk of audio from the stream (in bytes) -int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length ) -{ - int result = 0; - int i; - - // zero data past the end of the file - if( offset + length > Avi->audio_length ) - { - if( offset <= Avi->audio_length ) - { - int remaining_length = Avi->audio_length - offset; - - AVI_GetAudioChunk( Avi, audiodata, offset, remaining_length ); - - for( i = remaining_length; i < length; i++ ) - audiodata[i] = 0; - } - else - { - // we out of soundtrack, just zeroing buffer - for( i = 0; i < length; i++ ) - audiodata[i] = 0; - -// return length; - } - } - - // uncompressed audio! - if( Avi->audio_codec == WAVE_FORMAT_PCM ) - { - // very simple - read straight out - pAVIStreamRead( Avi->audio_stream, offset / Avi->audio_bytes_per_sample, length / Avi->audio_bytes_per_sample, audiodata, length, &result, NULL ); - return result; - } - else - { - // compressed audio! - result = 0; - - // seek to correct chunk and all that stuff - if( !AVI_SeekPosition( Avi, offset )) - return 0; // don't continue if we're waiting for the play pointer to catch up - - while( length > 0 ) - { - int blockread = Avi->cpa_conversion_header.cbDstLengthUsed - Avi->cpa_blockpos; - - if( blockread <= 0 ) // read next - { - Avi->cpa_blocknum++; - Avi->cpa_blockoffset += Avi->cpa_conversion_header.cbDstLengthUsed; - - pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL ); - pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN ); - - Avi->cpa_blockpos = 0; - continue; - } - - if( blockread > length ) - blockread = length; - - // copy the data - memcpy( audiodata + result, (void *)( Avi->cpa_dstbuffer + Avi->cpa_blockpos ), blockread ); - - Avi->cpa_blockpos += blockread; - result += blockread; - length -= blockread; - } - - return result; - } -} - -void AVI_CloseVideo( movie_state_t *Avi ) -{ - if( Avi->active ) - { - pAVIStreamGetFrameClose( Avi->video_getframe ); - - if( Avi->audio_stream != NULL ) - { - pAVIStreamRelease( Avi->audio_stream ); - Mem_Free( Avi->audio_header ); - - if( Avi->audio_codec != WAVE_FORMAT_PCM ) - { - pacmStreamUnprepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 ); - pacmStreamClose( Avi->cpa_conversion_stream, 0 ); - Mem_Free( Avi->cpa_srcbuffer ); - Mem_Free( Avi->cpa_dstbuffer ); - } - } - - pAVIStreamRelease( Avi->video_stream ); - - DeleteObject( Avi->hBitmap ); - pDrawDibClose( Avi->hDD ); - DeleteDC( Avi->hDC ); - } - - memset( Avi, 0, sizeof( movie_state_t )); -} - -void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet ) -{ - BITMAPINFOHEADER bmih; - AVISTREAMINFO stream_info; - int opened_streams = 0; - LONG hr; - wchar_t pathBuffer[MAX_PATH]; - - // default state: non-working. - Avi->active = false; - Avi->quiet = quiet; - - // can't load Video For Windows :-( - if( !avi_initialized ) return; - - // convert to wide char - if( MultiByteToWideChar( CP_UTF8, 0, filename, -1, pathBuffer, ARRAYSIZE( pathBuffer )) <= 0 ) - { - Con_DPrintf( S_ERROR "filename buffer limit exceeded\n" ); - return; - } - - // load the AVI - hr = pAVIFileOpenW( &Avi->pfile, pathBuffer, OF_SHARE_DENY_WRITE, 0L ); - - if( hr != 0 ) // error opening AVI: - { - switch( hr ) - { - case AVIERR_BADFORMAT: - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "corrupt file or unknown format.\n" ); - break; - case AVIERR_MEMORY: - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "insufficient memory to open file.\n" ); - break; - case AVIERR_FILEREAD: - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "disk error reading file.\n" ); - break; - case AVIERR_FILEOPEN: - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "disk error opening file.\n" ); - break; - case REGDB_E_CLASSNOTREG: - default: - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "no handler found (or file not found).\n" ); - break; - } - return; - } - - Avi->video_stream = Avi->audio_stream = NULL; - - // open the streams until a stream is not available. - while( 1 ) - { - PAVISTREAM stream = NULL; - - if( pAVIFileGetStream( Avi->pfile, &stream, 0L, opened_streams++ ) != AVIERR_OK ) - break; - - if( stream == NULL ) - break; - - pAVIStreamInfo( stream, &stream_info, sizeof( stream_info )); - - if( stream_info.fccType == streamtypeVIDEO && Avi->video_stream == NULL ) - { - Avi->video_stream = stream; - Avi->video_frames = stream_info.dwLength; - Avi->video_xres = stream_info.rcFrame.right - stream_info.rcFrame.left; - Avi->video_yres = stream_info.rcFrame.bottom - stream_info.rcFrame.top; - Avi->video_fps = (float)stream_info.dwRate / (float)stream_info.dwScale; - } - else if( stream_info.fccType == streamtypeAUDIO && Avi->audio_stream == NULL && load_audio ) - { - int size; - - Avi->audio_stream = stream; - - // read the audio header - pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), 0, &size ); - - Avi->audio_header = (WAVEFORMAT *)Mem_Malloc( cls.mempool, size ); - pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), Avi->audio_header, &size ); - Avi->audio_header_size = size; - Avi->audio_codec = Avi->audio_header->wFormatTag; - - // length of converted audio in samples - Avi->audio_length = (int)((float)stream_info.dwLength / Avi->audio_header->nAvgBytesPerSec ); - Avi->audio_length *= Avi->audio_header->nSamplesPerSec; - - if( Avi->audio_codec != WAVE_FORMAT_PCM ) - { - if( !AVI_ACMConvertAudio( Avi )) - { - Mem_Free( Avi->audio_header ); - Avi->audio_stream = NULL; - continue; - } - } - else Avi->audio_bytes_per_sample = Avi->audio_header->nBlockAlign; - Avi->audio_length *= Avi->audio_bytes_per_sample; - } - else - { - pAVIStreamRelease( stream ); - } - } - - // display error message-stream not found. - if( Avi->video_stream == NULL ) - { - if( Avi->pfile ) // if file is open, close it - pAVIFileRelease( Avi->pfile ); - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "couldn't find a valid video stream.\n" ); - return; - } - - pAVIFileRelease( Avi->pfile ); // release the file - Avi->video_getframe = pAVIStreamGetFrameOpen( Avi->video_stream, NULL ); // open the frame getter - - if( Avi->video_getframe == NULL ) - { - if( !Avi->quiet ) - Con_DPrintf( S_ERROR "error attempting to read video frames.\n" ); - return; // couldn't open frame getter. - } - - bmih.biSize = sizeof( BITMAPINFOHEADER ); - bmih.biPlanes = 1; - bmih.biBitCount = 32; - bmih.biCompression = BI_RGB; - bmih.biWidth = Avi->video_xres; - bmih.biHeight = -Avi->video_yres; // invert height to flip image upside down - - Avi->hDC = CreateCompatibleDC( 0 ); - Avi->hDD = pDrawDibOpen(); - Avi->hBitmap = CreateDIBSection( Avi->hDC, (BITMAPINFO*)(&bmih), DIB_RGB_COLORS, (void**)(&Avi->pframe_data), NULL, 0 ); - SelectObject( Avi->hDC, Avi->hBitmap ); - - Avi->active = true; // done -} - -qboolean AVI_IsActive( movie_state_t *Avi ) -{ - if( Avi != NULL ) - return Avi->active; - return false; -} - -movie_state_t *AVI_GetState( int num ) -{ - return &avi[num]; -} - -/* -============= -AVIKit user interface - -============= -*/ -movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) -{ - movie_state_t *Avi; - string path; - const char *fullpath; - - // fast reject - if( !avi_initialized ) - return NULL; - - // open cinematic - Q_snprintf( path, sizeof( path ), "media/%s", filename ); - COM_DefaultExtension( path, ".avi", sizeof( path )); - fullpath = FS_GetDiskPath( path, false ); - - if( FS_FileExists( path, false ) && !fullpath ) - { - Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path ); - return NULL; - } - - Avi = Mem_Malloc( cls.mempool, sizeof( movie_state_t )); - AVI_OpenVideo( Avi, fullpath, load_audio, false ); - - if( !AVI_IsActive( Avi )) - { - AVI_FreeVideo( Avi ); // something bad happens - return NULL; - } - - // all done - return Avi; -} - -void AVI_FreeVideo( movie_state_t *state ) -{ - if( !state ) return; - - if( Mem_IsAllocatedExt( cls.mempool, state )) - { - AVI_CloseVideo( state ); - Mem_Free( state ); - } -} - -qboolean AVI_Initailize( void ) -{ - if( Sys_CheckParm( "-noavi" )) - { - Con_Printf( "AVI: Disabled\n" ); - return false; - } - - if( !Sys_LoadLibrary( &avifile_dll )) - return false; - - if( !Sys_LoadLibrary( &msvfw_dll )) - { - Sys_FreeLibrary( &avifile_dll ); - return false; - } - - if( !Sys_LoadLibrary( &msacm_dll )) - { - Sys_FreeLibrary( &avifile_dll ); - Sys_FreeLibrary( &msvfw_dll ); - return false; - } - - avi_initialized = true; - pAVIFileInit(); - - return true; -} - -void AVI_Shutdown( void ) -{ - if( !avi_initialized ) return; - - pAVIFileExit(); - - Sys_FreeLibrary( &avifile_dll ); - Sys_FreeLibrary( &msvfw_dll ); - Sys_FreeLibrary( &msacm_dll ); - avi_initialized = false; -} -#endif // XASH_AVI == AVI_WIN32