|
|
/*==========================================================================;
* * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: dpvaconv.cpp * Content: Header file for DirectPlayVoice compression provider (ACM) * * History: * Date By Reason * =========== =========== ==================== * 10/27/99 rodtoll created * 02/03/2000 rodtoll Bug #130397 - Prefix detected memory leak * 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE! * 04/02/2001 simonpow Fixes for PREfast bugs #354859 (unitialised variables) * 06/27/2001 rodtoll RC2: DPVOICE: DPVACM's DllMain calls into acm -- potential hang * Move global initialization to first object creation ***************************************************************************/
#include "dpvacmpch.h"
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::CDPVACMConv"
CDPVACMConv::CDPVACMConv( ): m_fDirectConvert(FALSE), m_fValid(FALSE), m_pbInnerBuffer(NULL),m_dwInnerBufferSize(0), m_lRefCount(0), m_hacmSource(NULL), m_hacmTarget(NULL), m_pdvfci(NULL), m_fCritSecInited(FALSE) { }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::InitClass"
BOOL CDPVACMConv::InitClass( ) { if (DNInitializeCriticalSection( &m_csLock )) { m_fCritSecInited = TRUE; return TRUE; } else { return FALSE; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::~CDPVACMConv"
CDPVACMConv::~CDPVACMConv() { if (m_fCritSecInited) { DNDeleteCriticalSection( &m_csLock ); }
if( m_pdvfci != NULL ) { LPBYTE pTmp = (LPBYTE) m_pdvfci; delete [] pTmp; }
if( m_pbInnerBuffer != NULL ) { delete [] m_pbInnerBuffer; }
if( m_hacmSource != NULL ) { acmStreamClose( m_hacmSource, 0 ); }
if( m_hacmTarget != NULL ) { acmStreamClose( m_hacmTarget, 0 ); }
} #undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_QueryInterface"
HRESULT CDPVACMConv::I_QueryInterface( DPVACMCONVOBJECT *This, REFIID riid, PVOID *ppvObj ) { HRESULT hr = S_OK;
if( ppvObj == NULL || !DNVALID_WRITEPTR( ppvObj, sizeof(LPVOID) ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer passed for object" ); return DVERR_INVALIDPOINTER; } *ppvObj=NULL;
DNEnterCriticalSection( &This->pObject->m_csLock );
// hmmm, switch would be cleaner...
if( IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDPVConverter ) ) { *ppvObj = This; This->pObject->I_AddRef( This ); } else { hr = E_NOINTERFACE; }
DNLeaveCriticalSection( &This->pObject->m_csLock ); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_AddRef"
HRESULT CDPVACMConv::I_AddRef( DPVACMCONVOBJECT *This ) { LONG rc; DNEnterCriticalSection( &This->pObject->m_csLock );
rc = ++This->pObject->m_lRefCount; DNLeaveCriticalSection( &This->pObject->m_csLock );
return rc; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_Release"
HRESULT CDPVACMConv::I_Release( DPVACMCONVOBJECT *This ) { LONG rc;
DNEnterCriticalSection( &This->pObject->m_csLock );
rc = --This->pObject->m_lRefCount;
if( rc == 0 ) { DPFX(DPFPREP, DVF_INFOLEVEL, "Destroying object" ); DNLeaveCriticalSection( &This->pObject->m_csLock );
delete This->pObject; delete This;
DecrementObjectCount(); } else { DNLeaveCriticalSection( &This->pObject->m_csLock ); }
return rc; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_InitDeCompress"
HRESULT CDPVACMConv::I_InitDeCompress( DPVACMCONVOBJECT *This, GUID guidSourceCT, LPWAVEFORMATEX lpwfxTargetFormat ) { return This->pObject->InitDeCompress( guidSourceCT, lpwfxTargetFormat ); }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::InitDeCompress"
HRESULT CDPVACMConv::InitDeCompress( GUID guidSourceCT, LPWAVEFORMATEX lpwfxTargetFormat ) { HRESULT hr;
DNEnterCriticalSection( &m_csLock );
if( m_fValid ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Object already initialized" ); DNLeaveCriticalSection( &m_csLock ); return DVERR_INITIALIZED; }
hr = GetCompressionInfo( guidSourceCT );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "GetCTInfo Failed hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
hr = Initialize( m_pdvfci->lpwfxFormat, lpwfxTargetFormat, lpwfxTargetFormat );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to init ct, hr = 0x%x", hr ); delete [] m_pdvfci; m_pdvfci = NULL; DNLeaveCriticalSection( &m_csLock ); return hr; }
DNLeaveCriticalSection( &m_csLock ); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::GetCompressionInfo"
HRESULT CDPVACMConv::GetCompressionInfo( GUID guidCT ) { DWORD dwSize = 0; HRESULT hr; LPBYTE pBuffer = NULL;
hr = CDPVCPI::GetCompressionInfo( NULL, guidCT, pBuffer, &dwSize );
if( hr != DVERR_BUFFERTOOSMALL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error retrieving ct info, hr =0x%x", hr ); return hr; }
pBuffer = new BYTE[dwSize];
if( pBuffer == NULL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error allocating memory" ); return DVERR_OUTOFMEMORY; }
hr = CDPVCPI::GetCompressionInfo( NULL, guidCT, pBuffer, &dwSize );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error retrieving ct info after buff, hr =0x%x", hr ); delete [] pBuffer; return hr; }
m_pdvfci = (LPDVFULLCOMPRESSIONINFO) pBuffer;
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_InitCompress"
HRESULT CDPVACMConv::I_InitCompress( DPVACMCONVOBJECT *This, LPWAVEFORMATEX lpwfxSourceFormat, GUID guidTargetCT ) { return This->pObject->InitCompress( lpwfxSourceFormat, guidTargetCT ); }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::InitCompress"
HRESULT CDPVACMConv::InitCompress( LPWAVEFORMATEX lpwfxSourceFormat, GUID guidTargetCT ) { HRESULT hr;
DNEnterCriticalSection( &m_csLock );
if( m_fValid ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Object already initialized" ); DNLeaveCriticalSection( &m_csLock ); return DVERR_INITIALIZED; }
hr = GetCompressionInfo( guidTargetCT );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "GetCTInfo Failed hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
hr = Initialize( lpwfxSourceFormat, m_pdvfci->lpwfxFormat, lpwfxSourceFormat );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to init ct, hr = 0x%x", hr ); delete [] m_pdvfci; m_pdvfci = NULL; DNLeaveCriticalSection( &m_csLock ); return hr; }
DNLeaveCriticalSection( &m_csLock ); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_IsValid"
HRESULT CDPVACMConv::I_IsValid( DPVACMCONVOBJECT *This, LPBOOL pfValid ) { DNEnterCriticalSection( &This->pObject->m_csLock );
*pfValid = This->pObject->m_fValid;
DNLeaveCriticalSection( &This->pObject->m_csLock );
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_GetUnCompressedFrameSize"
HRESULT CDPVACMConv::I_GetUnCompressedFrameSize( DPVACMCONVOBJECT *This, LPDWORD lpdwFrameSize ) { DNEnterCriticalSection( &This->pObject->m_csLock );
if( !This->pObject->m_fValid ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Object not initialized" ); DNLeaveCriticalSection( &This->pObject->m_csLock ); return DVERR_NOTINITIALIZED; }
*lpdwFrameSize = This->pObject->m_dwUnCompressedFrameSize;
DNLeaveCriticalSection( &This->pObject->m_csLock );
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_GetCompressedFrameSize"
HRESULT CDPVACMConv::I_GetCompressedFrameSize( DPVACMCONVOBJECT *This, LPDWORD lpdwCompressedSize ) { DNEnterCriticalSection( &This->pObject->m_csLock );
if( !This->pObject->m_fValid ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Object not initialized" ); DNLeaveCriticalSection( &This->pObject->m_csLock ); return DVERR_NOTINITIALIZED; }
*lpdwCompressedSize = This->pObject->m_dwCompressedFrameSize;
DNLeaveCriticalSection( &This->pObject->m_csLock );
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_GetNumFramesPerBuffer"
HRESULT CDPVACMConv::I_GetNumFramesPerBuffer( DPVACMCONVOBJECT *This, LPDWORD lpdwFramesPerBuffer ) { DNEnterCriticalSection( &This->pObject->m_csLock );
if( !This->pObject->m_fValid ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Object not initialized" ); DNLeaveCriticalSection( &This->pObject->m_csLock ); return DVERR_NOTINITIALIZED; }
*lpdwFramesPerBuffer = This->pObject->m_dwNumFramesPerBuffer;
DNLeaveCriticalSection( &This->pObject->m_csLock );
return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::I_Convert"
HRESULT CDPVACMConv::I_Convert( DPVACMCONVOBJECT *This, LPVOID lpInputBuffer, DWORD dwInputSize, LPVOID lpOutputBuffer, LPDWORD lpdwOutputSize, BOOL fSilence ) { return This->pObject->Convert( lpInputBuffer, dwInputSize, lpOutputBuffer, lpdwOutputSize, fSilence ); }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::Convert"
HRESULT CDPVACMConv::Convert( LPVOID lpInputBuffer, DWORD dwInputSize, LPVOID lpOutputBuffer, LPDWORD lpdwOutputSize, BOOL fSilence ) { DWORD dwLengthUsed; // Used for storing tmp length values
HRESULT hr;
DNEnterCriticalSection( &m_csLock );
if( !m_fValid ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Object not initialized" ); DNLeaveCriticalSection( &m_csLock ); return DVERR_NOTINITIALIZED; } if( fSilence ) { memset( lpOutputBuffer, m_fTargetEightBit ? 0x80 : 0x00, *lpdwOutputSize ); DNLeaveCriticalSection( &m_csLock ); return true; }
if( m_fDirectConvert ) { // Setup the acm function
memset( &m_ashSource, 0, sizeof( ACMSTREAMHEADER ) ); m_ashSource.cbStruct = sizeof( ACMSTREAMHEADER ); m_ashSource.fdwStatus = 0; m_ashSource.dwUser = 0; m_ashSource.cbSrcLength = dwInputSize; m_ashSource.pbSrc = (LPBYTE) lpInputBuffer; m_ashSource.cbSrcLengthUsed = 0; m_ashSource.dwSrcUser = 0; m_ashSource.pbDst = (LPBYTE) lpOutputBuffer; m_ashSource.cbDstLength = *lpdwOutputSize; m_ashSource.cbDstLengthUsed = 0; m_ashSource.dwDstUser = 0;
// Prepare the header for conversion
hr = acmStreamPrepareHeader( m_hacmSource, &m_ashSource , 0);
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to prepare heade hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
// Convert the data
hr = acmStreamConvert( m_hacmSource, &m_ashSource, ACM_STREAMCONVERTF_BLOCKALIGN );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to perform the conversion hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
hr = acmStreamUnprepareHeader( m_hacmSource, &m_ashSource, 0 );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to perform the conversion hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
dwLengthUsed = m_ashSource.cbDstLengthUsed; } else { // Setup the acm header for conversion fro mthe source to the
// inner format
memset( &m_ashSource, 0, sizeof( ACMSTREAMHEADER ) ); m_ashSource.cbStruct = sizeof( ACMSTREAMHEADER ); m_ashSource.fdwStatus = 0; m_ashSource.dwUser = 0; m_ashSource.cbSrcLength = dwInputSize; m_ashSource.pbSrc = (LPBYTE) lpInputBuffer; m_ashSource.cbSrcLengthUsed = 0; m_ashSource.dwSrcUser = 0; m_ashSource.pbDst = m_pbInnerBuffer; m_ashSource.cbDstLength = m_dwInnerBufferSize; m_ashSource.cbDstLengthUsed = 0; m_ashSource.dwDstUser = 0;
// Prepare the header for conversion
hr = acmStreamPrepareHeader( m_hacmSource, &m_ashSource , 0);
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to prepare first stage header hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
// Convert the data
hr = acmStreamConvert( m_hacmSource, &m_ashSource, ACM_STREAMCONVERTF_BLOCKALIGN );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to convert first stage hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
hr = acmStreamUnprepareHeader( m_hacmSource, &m_ashSource, 0 );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to unprepare first stage header hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
DPFX(DPFPREP, DVF_INFOLEVEL, "CONVERTER: Filling in %d bytes", m_dwInnerBufferSize - m_ashSource.cbDstLengthUsed );
memset( &m_ashTarget, 0, sizeof( ACMSTREAMHEADER ) ); m_ashTarget.cbStruct = sizeof( ACMSTREAMHEADER ); m_ashTarget.fdwStatus = 0; m_ashTarget.dwUser = 0; m_ashTarget.cbSrcLength = m_dwInnerBufferSize; m_ashTarget.pbSrc = m_pbInnerBuffer; m_ashTarget.cbSrcLengthUsed = 0; m_ashTarget.dwSrcUser = 0; m_ashTarget.pbDst = (LPBYTE) lpOutputBuffer; m_ashTarget.cbDstLength = *lpdwOutputSize; m_ashTarget.cbDstLengthUsed = 0; m_ashTarget.dwDstUser = 0;
// Prepare the header for conversion
hr = acmStreamPrepareHeader( m_hacmTarget, &m_ashTarget , 0);
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to prepare second stage header hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
// Convert the data
hr = acmStreamConvert( m_hacmTarget, &m_ashTarget, ACM_STREAMCONVERTF_BLOCKALIGN );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to convert second stage hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
hr = acmStreamUnprepareHeader( m_hacmTarget, &m_ashTarget, 0 );
if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to unprepare second stage header hr=0x%x", hr ); DNLeaveCriticalSection( &m_csLock ); return hr; }
dwLengthUsed = m_ashTarget.cbDstLengthUsed; }
DWORD offset = *lpdwOutputSize - dwLengthUsed;
if( offset > 0 ) { LPBYTE lpbTmp = (LPBYTE) lpOutputBuffer; // memset( &lpbTmp[*lpdwOutputSize - offset], (m_fTargetEightBit) ? 0x80 : 0x00, offset );
memset( &lpbTmp[*lpdwOutputSize - offset], lpbTmp[*lpdwOutputSize - offset-1], offset ); }
DNLeaveCriticalSection( &m_csLock );
// Always return the right length
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::Initialize"
HRESULT CDPVACMConv::Initialize( WAVEFORMATEX *pwfSrcFormat, WAVEFORMATEX *pwfTargetFormat, const WAVEFORMATEX *pwfUnCompressedFormat ) { HRESULT retValue;
// Attempt the conversion directly
retValue = acmStreamOpen( &m_hacmSource, NULL, pwfSrcFormat, pwfTargetFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME );
// If it's not possible, we'll have to do a two step conversion
if( retValue == static_cast<HRESULT>(ACMERR_NOTPOSSIBLE) ) { retValue = acmStreamOpen( &m_hacmSource, NULL, pwfSrcFormat, &CDPVACMI::s_wfxInnerFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME );
if( FAILED( retValue ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Source compressor failed init hr=0x%x", retValue ); goto INITIALIZE_ERROR; } retValue = acmStreamOpen( &m_hacmTarget, NULL, &CDPVACMI::s_wfxInnerFormat, pwfTargetFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME );
if( FAILED( retValue ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Target compressor failed init hr=0x%x", retValue ); goto INITIALIZE_ERROR; }
m_fDirectConvert = FALSE;
} // Still not possible
else if( retValue != static_cast<HRESULT >(0)) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Compressor create error hr=0x%x", retValue ); goto INITIALIZE_ERROR; } // Direct conversion was possible
else { m_fDirectConvert = TRUE; }
// If we're not direct converting, create an inner conversion
// buffer
if( !m_fDirectConvert ) { m_dwInnerBufferSize = CalcUnCompressedFrameSize( &CDPVACMI::s_wfxInnerFormat ); m_pbInnerBuffer = new BYTE[m_dwInnerBufferSize];
if( m_pbInnerBuffer == NULL ) { acmStreamClose( m_hacmSource, 0 ); acmStreamClose( m_hacmTarget, 0 ); m_fValid = FALSE; retValue = DVERR_OUTOFMEMORY; } } else { m_pbInnerBuffer = NULL; m_dwInnerBufferSize = 0; }
m_dwUnCompressedFrameSize = CalcUnCompressedFrameSize( pwfUnCompressedFormat ); m_dwCompressedFrameSize = m_pdvfci->dwFrameLength; m_dwNumFramesPerBuffer = m_pdvfci->dwFramesPerBuffer;
if( pwfTargetFormat->wBitsPerSample == 8 ) { m_fTargetEightBit = TRUE; } else { m_fTargetEightBit = FALSE; }
m_fValid = TRUE;
return DV_OK; INITIALIZE_ERROR:
if( m_hacmSource != NULL ) acmStreamClose( m_hacmSource, 0 );
if( m_hacmTarget != NULL ) acmStreamClose( m_hacmTarget, 0 );
if( m_pbInnerBuffer != NULL ) delete [] m_pbInnerBuffer;
m_fValid = FALSE;
return retValue; }
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMConv::CalcUnCompressedFrameSize"
DWORD CDPVACMConv::CalcUnCompressedFrameSize( const WAVEFORMATEX* lpwfxFormat ) const { DWORD frameSize;
switch( lpwfxFormat->nSamplesPerSec ) { case 8000: frameSize = m_pdvfci->dwFrame8Khz; break; case 11025: frameSize = m_pdvfci->dwFrame11Khz; break; case 22050: frameSize = m_pdvfci->dwFrame22Khz; break; case 44100: frameSize = m_pdvfci->dwFrame44Khz; break; default: return 0; }
if( lpwfxFormat->wBitsPerSample == 16 ) frameSize *= 2;
frameSize *= lpwfxFormat->nChannels;
return frameSize; }
|