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.
545 lines
16 KiB
545 lines
16 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dpvacmi.cpp
|
|
* Content: Definition of object which implements ACM compression provider interface
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* =========== =========== ====================
|
|
* 10/27/99 rodtoll created
|
|
* 12/16/99 rodtoll Bug #123250 - Insert proper names/descriptions for codecs
|
|
* Codec names now based on resource entries for format and
|
|
* names are constructed using ACM names + bitrate
|
|
* 01/20/00 rodtoll Removed dplay reference (DPERR_OUTOFMEMORY)
|
|
* 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
|
|
* 03/16/2000 rodtoll Fixed problem w/GameVoice build -- always loaded dvoice provider
|
|
* 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k on non-admin account
|
|
* 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
|
|
* 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h added STR_* and strutils.h
|
|
* 08/31/2000 rodtoll Whistler Bug #171837, 171838 - Prefix Bug
|
|
* 04/22/2001 rodtoll MANBUG #50058 DPVOICE: VoicePosition: No sound for couple of seconds when
|
|
* positioning bars moved. Increased # of frames / buffer value for codecs.
|
|
* 02/25/2002 rodtoll WINBUG #550063: Potential DOS by forcing server to allocate excessive amounts of memory.
|
|
* Reduced upper bounds on individual sub-queues to 32 messages from 64.
|
|
* rodtoll WINBUG #552283: Reduce attack surface / dead code removal
|
|
* Removed ability to load arbitrary ACM codecs.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dpvacmpch.h"
|
|
|
|
|
|
#define DPVACM_NUM_DEFAULT_TYPES 4
|
|
|
|
BYTE abTrueSpeechData[] = {
|
|
0x01, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
BYTE abGSMData[] = {
|
|
0x40, 0x01
|
|
};
|
|
|
|
BYTE abADPCMData[] = {
|
|
0xF4, 0x01, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
|
|
0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
|
0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,
|
|
0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
|
|
};
|
|
|
|
VOID *s_pvExtras[DPVACM_NUM_DEFAULT_TYPES] = {
|
|
&abTrueSpeechData,
|
|
&abGSMData,
|
|
&abADPCMData,
|
|
NULL
|
|
};
|
|
|
|
WAVEFORMATEX s_wfxFormats[DPVACM_NUM_DEFAULT_TYPES] =
|
|
{
|
|
// Tag, Chan, SamS, Avg, Align, Bits, size
|
|
{ 34, 0x01, 8000, 1067, 32, 1, sizeof( abTrueSpeechData ) },
|
|
{ 49, 0x01, 8000, 1625, 65, 0, sizeof( abGSMData ) },
|
|
{ 2, 0x01, 8000, 4096, 256, 4, sizeof( abADPCMData ) },
|
|
{ 1, 0x01, 8000, 8000, 1, 8, 0 }
|
|
};
|
|
|
|
DVFULLCOMPRESSIONINFO s_dvInfoDefault[DPVACM_NUM_DEFAULT_TYPES] =
|
|
{
|
|
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_TRUESPEECH.Data1, DPVCTGUID_TRUESPEECH.Data2, DPVCTGUID_TRUESPEECH.Data3,
|
|
DPVCTGUID_TRUESPEECH.Data4[0], DPVCTGUID_TRUESPEECH.Data4[1], DPVCTGUID_TRUESPEECH.Data4[2], DPVCTGUID_TRUESPEECH.Data4[3],
|
|
DPVCTGUID_TRUESPEECH.Data4[4], DPVCTGUID_TRUESPEECH.Data4[5], DPVCTGUID_TRUESPEECH.Data4[6], DPVCTGUID_TRUESPEECH.Data4[7],
|
|
NULL, NULL, 0, 8536, NULL, 12, 1, 90, 96, 720, 993, 1986, 3972, 32, 22, 10, 1, 0, 0 },
|
|
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_GSM.Data1, DPVCTGUID_GSM.Data2, DPVCTGUID_GSM.Data3,
|
|
DPVCTGUID_GSM.Data4[0], DPVCTGUID_GSM.Data4[1], DPVCTGUID_GSM.Data4[2], DPVCTGUID_GSM.Data4[3],
|
|
DPVCTGUID_GSM.Data4[4], DPVCTGUID_GSM.Data4[5], DPVCTGUID_GSM.Data4[6], DPVCTGUID_GSM.Data4[7],
|
|
NULL, NULL, 0, 13000, NULL, 13, 1, 80, 130, 640, 882, 1764, 3528, 32, 24, 10, 1, 0, 0 },
|
|
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_ADPCM.Data1, DPVCTGUID_ADPCM.Data2, DPVCTGUID_ADPCM.Data3,
|
|
DPVCTGUID_ADPCM.Data4[0], DPVCTGUID_ADPCM.Data4[1], DPVCTGUID_ADPCM.Data4[2], DPVCTGUID_ADPCM.Data4[3],
|
|
DPVCTGUID_ADPCM.Data4[4], DPVCTGUID_ADPCM.Data4[5], DPVCTGUID_ADPCM.Data4[6], DPVCTGUID_ADPCM.Data4[7],
|
|
NULL, NULL, 0, 32768, NULL, 15, 1, 63, 256, 500, 690, 1380, 2760, 32, 31, 10, 1, 0, 0 },
|
|
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_NONE.Data1, DPVCTGUID_NONE.Data2, DPVCTGUID_NONE.Data3,
|
|
DPVCTGUID_NONE.Data4[0], DPVCTGUID_NONE.Data4[1], DPVCTGUID_NONE.Data4[2], DPVCTGUID_NONE.Data4[3],
|
|
DPVCTGUID_NONE.Data4[4], DPVCTGUID_NONE.Data4[5], DPVCTGUID_NONE.Data4[6], DPVCTGUID_NONE.Data4[7],
|
|
NULL, NULL, 0, 64000, NULL, 20, 1, 50, 394, 394, 543, 1086, 2172, 32, 39, 10, 1, 0, 0 }
|
|
};
|
|
|
|
const wchar_t * const s_wszInfoNames[DPVACM_NUM_DEFAULT_TYPES] =
|
|
{
|
|
L"DSP Group Truespeech(TM) (8.000 kHz, 1 Bit, Mono)",
|
|
L"GSM 6.10 (8.000 kHz, Mono)",
|
|
L"Microsoft ADPCM (8.000 kHz, 4 Bit, Mono)",
|
|
L"PCM (8.000 kHz, 8 Bit, Mono"
|
|
};
|
|
|
|
WAVEFORMATEX CDPVACMI::s_wfxInnerFormat= {
|
|
WAVE_FORMAT_PCM, 1,8000,16000,2,16,0
|
|
};
|
|
|
|
#define MAX_RESOURCE_STRING_LENGTH 200
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::LoadDefaultTypes"
|
|
HRESULT CDPVACMI::LoadDefaultTypes( HINSTANCE hInst )
|
|
{
|
|
HRESULT hr = DV_OK;
|
|
CompressionNode *pNewNode;
|
|
CWaveFormat wfxFormat;
|
|
|
|
for( DWORD dwIndex = 0; dwIndex < DPVACM_NUM_DEFAULT_TYPES; dwIndex++ )
|
|
{
|
|
pNewNode = new CompressionNode;
|
|
|
|
if( pNewNode == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory allocation failure" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
pNewNode->pdvfci = new DVFULLCOMPRESSIONINFO;
|
|
|
|
if( pNewNode->pdvfci == NULL )
|
|
{
|
|
delete pNewNode;
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory allocation failure" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
// Copy main portion
|
|
memcpy( pNewNode->pdvfci, &s_dvInfoDefault[dwIndex], sizeof( DVFULLCOMPRESSIONINFO ) );
|
|
|
|
// Copy the waveformat
|
|
hr = wfxFormat.InitializeCPY( &s_wfxFormats[dwIndex], s_pvExtras[dwIndex] );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Unable to initialize built-in type %d", dwIndex );
|
|
CN_FreeItem( pNewNode );
|
|
continue;
|
|
}
|
|
|
|
pNewNode->pdvfci->lpwfxFormat = wfxFormat.Disconnect();
|
|
|
|
DNASSERT( pNewNode->pdvfci->lpwfxFormat );
|
|
|
|
hr = GetCompressionNameAndDescription( hInst, pNewNode->pdvfci );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error building built-in type: %d hr=0x%x", dwIndex, hr );
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Type will not be available" );
|
|
|
|
CN_FreeItem( pNewNode );
|
|
|
|
continue;
|
|
}
|
|
|
|
AddEntry( pNewNode );
|
|
}
|
|
|
|
return DV_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::AddEntry"
|
|
void CDPVACMI::AddEntry( CompressionNode *pNewNode )
|
|
{
|
|
CompressionNode *pcNode, *pcPrevNode;
|
|
|
|
pcPrevNode = NULL;
|
|
pcNode = s_pcnList;
|
|
|
|
// Run the list and ensure an entry doesn't already exist
|
|
// If one does, over-ride it with this new one.
|
|
while( pcNode )
|
|
{
|
|
// A node already exists for this type
|
|
if( pcNode->pdvfci->guidType == pNewNode->pdvfci->guidType )
|
|
{
|
|
// We need to drop this count because we increment it below.
|
|
s_dwNumCompressionTypes--;
|
|
|
|
if( pcPrevNode == NULL )
|
|
{
|
|
s_pcnList = pcNode->pcnNext;
|
|
}
|
|
else
|
|
{
|
|
pcPrevNode->pcnNext = pcNode->pcnNext;
|
|
}
|
|
|
|
CN_FreeItem(pcNode);
|
|
break;
|
|
}
|
|
|
|
pcPrevNode = pcNode;
|
|
pcNode = pcNode->pcnNext;
|
|
}
|
|
|
|
pNewNode->pcnNext = s_pcnList;
|
|
s_pcnList = pNewNode;
|
|
s_dwNumCompressionTypes++;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::InitCompressionList"
|
|
HRESULT CDPVACMI::InitCompressionList( HINSTANCE hInst, const wchar_t *szwRegistryBase )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = IsPCMConverterAvailable();
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "PCM Converter is disabled hr=0x%x, no ACM compression types are available", hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = LoadDefaultTypes( hInst );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load built-in types from registry." );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return DV_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::CreateCompressor"
|
|
HRESULT CDPVACMI::CreateCompressor( DPVCPIOBJECT *This, LPWAVEFORMATEX lpwfxSrcFormat, GUID guidTargetCT, PDPVCOMPRESSOR *ppCompressor, DWORD dwFlags )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = COM_CoCreateInstance( CLSID_DPVCPACM_CONVERTER, NULL, CLSCTX_INPROC_SERVER, IID_IDPVConverter, (void **) ppCompressor, FALSE );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to create converter, hr = 0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = (*ppCompressor)->lpVtbl->InitCompress( (*ppCompressor), lpwfxSrcFormat, guidTargetCT );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to init compressor, hr = 0x%x", hr );
|
|
(*ppCompressor)->lpVtbl->Release((*ppCompressor));
|
|
*ppCompressor = NULL;
|
|
return hr;
|
|
}
|
|
|
|
return DV_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::CreateDeCompressor"
|
|
HRESULT CDPVACMI::CreateDeCompressor( DPVCPIOBJECT *This, GUID guidTargetCT, LPWAVEFORMATEX lpwfxSrcFormat, PDPVCOMPRESSOR *ppCompressor, DWORD dwFlags )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = COM_CoCreateInstance( CLSID_DPVCPACM_CONVERTER, NULL, CLSCTX_INPROC_SERVER, IID_IDPVConverter, (void **) ppCompressor, FALSE );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to create decompressor, hr = 0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = (*ppCompressor)->lpVtbl->InitDeCompress( (*ppCompressor), guidTargetCT, lpwfxSrcFormat );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to init decompressor, hr = 0x%x", hr );
|
|
(*ppCompressor)->lpVtbl->Release((*ppCompressor));
|
|
*ppCompressor = NULL;
|
|
return hr;
|
|
}
|
|
|
|
return DV_OK;
|
|
}
|
|
|
|
// # of chars of extra tacked on by description
|
|
// This is equivalent to "XXXXXXX.X kbit/s"
|
|
#define DVACMCP_EXTRACHARS 80
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::GetDriverNameW"
|
|
HRESULT CDPVACMI::GetDriverNameW( HACMDRIVERID hadid, wchar_t *szwDriverName )
|
|
{
|
|
ACMDRIVERDETAILSW acDriverDetails;
|
|
MMRESULT mmr;
|
|
|
|
memset( &acDriverDetails, 0x00, sizeof( ACMDRIVERDETAILS ) );
|
|
acDriverDetails.cbStruct = sizeof( ACMDRIVERDETAILS );
|
|
|
|
mmr = acmDriverDetailsW( hadid, &acDriverDetails, 0 );
|
|
|
|
if( mmr != 0 )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get driver details mmr=0x%x", mmr );
|
|
return DVERR_COMPRESSIONNOTSUPPORTED;
|
|
}
|
|
|
|
if( acDriverDetails.fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Driver is disabled!" );
|
|
return DVERR_COMPRESSIONNOTSUPPORTED;
|
|
}
|
|
|
|
wcscpy( szwDriverName, acDriverDetails.szShortName );
|
|
|
|
return DV_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::GetDriverNameA"
|
|
HRESULT CDPVACMI::GetDriverNameA( HACMDRIVERID hadid, wchar_t *szwDriverName )
|
|
{
|
|
ACMDRIVERDETAILSA acDriverDetails;
|
|
MMRESULT mmr;
|
|
|
|
memset( &acDriverDetails, 0x00, sizeof( ACMDRIVERDETAILS ) );
|
|
acDriverDetails.cbStruct = sizeof( ACMDRIVERDETAILS );
|
|
|
|
mmr = acmDriverDetailsA( hadid, &acDriverDetails, 0 );
|
|
|
|
if( mmr != 0 )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get driver details mmr=0x%x", mmr );
|
|
return DVERR_COMPRESSIONNOTSUPPORTED;
|
|
}
|
|
|
|
if( acDriverDetails.fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Driver is disabled!" );
|
|
return DVERR_COMPRESSIONNOTSUPPORTED;
|
|
}
|
|
|
|
if( FAILED(STR_jkAnsiToWide( szwDriverName, acDriverDetails.szShortName, ACMDRIVERDETAILS_SHORTNAME_CHARS+1 )) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to convert driver name to UNICODE" );
|
|
return DVERR_COMPRESSIONNOTSUPPORTED;
|
|
}
|
|
|
|
return DV_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::LoadAndAllocString"
|
|
HRESULT CDPVACMI::LoadAndAllocString( HINSTANCE hInstance, UINT uiResourceID, wchar_t **lpswzString )
|
|
{
|
|
int length;
|
|
HRESULT hr;
|
|
|
|
#ifdef UNICODE
|
|
wchar_t wszTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
|
|
|
|
length = LoadStringW( hInstance, uiResourceID, wszTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
|
|
|
|
if( length == 0 )
|
|
{
|
|
hr = GetLastError();
|
|
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load resource ID %d error 0x%x", uiResourceID, hr );
|
|
*lpswzString = NULL;
|
|
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
*lpswzString = new wchar_t[length+1];
|
|
|
|
if( *lpswzString == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Alloc failure" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
wcscpy( *lpswzString, wszTmpBuffer );
|
|
|
|
return DV_OK;
|
|
}
|
|
#else
|
|
char szTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
|
|
|
|
length = LoadStringA( hInstance, uiResourceID, szTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
|
|
|
|
if( length == 0 )
|
|
{
|
|
hr = GetLastError();
|
|
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load resource ID %d error 0x%x", uiResourceID, hr );
|
|
*lpswzString = NULL;
|
|
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
*lpswzString = new wchar_t[length+1];
|
|
|
|
if( *lpswzString == NULL )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Alloc failure" );
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
|
|
if( FAILED(STR_jkAnsiToWide( *lpswzString, szTmpBuffer, length+1 )) )
|
|
{
|
|
hr = GetLastError();
|
|
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to upconvert from ansi to unicode hr=0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
return DV_OK;
|
|
}
|
|
#endif // UNICODE
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CDPVACMI::GetCompressionNameAndDescription"
|
|
HRESULT CDPVACMI::GetCompressionNameAndDescription( HINSTANCE hInst, DVFULLCOMPRESSIONINFO *pdvCompressionInfo )
|
|
{
|
|
MMRESULT mmr;
|
|
HACMSTREAM has = NULL;
|
|
HACMDRIVERID acDriverID = NULL;
|
|
wchar_t szwDriverName[ACMDRIVERDETAILS_SHORTNAME_CHARS+DVACMCP_EXTRACHARS];
|
|
wchar_t szExtraCharsBuild[DVACMCP_EXTRACHARS+1];
|
|
wchar_t *szwFormat;
|
|
HRESULT hr;
|
|
|
|
// Description is always NULL
|
|
pdvCompressionInfo->lpszDescription = NULL;
|
|
|
|
// Attempt to open a conversion using the parameters specified.
|
|
mmr = acmStreamOpen( &has, NULL, &s_wfxInnerFormat, pdvCompressionInfo->lpwfxFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME );
|
|
|
|
if( mmr != 0 )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed testing compression type. mmr=0x%x", mmr );
|
|
hr = DVERR_COMPRESSIONNOTSUPPORTED;
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
mmr = acmDriverID( (HACMOBJ) has, &acDriverID, 0 );
|
|
|
|
if( mmr != 0 )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to determine ACM driver for type mmr=0x%x", mmr );
|
|
hr = DVERR_COMPRESSIONNOTSUPPORTED;
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
hr = GetDriverNameW( acDriverID, szwDriverName );
|
|
#else
|
|
hr = GetDriverNameA( acDriverID, szwDriverName );
|
|
#endif
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed getting driver name hr=0x%x", hr );
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
|
|
|
|
if( pdvCompressionInfo->dwMaxBitsPerSecond % 1000 == 0 )
|
|
{
|
|
if( FAILED( LoadAndAllocString( hInst, IDS_CODECNAME_KBITSPERSEC, &szwFormat ) ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load format for name" );
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
swprintf( szExtraCharsBuild, szwFormat, pdvCompressionInfo->dwMaxBitsPerSecond / 1000 );
|
|
delete [] szwFormat;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwMajor, dwFraction;
|
|
|
|
dwMajor = pdvCompressionInfo->dwMaxBitsPerSecond / 1000;
|
|
dwFraction = (pdvCompressionInfo->dwMaxBitsPerSecond % 1000) / 100;
|
|
|
|
if( (pdvCompressionInfo->dwMaxBitsPerSecond % 1000) > 500 )
|
|
{
|
|
dwFraction++;
|
|
}
|
|
|
|
if( dwFraction > 10 )
|
|
{
|
|
dwMajor++;
|
|
dwFraction -= 10;
|
|
}
|
|
|
|
if( FAILED( LoadAndAllocString( hInst, IDS_CODECNAME_KBITSPERSEC_FULL, &szwFormat ) ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load format for name (full)" );
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
swprintf( szExtraCharsBuild, szwFormat, dwMajor, dwFraction );
|
|
delete [] szwFormat;
|
|
}
|
|
|
|
if( FAILED( LoadAndAllocString( hInst, IDS_CODECNAME_FORMAT, &szwFormat ) ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load format" );
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
pdvCompressionInfo->lpszName = new wchar_t[wcslen(szwDriverName)+wcslen(szwFormat)+wcslen(szExtraCharsBuild)+1];
|
|
|
|
if( pdvCompressionInfo->lpszName == NULL )
|
|
{
|
|
delete [] szwFormat;
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to allocate space for compression name" );
|
|
hr = DVERR_OUTOFMEMORY;
|
|
goto GETINFOERROR;
|
|
}
|
|
|
|
swprintf( pdvCompressionInfo->lpszName, szwFormat, szwDriverName, szExtraCharsBuild );
|
|
|
|
acmStreamClose( has, 0 );
|
|
|
|
if( szwFormat != NULL )
|
|
delete [] szwFormat;
|
|
|
|
return DV_OK;
|
|
|
|
GETINFOERROR:
|
|
|
|
if( has != NULL )
|
|
{
|
|
acmStreamClose( has, 0 );
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|