⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aacdecoder.cpp

📁 自己整理的一个AAC解码器,可以在EVC下跑的
💻 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 + -