📄 codec.cpp
字号:
#include "codec.h"
#include <assert.h>
// we must register these by emailing to mmreg@microsoft.com
const int codec::m_iCompressedFormatTag = 0x1234;
const int codec::m_iManufacturerID = MM_GADGETLABS;
const int codec::m_iProductID = 7;
const wchar_t g_sCodecName[]=L"MPEG-2/4 AAC audio codec";
const wchar_t g_sLongCodecName[]=L"Very special audio codec";
const wchar_t g_sFormatName[]=L"MPEG-2/4 AAC";
codec::codec()
{
}
codec::~codec()
{
}
HRESULT codec::formattag_details(ACMFORMATTAGDETAILSW* lParam1, DWORD lParam2)
{
bool bCompressedFormat;
switch(lParam2)
{
case ACM_FORMATTAGDETAILSF_INDEX:
if(lParam1->dwFormatTagIndex>=2)
return ACMERR_NOTPOSSIBLE;
bCompressedFormat=(lParam1->dwFormatTagIndex==1);
break;
case ACM_FORMATTAGDETAILSF_FORMATTAG:
if(lParam1->dwFormatTag==1)
bCompressedFormat=false;
else if(lParam1->dwFormatTag==m_iCompressedFormatTag)
bCompressedFormat=true;
else
return ACMERR_NOTPOSSIBLE;
case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
bCompressedFormat=true;
break;
default:
return ACMERR_NOTPOSSIBLE;
}
lParam1->cbStruct=sizeof(ACMFORMATTAGDETAILSW);
lParam1->cbFormatSize=bCompressedFormat ? 20 : 16;
lParam1->fdwSupport=ACMDRIVERDETAILS_SUPPORTF_CODEC;
if(bCompressedFormat)
lParam1->cStandardFormats=8; // 44 & 48 khz 16 bit, mono & stereo, 64 & 128 kbps
else
lParam1->cStandardFormats=8; // 44 & 48 khz 8 & 16 bit, mono & stereo
if(bCompressedFormat)
{
wcscpy(lParam1->szFormatTag, g_sFormatName);
lParam1->dwFormatTag=m_iCompressedFormatTag;
}
else
{
wcscpy(lParam1->szFormatTag, L"PCM");
lParam1->dwFormatTag=1;
}
return MMSYSERR_NOERROR;
}
void codec::fill_pcm_format(WAVEFORMATEX* pwfx, int rate, int bits, int channels)
{
pwfx->wFormatTag=1;
pwfx->nSamplesPerSec=rate;
pwfx->wBitsPerSample=bits;
pwfx->nChannels=channels;
pwfx->nAvgBytesPerSec=rate * bits * channels / 8;
pwfx->nBlockAlign=channels * bits / 8;
pwfx->cbSize=0;
}
#define MAIN 0
#define LOW 1
#define SSR 2
#define LTP 3
static unsigned int aacSamplingRates[16] = {
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 7350, 0, 0, 0
};
void codec::fill_compressed_format(WAVEFORMATEX* pwfx, int rate, int bits, int channels, int bitrate)
{
pwfx->wFormatTag=m_iCompressedFormatTag;
pwfx->nSamplesPerSec=rate;
pwfx->wBitsPerSample=bits;
pwfx->nChannels=channels;
pwfx->nAvgBytesPerSec=bitrate / 8;
pwfx->nBlockAlign=1024;
pwfx->cbSize=2;
unsigned char* ext=(unsigned char*)(&pwfx[1]);
int profile = MAIN;
int samplerate_index=-1;
for(int i=0; i<16; i++)
if(aacSamplingRates[i]==rate)
{
samplerate_index=i;
break;
}
if(samplerate_index<0)
return;
ext[0] = ((profile + 1) << 3) | ((samplerate_index & 0xe) >> 1);
ext[1] = ((samplerate_index & 0x1) << 7) | (channels << 3);
// 960 byte frames not used
}
HRESULT codec::format_details(ACMFORMATDETAILSW* lParam1, DWORD lParam2)
{
lParam1->cbStruct=sizeof(ACMFORMATDETAILSW);
lParam1->szFormat[0]=0;
lParam1->fdwSupport=ACMDRIVERDETAILS_SUPPORTF_CODEC;
if(lParam1->dwFormatTag==1)
{
if(lParam2==ACM_FORMATDETAILSF_INDEX)
{
switch(lParam1->dwFormatIndex)
{
case 0:
fill_pcm_format(lParam1->pwfx, 44100, 16, 1);
break;
case 1:
fill_pcm_format(lParam1->pwfx, 44100, 16, 2);
break;
case 2:
fill_pcm_format(lParam1->pwfx, 44100, 8, 1);
break;
case 3:
fill_pcm_format(lParam1->pwfx, 44100, 8, 2);
break;
case 4:
fill_pcm_format(lParam1->pwfx, 48000, 16, 1);
break;
case 5:
fill_pcm_format(lParam1->pwfx, 48000, 16, 2);
break;
case 6:
fill_pcm_format(lParam1->pwfx, 48000, 8, 1);
break;
case 7:
fill_pcm_format(lParam1->pwfx, 48000, 8, 2);
break;
default:
return ACMERR_NOTPOSSIBLE;
}
}
else if(lParam2==ACM_FORMATDETAILSF_FORMAT)
{
if((lParam1->pwfx->nSamplesPerSec != 44100) && (lParam1->pwfx->nSamplesPerSec != 48000))
return ACMERR_NOTPOSSIBLE;
}
else
return ACMERR_NOTPOSSIBLE;
}
else if(lParam1->dwFormatTag==m_iCompressedFormatTag)
{
if(lParam2==ACM_FORMATDETAILSF_INDEX)
{
switch(lParam1->dwFormatIndex)
{
case 0:
fill_compressed_format(lParam1->pwfx, 44100, 16, 1, 128000);
break;
case 1:
fill_compressed_format(lParam1->pwfx, 44100, 16, 2, 128000);
break;
case 2:
fill_compressed_format(lParam1->pwfx, 44100, 16, 1, 64000);
break;
case 3:
fill_compressed_format(lParam1->pwfx, 44100, 16, 2, 64000);
break;
case 4:
fill_compressed_format(lParam1->pwfx, 48000, 16, 1, 128000);
break;
case 5:
fill_compressed_format(lParam1->pwfx, 48000, 16, 2, 128000);
break;
case 6:
fill_compressed_format(lParam1->pwfx, 48000, 16, 1, 64000);
break;
case 7:
fill_compressed_format(lParam1->pwfx, 48000, 16, 2, 64000);
break;
default:
return ACMERR_NOTPOSSIBLE;
}
}
else if(lParam2==ACM_FORMATDETAILSF_FORMAT)
{
if((lParam1->pwfx->nSamplesPerSec != 44100) && (lParam1->pwfx->nSamplesPerSec != 48000))
return ACMERR_NOTPOSSIBLE;
}
else
return ACMERR_NOTPOSSIBLE;
}
else
return ACMERR_NOTPOSSIBLE;
return MMSYSERR_NOERROR;
}
HRESULT codec::format_suggest(ACMDRVFORMATSUGGEST* pFormat)
{
bool bEncode;
if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)
{
if((pFormat->pwfxDst->wFormatTag == 1) && (pFormat->pwfxSrc->wFormatTag == m_iCompressedFormatTag))
bEncode=false;
else
if((pFormat->pwfxDst->wFormatTag == m_iCompressedFormatTag) && (pFormat->pwfxSrc->wFormatTag == 1))
bEncode=true;
else
return ACMERR_NOTPOSSIBLE;
}
else
{
if(pFormat->pwfxSrc->wFormatTag == m_iCompressedFormatTag)
{
pFormat->pwfxDst->wFormatTag=1;
bEncode=false;
}
else
if(pFormat->pwfxSrc->wFormatTag == 1)
{
pFormat->pwfxDst->wFormatTag=m_iCompressedFormatTag;
bEncode=true;
}
else
return ACMERR_NOTPOSSIBLE;
}
if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)
{
if(pFormat->pwfxDst->nChannels != pFormat->pwfxSrc->nChannels)
return ACMERR_NOTPOSSIBLE;
}
int iChannels = pFormat->pwfxSrc->nChannels;
if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)
{
if(pFormat->pwfxDst->nSamplesPerSec != pFormat->pwfxSrc->nSamplesPerSec)
return ACMERR_NOTPOSSIBLE;
}
int iSamplesPerSec = pFormat->pwfxSrc->nSamplesPerSec;
if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)
{
if(pFormat->pwfxDst->wBitsPerSample != pFormat->pwfxSrc->wBitsPerSample)
return ACMERR_NOTPOSSIBLE;
}
int iBitsPerSample = pFormat->pwfxSrc->wBitsPerSample;
if(bEncode)
fill_compressed_format(pFormat->pwfxDst, iSamplesPerSec, iBitsPerSample, iChannels, 128000);
else
fill_pcm_format(pFormat->pwfxDst, iSamplesPerSec, iBitsPerSample, iChannels);
return MMSYSERR_NOERROR;
}
HRESULT codec::details(ACMDRIVERDETAILSW* pDetails)
{
memset(pDetails, 0, sizeof(ACMDRIVERDETAILSW));
pDetails->cbStruct=sizeof(ACMDRIVERDETAILSW);
pDetails->fccType=ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
pDetails->fccComp=ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
pDetails->wMid=m_iManufacturerID;
pDetails->wPid=m_iProductID;
pDetails->vdwACM=0x3320000;
pDetails->vdwDriver=0x1000000;
pDetails->fdwSupport=ACMDRIVERDETAILS_SUPPORTF_CODEC;
pDetails->cFormatTags=2;
pDetails->cFilterTags=0;
wcscpy(pDetails->szShortName, g_sCodecName);
wcscpy(pDetails->szLongName, g_sLongCodecName);
return MMSYSERR_NOERROR;
}
HRESULT codec::about(DWORD h)
{
if(h==(DWORD)-1)
return MMSYSERR_NOERROR;
MessageBoxW((HWND)h, g_sLongCodecName, L"About", MB_OK);
return MMSYSERR_NOERROR;
}
HRESULT codec::open(ACMDRVSTREAMINSTANCE* pStream)
{
if(pStream->pwfxDst->nChannels != pStream->pwfxSrc->nChannels)
return ACMERR_NOTPOSSIBLE;
if(pStream->pwfxDst->nSamplesPerSec != pStream->pwfxSrc->nSamplesPerSec)
return ACMERR_NOTPOSSIBLE;
bool bDecode = (pStream->pwfxDst->wFormatTag == 1);
if(bDecode)
{
if(pStream->pwfxDst->wBitsPerSample!=16)
return ACMERR_NOTPOSSIBLE;
if(pStream->pwfxSrc->wFormatTag!=m_iCompressedFormatTag)
return ACMERR_NOTPOSSIBLE;
}
else
{
// if(pStream->pwfxSrc->wBitsPerSample!=16)
// return ACMERR_NOTPOSSIBLE;
if(pStream->pwfxDst->wFormatTag!=m_iCompressedFormatTag)
return ACMERR_NOTPOSSIBLE;
if(pStream->pwfxSrc->wFormatTag!=1)
return ACMERR_NOTPOSSIBLE;
}
if(pStream->fdwOpen & ACM_STREAMOPENF_QUERY)
return MMSYSERR_NOERROR;
if(bDecode)
pStream->dwDriver=(DWORD)new decoder(pStream->pwfxSrc);
else
pStream->dwDriver=(DWORD)new encoder(pStream->pwfxSrc, pStream->pwfxDst);
return MMSYSERR_NOERROR;
}
HRESULT codec::prepare(ACMDRVSTREAMINSTANCE* pStream, ACMDRVSTREAMHEADER* pHeader)
{
return MMSYSERR_NOTSUPPORTED;
}
HRESULT codec::reset(ACMDRVSTREAMINSTANCE* pStream)
{
stream* pstr=(stream*)pStream->dwDriver;
return pstr->reset();
}
HRESULT codec::size(ACMDRVSTREAMINSTANCE* pStream, ACMDRVSTREAMSIZE* pSize)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -