📄 coreaac.cpp
字号:
/*
* CoreAAC - AAC DirectShow Decoder Filter
*
* Modification to decode AAC without ADTS and multichannel support
* (c) 2003 christophe.paris@free.fr
*
* Under section 8 of the GNU General Public License, the copyright
* holders of CoreAAC explicitly forbid distribution in the following
* countries:
* - Japan
* - United States of America
*
*
* AAC DirectShow Decoder Filter
* Copyright (C) 2003 Robert Cioch
*
* 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 2 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <windows.h>
#include <streams.h>
#include <initguid.h>
#include <olectl.h>
#include <transfrm.h>
#include <mmreg.h>
#include <ks.h>
#include <ksmedia.h>
#include <stdio.h>
#include "AACProfilesName.h"
#include "ICoreAAC.h"
#include "CoreAACGUID.h"
#include "CoreAACInfoProp.h"
#include "CoreAACAboutProp.h"
#include "CoreAAC.h"
// ============================================================================
// Registration setup stuff
AMOVIESETUP_MEDIATYPE sudInputType[] =
{
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_AAC }
};
AMOVIESETUP_MEDIATYPE sudOutputType[] =
{
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM }
};
AMOVIESETUP_PIN sudPins[] =
{
{ L"Input",
FALSE, // bRendered
FALSE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
NULL, // ConnectsToPin
NUMELMS(sudInputType), // Number of media types
sudInputType
},
{ L"Output",
FALSE, // bRendered
TRUE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
NULL, // ConnectsToPin
NUMELMS(sudOutputType), // Number of media types
sudOutputType
}
};
AMOVIESETUP_FILTER sudDecoder =
{
&CLSID_DECODER,
L"CoreAAC Audio Decoder",
MERIT_PREFERRED,
NUMELMS(sudPins),
sudPins
};
// ============================================================================
// COM Global table of objects in this dll
CFactoryTemplate g_Templates[] =
{
{ L"CoreAAC Audio Decoder", &CLSID_DECODER, CCoreAACDecoder::CreateInstance, NULL, &sudDecoder },
{ L"CoreAAC Audio Decoder Info", &CLSID_CoreAACInfoProp, CCoreAACInfoProp::CreateInstance, NULL, NULL},
{ L"CoreAAC Audio Decoder About", &CLSID_CoreAACAboutProp, CCoreAACAboutProp::CreateInstance, NULL, NULL},
};
// Count of objects listed in g_cTemplates
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
// ============================================================================
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
// ----------------------------------------------------------------------------
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
// ----------------------------------------------------------------------------
// The streams.h DLL entrypoint.
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
// The entrypoint required by the MSVC runtimes. This is used instead
// of DllEntryPoint directly to ensure global C++ classes get initialised.
BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) {
return DllEntryPoint(reinterpret_cast<HINSTANCE>(hDllHandle), dwReason, lpreserved);
}
// ----------------------------------------------------------------------------
CUnknown *WINAPI CCoreAACDecoder::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CCoreAACDecoder *pNewObject = new CCoreAACDecoder(punk, phr);
if (!pNewObject)
*phr = E_OUTOFMEMORY;
return pNewObject;
}
// ----------------------------------------------------------------------------
void SaveInt(char* keyname, int value)
{
HKEY hKey;
DWORD dwDisp;
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER,
"Software\\CoreAAC", 0, "REG_SZ",
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp))
{
DWORD dwSize = sizeof(DWORD);
RegSetValueEx(hKey, keyname, 0, REG_DWORD, (CONST BYTE*)&value, dwSize);
RegCloseKey(hKey);
}
}
int LoadInt(char* keyname, int default_value)
{
HKEY hKey;
int result = default_value;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
"Software\\CoreAAC", 0, KEY_READ, &hKey))
{
DWORD dwTmp = 0;
DWORD dwcbData = sizeof(DWORD);
if(RegQueryValueEx(hKey, keyname, NULL, NULL, (LPBYTE) &dwTmp, &dwcbData) == ERROR_SUCCESS)
{
result = dwTmp;
}
RegCloseKey(hKey);
}
return result;
}
// ----------------------------------------------------------------------------
CCoreAACDecoder::CCoreAACDecoder(LPUNKNOWN lpunk, HRESULT *phr) :
CTransformFilter(NAME("CoreAAC Audio Decoder"), lpunk, CLSID_DECODER),
m_decHandle(NULL),
m_decoderSpecificLen(0),
m_decoderSpecific(NULL),
m_Channels(0),
m_SamplesPerSec(0),
m_BitsPerSample(0),
m_Bitrate(0),
m_brCalcFrames(0),
m_brBytesConsumed(0),
m_DecodedFrames(0),
m_OutputBuffLen(0),
m_DownMatrix(false)
{
NOTE("CCoreAACDecoder::CCoreAACDecoder");
m_ProfileName[0] = '\0';
m_DownMatrix = LoadInt("DownMatrix", TRUE) ? true : false;
}
// ----------------------------------------------------------------------------
CCoreAACDecoder::~CCoreAACDecoder()
{
NOTE("CCoreAACDecoder::~CCoreAACDecoder");
SaveInt("DownMatrix",m_DownMatrix);
if(m_decHandle)
{
faacDecClose(m_decHandle);
m_decHandle = NULL;
}
if(m_decoderSpecific)
{
delete m_decoderSpecific;
m_decoderSpecific = NULL;
}
}
// ----------------------------------------------------------------------------
STDMETHODIMP CCoreAACDecoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
if(riid == IID_ICoreAACDec)
return GetInterface((ICoreAACDec *)this, ppv);
else if (riid == IID_ISpecifyPropertyPages)
return GetInterface((ISpecifyPropertyPages *)this, ppv);
else
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}
// ----------------------------------------------------------------------------
// property pages
STDMETHODIMP CCoreAACDecoder::GetPages(CAUUID *pPages)
{
pPages->cElems = 2;
pPages->pElems = (GUID *)CoTaskMemAlloc(pPages->cElems * sizeof(GUID));
if (!pPages->pElems)
return E_OUTOFMEMORY;
pPages->pElems[0] = CLSID_CoreAACInfoProp;
pPages->pElems[1] = CLSID_CoreAACAboutProp;
return S_OK;
}
// ============================================================================
// accept only aac audio wrapped in waveformat
HRESULT CCoreAACDecoder::CheckInputType(const CMediaType *mtIn)
{
if (*mtIn->Type() != MEDIATYPE_Audio || *mtIn->Subtype() != MEDIASUBTYPE_AAC)
return VFW_E_TYPE_NOT_ACCEPTED;
if (*mtIn->FormatType() != FORMAT_WaveFormatEx)
return VFW_E_TYPE_NOT_ACCEPTED;
WAVEFORMATEX *wfex = (WAVEFORMATEX *)mtIn->Format();
if (wfex->wFormatTag != WAVE_FORMAT_AAC)
return VFW_E_TYPE_NOT_ACCEPTED;
if(wfex->cbSize < 2)
return VFW_E_TYPE_NOT_ACCEPTED;
m_decoderSpecificLen = wfex->cbSize;
if(m_decoderSpecific)
{
delete m_decoderSpecific;
m_decoderSpecific = NULL;
}
m_decoderSpecific = new unsigned char[m_decoderSpecificLen];
// Keep decoderSpecific initialization data (appended to the WAVEFORMATEX struct)
memcpy(m_decoderSpecific,(char*)wfex+sizeof(WAVEFORMATEX), m_decoderSpecificLen);
return S_OK;
}
// ============================================================================
// propose proper waveformat
HRESULT CCoreAACDecoder::GetMediaType(int iPosition, CMediaType *mtOut)
{
if (!m_pInput->IsConnected())
{
return E_UNEXPECTED;
}
if (iPosition < 0)
{
return E_INVALIDARG;
}
if (iPosition > 0)
{
return VFW_S_NO_MORE_ITEMS;
}
// Some drivers don't like WAVEFORMATEXTENSIBLE when channels are <= 2 so
// we fall back to a classic WAVEFORMATEX struct in this case
WAVEFORMATEXTENSIBLE wfex;
ZeroMemory(&wfex, sizeof(WAVEFORMATEXTENSIBLE));
wfex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
wfex.Format.wFormatTag = (m_Channels <= 2) ? WAVE_FORMAT_PCM : WAVE_FORMAT_EXTENSIBLE;
wfex.Format.cbSize = (m_Channels <= 2) ? 0 : sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
wfex.Format.nChannels = (unsigned short)m_Channels;
wfex.Format.nSamplesPerSec = (unsigned short)m_SamplesPerSec;
wfex.Format.wBitsPerSample = m_BitsPerSample;
wfex.Format.nBlockAlign = (unsigned short)((wfex.Format.nChannels * wfex.Format.wBitsPerSample) / 8);
wfex.Format.nAvgBytesPerSec = wfex.Format.nSamplesPerSec * wfex.Format.nBlockAlign;
switch(m_Channels)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -