Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

667 lines
18 KiB

/*==========================================================================;
*
* 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;
}