📄 aacdecoder.cpp
字号:
/*
* HDX4 AAC Decoder - Copyright (C) 2005 Jomigo GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//-------------------------------------------------------------------------------------------------------//
// AACDecoder.cpp : AAC DirectShow Decoder Filter
//-------------------------------------------------------------------------------------------------------//
#include "StdAfx.h"
#include <streams.h>
#include <initguid.h>
//#include <ks.h>
//#include <ksmedia.h>
#include <math.h>
#include "AACDecoder.h"
//-------------------------------------------------------------------------------------------------------//
// DLLEntryPoint
//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/buildingdirectshowfilters.asp
//-------------------------------------------------------------------------------------------------------//
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
//-------------------------------------------------------------------------------------------------------//
// NonDelegatingQueryInterface
//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/usingcunknown.asp
//-------------------------------------------------------------------------------------------------------//
STDMETHODIMP CAACDecoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}
//-------------------------------------------------------------------------------------------------------//
// CreateInstance
//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/step6addsupportforcom.asp
//-------------------------------------------------------------------------------------------------------//
CUnknown *WINAPI CAACDecoder::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CAACDecoder *pNewObject = new CAACDecoder(punk, phr);
if (!pNewObject)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}
//-------------------------------------------------------------------------------------------------------//
// Declare Filter Information
//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/declarefilterinformation.asp
//-------------------------------------------------------------------------------------------------------//
AMOVIESETUP_MEDIATYPE sudMediaInputType[] = {
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_AAC_AUDIO },
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_AAC },
} ;
AMOVIESETUP_MEDIATYPE sudMediaOutputType[] = { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM };
AMOVIESETUP_PIN sudPins[] =
{
{ L"In",
FALSE,
FALSE,
FALSE,
FALSE,
&CLSID_NULL,
NULL,
2,
sudMediaInputType
},
{ L"Out",
FALSE,
TRUE,
FALSE,
FALSE,
&CLSID_NULL,
NULL,
1,
sudMediaOutputType
}
};
AMOVIESETUP_FILTER sudFilterReg =
{
&CLSID_AACDECODER,
L"AAC4DS AAC Decoder",
MERIT_NORMAL,
2,
sudPins
};
//-------------------------------------------------------------------------------------------------------//
// Declare Factory Template
//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/declarethefactorytemplate.asp
//-------------------------------------------------------------------------------------------------------//
CFactoryTemplate g_Templates[] =
{
L"AAC4DS AAC Decoder",
&CLSID_AACDECODER,
CAACDecoder::CreateInstance,
NULL,
&sudFilterReg
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
//-------------------------------------------------------------------------------------------------------//
// DllRegisterServer and DllUnregisterServer
//
// Link: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/dllfunctions.asp
//-------------------------------------------------------------------------------------------------------//
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
//-------------------------------------------------------------------------------------------------------//
// CTransformFilter Methods
//-------------------------------------------------------------------------------------------------------//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/step3aimplementthecheckinputtypemethod.asp
HRESULT CAACDecoder::CheckInputType(const CMediaType *pmtIn)
{
if( (*pmtIn->Type() != MEDIATYPE_Audio) ||
((*pmtIn->Subtype() != MEDIASUBTYPE_AAC_AUDIO) && (*pmtIn->Subtype() != MEDIASUBTYPE_AAC))
)
{
return VFW_E_TYPE_NOT_ACCEPTED;
}
WAVEFORMATEX *pInputFormat = (WAVEFORMATEX *)pmtIn->Format();
m_nSamplesPerSec = pInputFormat->nSamplesPerSec;
m_nBitsPerSample = pInputFormat->wBitsPerSample;
m_nChannels = pInputFormat->nChannels;
m_nESConfigSize = pInputFormat->cbSize;
if((!m_pbESConfiguration) && m_nESConfigSize)
{
m_pbESConfiguration = new BYTE [m_nESConfigSize];
memcpy(m_pbESConfiguration,(char*) pInputFormat + sizeof(WAVEFORMATEX), m_nESConfigSize);
}
return S_OK;
}
//-------------------------------------------------------------------------------------------------------//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/step3cimplementthechecktransformmethod.asp
HRESULT CAACDecoder::CheckTransform(const CMediaType *pmtIn, const CMediaType *pmtOut)
{
if ((*pmtOut->Type() != MEDIATYPE_Audio) || (*pmtOut->Subtype() != MEDIASUBTYPE_PCM))
{
return VFW_E_TYPE_NOT_ACCEPTED;
}
return S_OK;
}
//-------------------------------------------------------------------------------------------------------//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/step4setallocatorproperties.asp
HRESULT CAACDecoder::DecideBufferSize(IMemAllocator *pAllocator, ALLOCATOR_PROPERTIES *pProperties)
{
pProperties->cBuffers = 1;
pProperties->cbBuffer = 4 * 8 * m_nChannels * 1024;
HRESULT hr;
ALLOCATOR_PROPERTIES alloc;
if((hr = pAllocator->SetProperties(pProperties, &alloc)) < 0)
return hr ;
if (alloc.cbBuffer < pProperties->cbBuffer)
return E_FAIL ;
return S_OK;
}
//-------------------------------------------------------------------------------------------------------//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/step3bimplementthegetmediatypemethod.asp
HRESULT CAACDecoder::GetMediaType(int iPosition, CMediaType *pmtOut)
{
if (!m_pInput->IsConnected())
{
return E_UNEXPECTED;
}
if (iPosition < 0)
{
return E_INVALIDARG;
}
if (iPosition == 0)
{
WAVEFORMATEX *pFmt = NULL, *pFmtIn = NULL;
CheckPointer(pmtOut,E_POINTER);
CMediaType &objCurrMedia = m_pInput->CurrentMediaType();
ASSERT(objCurrMedia.formattype == FORMAT_WaveFormatEx);
pFmtIn = (WAVEFORMATEX *)objCurrMedia.pbFormat; //FORMAT_VideoInfo
pmtOut->SetType(&MEDIATYPE_Audio);
pmtOut->SetSubtype(&MEDIASUBTYPE_PCM);
pmtOut->SetFormatType(&FORMAT_WaveFormatEx);
/* 说明:如果没有在这里分配内存或相关其他地方进行处理的话,会导致过滤器构造出
现异常的,这点非常重要 // */
pFmt = (WAVEFORMATEX *)pmtOut->AllocFormatBuffer(sizeof(WAVEFORMATEX));
pFmt->cbSize = sizeof(WAVEFORMATEX);
pFmt->wFormatTag = WAVE_FORMAT_PCM;
pFmt->nChannels = m_nChannels;//pFmtIn->nChannels;
pFmt->nSamplesPerSec = pFmtIn->nSamplesPerSec; //44100;//记录每秒取样的次数
pFmt->wBitsPerSample = 16;//pFmtIn->wBitsPerSample; //记录每个取样所需的bit数
int m_iBytesOneSample = pFmt->wBitsPerSample / 2;
pFmt->nBlockAlign = pFmt->wBitsPerSample * pFmt->nChannels / 8; //要求这样计算的
pFmt->nAvgBytesPerSec = pFmt->nBlockAlign * pFmt->nSamplesPerSec;//
if(pFmt->nAvgBytesPerSec <= 0) //保护一下
{
pFmt->nAvgBytesPerSec = PCM_FRAME_SIZE;
}
return S_OK;
}
if (iPosition > 0)
{
return VFW_S_NO_MORE_ITEMS;
}
return S_OK;
}
//-------------------------------------------------------------------------------------------------------//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/step5transformtheimage.asp
HRESULT CAACDecoder::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
BYTE *pInput = NULL;
BYTE *pOutput = NULL;
if (pIn->GetPointer (&pInput) != S_OK) return S_OK;
if (pOut->GetPointer(&pOutput) != S_OK) return S_OK;
if(!m_hDecoder)
{
m_hDecoder = faacDecOpen();
faacDecConfigurationPtr config = faacDecGetCurrentConfiguration(m_hDecoder);
unsigned long nSamplesPerSecInit2 = 0;
unsigned long nChannelsInit2 = 0;
if(NULL == m_pbESConfiguration && NULL != pInput)
{
m_nESConfigSize = 2;
m_pbESConfiguration = new BYTE [m_nESConfigSize];
memcpy(m_pbESConfiguration,(char*) pInput, m_nESConfigSize);
}
if(faacDecInit2(m_hDecoder, m_pbESConfiguration, m_nESConfigSize, &nSamplesPerSecInit2, &nChannelsInit2) < 0)
{
unsigned long nSamplesPerSec = 0;
unsigned long nChannels = 0;
if((faacDecInit(m_hDecoder, m_pbESConfiguration, &nSamplesPerSec, &nChannels)) < 0)
{
return E_FAIL;
}
}
m_nChannels = nChannelsInit2;
// m_nChannels = 2;
config->defSampleRate = nSamplesPerSecInit2;
faacDecSetConfiguration(m_hDecoder, config);
}
DWORD dwSrcLength = pIn->GetActualDataLength();
DWORD dwDstLength = pOut->GetSize();
if(!m_pBuffer)
{
m_pBuffer = new BYTE [4 * 8 * m_nChannels * 1024];
}
short *psPCMSamples = (short*) m_pBuffer;
int nResult = 0;
int loopResult = 0;
int UsedBytes = 0;
int OutputsampleCount = 0;
unsigned long ulUsedBytes = 0;
unsigned long ulOutputsampleCount = 0;
// AAC Decoder Loop
while(UsedBytes < dwSrcLength)
{
loopResult = faacDecDecode(m_hDecoder, (unsigned char*) ((BYTE*)pInput + UsedBytes),
&ulUsedBytes, psPCMSamples+OutputsampleCount, &ulOutputsampleCount);
if (loopResult == FAAD_FATAL_ERROR)
{
return S_FALSE;
}
UsedBytes += ulUsedBytes;
OutputsampleCount += ulOutputsampleCount;
nResult += loopResult;
}
int sample, ch;
short *pBuffer = (short*)pOutput;
// faad1 Sample-Order : Center, Left, Right, Left-Rear, Right-Rear, Subwoofer
// DirectShow-Order : Left, Right, Center, Subwoofer, Left-Rear, Right-Rear
if(MixDown && (m_nChannels >= 3))
{
for(sample = 0; sample < OutputsampleCount; sample += m_nChannels)
{
for(int ch = 0; ch < m_nChannels; ch++)
{
// 1/2Volume * ( 1Volume Center + 1/2Volume Left + 1/2Volume Right ) = 1Volume Mono
// (we use sqrt2, (Peak * 1/sqrt2) is the Effective Value of a Sinus formed Signal)
*pBuffer++ = (1.0/(1.0+sqrtf(2.0))) * (psPCMSamples[0] + psPCMSamples[1]/sqrtf(2.0) + psPCMSamples[2]/sqrtf(2.0));
}
psPCMSamples += m_nChannels;
}
}
else
{
switch(m_nChannels)
{
case 1: // Mono
case 2: // Stereo
memcpy(pOutput, psPCMSamples, OutputsampleCount * m_nChannels * sizeof(short));
break;
case 3: // 2.1
for(sample = 0; sample < OutputsampleCount; sample += m_nChannels)
{
int ChannelMap[3] = {2,3,1};
for(int ch = 0; ch < m_nChannels; ch++)
{
*pBuffer++ = psPCMSamples[ChannelMap[ch]-1];
}
psPCMSamples += m_nChannels;
}
break;
case 4: // Quad
for(sample = 0; sample < OutputsampleCount; sample += m_nChannels)
{
int ChannelMap[4] = {2,3,1,4};
for(int ch = 0; ch < m_nChannels; ch++)
{
*pBuffer++ = psPCMSamples[ChannelMap[ch]-1];
}
psPCMSamples += m_nChannels;
}
break;
case 5: // Surround
for(sample = 0; sample < OutputsampleCount; sample += m_nChannels)
{
int ChannelMap[5] = {2,3,1,4,5};
for(int ch = 0; ch < m_nChannels; ch++)
{
*pBuffer++ = psPCMSamples[ChannelMap[ch]-1];
}
psPCMSamples += m_nChannels;
}
break;
case 6: // 5.1
for(sample = 0; sample < OutputsampleCount; sample += m_nChannels)
{
int ChannelMap[6] = {2,3,1,6,4,5};
for(int ch = 0; ch < m_nChannels; ch++)
{
*pBuffer++ = psPCMSamples[ChannelMap[ch]-1];
}
psPCMSamples += m_nChannels;
}
break;
}
}
DWORD dwActualDstLength = OutputsampleCount * sizeof(short);//ulOutputsampleCount
pOut->SetActualDataLength(dwActualDstLength);
return S_OK;
}
extern AMOVIESETUP_FILTER g_sttSudFilter;
/***************************************************************************************
函数名: GetSetupData
返回值:
1.NULL -- 失败
2.其他 -- 首地址
功 能:
1.加载一个媒体文件
参 数:
1.无
说 明:
1.重载虚函数
创建者: 罗清胜(2006-06-08 22:09)
***************************************************************************************/
LPAMOVIESETUP_FILTER CAACDecoder::GetSetupData()
{
return &sudFilterReg;
}
//-------------------------------------------------------------------------------------------------------//
// CONSTRUCTOR / DESTRUCTOR
//-------------------------------------------------------------------------------------------------------//
CAACDecoder::CAACDecoder(LPUNKNOWN lpunk, HRESULT *phr)
: CTransformFilter(NAME("HDX4 AAC Decoder"), lpunk, CLSID_AACDECODER)
{
m_pBuffer = NULL;
m_hDecoder = NULL;
m_nESConfigSize = 0;
m_pbESConfiguration = NULL;
m_nChannels = 0;
m_nSamplesPerSec = 0;
m_nBitsPerSample = 0;
MixDown = false;
}
//-------------------------------------------------------------------------------------------------------//
CAACDecoder::~CAACDecoder()
{
if(m_pBuffer) delete m_pBuffer;
if(m_hDecoder) faacDecClose(m_hDecoder);
if(m_pbESConfiguration) delete m_pbESConfiguration;
}
//-------------------------------------------------------------------------------------------------------//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -