2
* CoreAAC - AAC DirectShow Decoder Filter
4
* Modification to decode AAC without ADTS and multichannel support
5
* (c) 2003 christophe.paris@free.fr
7
* Under section 8 of the GNU General Public License, the copyright
8
* holders of CoreAAC explicitly forbid distribution in the following
11
* - United States of America
14
* AAC DirectShow Decoder Filter
15
* Copyright (C) 2003 Robert Cioch
17
* This program is free software; you can redistribute it and/or modify
18
* it under the terms of the GNU General Public License as published by
19
* the Free Software Foundation; either version 2 of the License, or
20
* (at your option) any later version.
22
* This program is distributed in the hope that it will be useful,
23
* but WITHOUT ANY WARRANTY; without even the implied warranty of
24
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
* GNU General Public License for more details.
27
* You should have received a copy of the GNU General Public License
28
* along with this program; if not, write to the Free Software
29
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46
#include "AACProfilesName.h"
48
#include "CoreAACGUID.h"
49
#include "CoreAACInfoProp.h"
50
#include "CoreAACAboutProp.h"
53
// ============================================================================
54
// Registration setup stuff
56
AMOVIESETUP_MEDIATYPE sudInputType[] =
58
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_AAC }
61
AMOVIESETUP_MEDIATYPE sudOutputType[] =
63
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM }
66
AMOVIESETUP_PIN sudPins[] =
73
&CLSID_NULL, // clsConnectsToFilter
74
NULL, // ConnectsToPin
75
NUMELMS(sudInputType), // Number of media types
83
&CLSID_NULL, // clsConnectsToFilter
84
NULL, // ConnectsToPin
85
NUMELMS(sudOutputType), // Number of media types
90
AMOVIESETUP_FILTER sudDecoder =
93
L"CoreAAC Audio Decoder",
99
// ============================================================================
100
// COM Global table of objects in this dll
102
CFactoryTemplate g_Templates[] =
104
{ L"CoreAAC Audio Decoder", &CLSID_DECODER, CCoreAACDecoder::CreateInstance, NULL, &sudDecoder },
105
{ L"CoreAAC Audio Decoder Info", &CLSID_CoreAACInfoProp, CCoreAACInfoProp::CreateInstance, NULL, NULL},
106
{ L"CoreAAC Audio Decoder About", &CLSID_CoreAACAboutProp, CCoreAACAboutProp::CreateInstance, NULL, NULL},
109
// Count of objects listed in g_cTemplates
110
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
112
// ============================================================================
114
STDAPI DllRegisterServer()
116
return AMovieDllRegisterServer2(TRUE);
119
// ----------------------------------------------------------------------------
121
STDAPI DllUnregisterServer()
123
return AMovieDllRegisterServer2(FALSE);
126
// ----------------------------------------------------------------------------
128
// The streams.h DLL entrypoint.
129
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
131
// The entrypoint required by the MSVC runtimes. This is used instead
132
// of DllEntryPoint directly to ensure global C++ classes get initialised.
133
BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) {
135
return DllEntryPoint(reinterpret_cast<HINSTANCE>(hDllHandle), dwReason, lpreserved);
138
// ----------------------------------------------------------------------------
140
CUnknown *WINAPI CCoreAACDecoder::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
142
CCoreAACDecoder *pNewObject = new CCoreAACDecoder(punk, phr);
144
*phr = E_OUTOFMEMORY;
148
// ----------------------------------------------------------------------------
150
void SaveInt(char* keyname, int value)
154
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER,
155
"Software\\CoreAAC", 0, "REG_SZ",
156
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp))
158
DWORD dwSize = sizeof(DWORD);
159
RegSetValueEx(hKey, keyname, 0, REG_DWORD, (CONST BYTE*)&value, dwSize);
164
int LoadInt(char* keyname, int default_value)
167
int result = default_value;
169
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
170
"Software\\CoreAAC", 0, KEY_READ, &hKey))
173
DWORD dwcbData = sizeof(DWORD);
174
if(RegQueryValueEx(hKey, keyname, NULL, NULL, (LPBYTE) &dwTmp, &dwcbData) == ERROR_SUCCESS)
183
// ----------------------------------------------------------------------------
185
CCoreAACDecoder::CCoreAACDecoder(LPUNKNOWN lpunk, HRESULT *phr) :
186
CTransformFilter(NAME("CoreAAC Audio Decoder"), lpunk, CLSID_DECODER),
188
m_decoderSpecificLen(0),
189
m_decoderSpecific(NULL),
195
m_brBytesConsumed(0),
200
NOTE("CCoreAACDecoder::CCoreAACDecoder");
202
m_ProfileName[0] = '\0';
203
m_DownMatrix = LoadInt("DownMatrix", TRUE) ? true : false;
206
// ----------------------------------------------------------------------------
208
CCoreAACDecoder::~CCoreAACDecoder()
210
NOTE("CCoreAACDecoder::~CCoreAACDecoder");
212
SaveInt("DownMatrix",m_DownMatrix);
216
faacDecClose(m_decHandle);
219
if(m_decoderSpecific)
221
delete m_decoderSpecific;
222
m_decoderSpecific = NULL;
226
// ----------------------------------------------------------------------------
228
STDMETHODIMP CCoreAACDecoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
230
if(riid == IID_ICoreAACDec)
231
return GetInterface((ICoreAACDec *)this, ppv);
232
else if (riid == IID_ISpecifyPropertyPages)
233
return GetInterface((ISpecifyPropertyPages *)this, ppv);
235
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
238
// ----------------------------------------------------------------------------
241
STDMETHODIMP CCoreAACDecoder::GetPages(CAUUID *pPages)
244
pPages->pElems = (GUID *)CoTaskMemAlloc(pPages->cElems * sizeof(GUID));
246
return E_OUTOFMEMORY;
248
pPages->pElems[0] = CLSID_CoreAACInfoProp;
249
pPages->pElems[1] = CLSID_CoreAACAboutProp;
254
// ============================================================================
255
// accept only aac audio wrapped in waveformat
257
HRESULT CCoreAACDecoder::CheckInputType(const CMediaType *mtIn)
259
if (*mtIn->Type() != MEDIATYPE_Audio || *mtIn->Subtype() != MEDIASUBTYPE_AAC)
260
return VFW_E_TYPE_NOT_ACCEPTED;
262
if (*mtIn->FormatType() != FORMAT_WaveFormatEx)
263
return VFW_E_TYPE_NOT_ACCEPTED;
265
WAVEFORMATEX *wfex = (WAVEFORMATEX *)mtIn->Format();
266
if (wfex->wFormatTag != WAVE_FORMAT_AAC)
267
return VFW_E_TYPE_NOT_ACCEPTED;
270
return VFW_E_TYPE_NOT_ACCEPTED;
272
m_decoderSpecificLen = wfex->cbSize;
273
if(m_decoderSpecific)
275
delete m_decoderSpecific;
276
m_decoderSpecific = NULL;
278
m_decoderSpecific = new unsigned char[m_decoderSpecificLen];
280
// Keep decoderSpecific initialization data (appended to the WAVEFORMATEX struct)
281
memcpy(m_decoderSpecific,(char*)wfex+sizeof(WAVEFORMATEX), m_decoderSpecificLen);
286
// ============================================================================
287
// propose proper waveformat
289
HRESULT CCoreAACDecoder::GetMediaType(int iPosition, CMediaType *mtOut)
291
if (!m_pInput->IsConnected())
303
return VFW_S_NO_MORE_ITEMS;
306
// Some drivers don't like WAVEFORMATEXTENSIBLE when channels are <= 2 so
307
// we fall back to a classic WAVEFORMATEX struct in this case
309
WAVEFORMATEXTENSIBLE wfex;
310
ZeroMemory(&wfex, sizeof(WAVEFORMATEXTENSIBLE));
312
wfex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
313
wfex.Format.wFormatTag = (m_Channels <= 2) ? WAVE_FORMAT_PCM : WAVE_FORMAT_EXTENSIBLE;
314
wfex.Format.cbSize = (m_Channels <= 2) ? 0 : sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
315
wfex.Format.nChannels = (unsigned short)m_Channels;
316
wfex.Format.nSamplesPerSec = (unsigned short)m_SamplesPerSec;
317
wfex.Format.wBitsPerSample = m_BitsPerSample;
318
wfex.Format.nBlockAlign = (unsigned short)((wfex.Format.nChannels * wfex.Format.wBitsPerSample) / 8);
319
wfex.Format.nAvgBytesPerSec = wfex.Format.nSamplesPerSec * wfex.Format.nBlockAlign;
323
wfex.dwChannelMask = KSAUDIO_SPEAKER_MONO;
326
wfex.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
329
wfex.dwChannelMask = KSAUDIO_SPEAKER_STEREO | SPEAKER_FRONT_CENTER;
332
//wfex.dwChannelMask = KSAUDIO_SPEAKER_QUAD;
333
wfex.dwChannelMask = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER);
336
wfex.dwChannelMask = KSAUDIO_SPEAKER_QUAD | SPEAKER_FRONT_CENTER;
339
wfex.dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
342
wfex.dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; // XXX : or SPEAKER_ALL ??
345
wfex.Samples.wValidBitsPerSample = wfex.Format.wBitsPerSample;
347
mtOut->SetType(&MEDIATYPE_Audio);
348
mtOut->SetSubtype(&MEDIASUBTYPE_PCM);
349
mtOut->SetFormatType(&FORMAT_WaveFormatEx);
350
mtOut->SetFormat( (BYTE*) &wfex, sizeof(WAVEFORMATEX)+wfex.Format.cbSize);
351
mtOut->SetTemporalCompression(FALSE);
356
// ----------------------------------------------------------------------------
358
HRESULT CCoreAACDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
360
if (*mtOut->Type() != MEDIATYPE_Audio ||
361
*mtOut->Subtype() != MEDIASUBTYPE_PCM ||
362
*mtOut->FormatType() != FORMAT_WaveFormatEx)
364
return VFW_E_TYPE_NOT_ACCEPTED;
370
// ----------------------------------------------------------------------------
372
// 960 for LD or else 1024 (expanded to 2048 for HE-AAC)
373
#define MAXFRAMELEN 2048
375
HRESULT CCoreAACDecoder::DecideBufferSize(IMemAllocator *pAllocator, ALLOCATOR_PROPERTIES *pProperties)
377
pProperties->cBuffers = 8;
378
m_OutputBuffLen = m_Channels * MAXFRAMELEN * sizeof(short);
379
pProperties->cbBuffer = m_OutputBuffLen;
381
NOTE1("CCoreAACDecoder::DecideBufferSize %d", pProperties->cbBuffer);
383
ALLOCATOR_PROPERTIES Actual;
384
HRESULT hr = pAllocator->SetProperties(pProperties, &Actual);
388
if (Actual.cbBuffer < pProperties->cbBuffer || Actual.cBuffers < pProperties->cBuffers)
394
// ----------------------------------------------------------------------------
396
HRESULT CCoreAACDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
398
HRESULT hr = CTransformFilter::CompleteConnect(direction, pReceivePin);
400
if(direction == PINDIR_INPUT)
404
faacDecClose(m_decHandle);
407
m_decHandle = faacDecOpen();
409
faacDecConfigurationPtr config;
410
config = faacDecGetCurrentConfiguration(m_decHandle);
411
config->downMatrix = m_DownMatrix;
412
faacDecSetConfiguration(m_decHandle, config);
414
// Initialize the decoder
415
unsigned long SamplesPerSec = 0;
416
unsigned char Channels = 0;
417
if(faacDecInit2(m_decHandle, m_decoderSpecific, m_decoderSpecificLen,
418
&SamplesPerSec, &Channels) < 0)
425
Channels = 2; // TODO : check with mono
428
mp4AudioSpecificConfig info;
429
AudioSpecificConfig(m_decoderSpecific,m_decoderSpecificLen,&info);
431
wsprintf(m_ProfileName,"%s%s",
432
ObjectTypesNameTable[info.objectTypeIndex],
434
info.sbr_present_flag ?
442
m_Channels = Channels;
443
m_SamplesPerSec = SamplesPerSec;
444
m_BitsPerSample = 16; // we always decode to the default 16 bits (we could add 24,32,float)
447
m_brBytesConsumed = 0;
454
// ----------------------------------------------------------------------------
456
HRESULT CCoreAACDecoder::StartStreaming(void)
459
m_brBytesConsumed = 0;
461
return CTransformFilter::StartStreaming();
464
// ----------------------------------------------------------------------------
466
HRESULT CCoreAACDecoder::Transform(IMediaSample *pIn, IMediaSample *pOut)
468
if (m_State == State_Stopped)
470
pOut->SetActualDataLength(0);
474
if(pIn->IsPreroll() == S_OK)
479
// Decode the sample data
480
DWORD ActualDstLength;
482
DWORD SrcLength = pIn->GetActualDataLength();
483
DWORD DstLength = pOut->GetSize();
485
hr = pIn->GetPointer(&pSrc);
488
hr = pOut->GetPointer(&pDst);
492
if(!pSrc || !pDst || (DstLength < m_OutputBuffLen))
496
// (use our buffer calculated len, as the Waveout renderer seems to report wrongly a bigger size)
497
if(!Decode(pSrc, SrcLength, pDst, m_OutputBuffLen, &ActualDstLength))
500
NOTE3("Transform: %u->%u (%u)\n", SrcLength, ActualDstLength, m_OutputBuffLen);
502
// Copy the actual data length
503
pOut->SetActualDataLength(ActualDstLength);
507
// ----------------------------------------------------------------------------
509
// AAC order : C, L, R, L", R", LFE
510
// DShow order : L, R, C, LFE, L", R"
512
const int MAXCHANNELS = 6;
513
const int chmap[MAXCHANNELS][MAXCHANNELS+1] = {
514
// first column tell us if we need to remap
517
{ 1, 1, 2, 0, }, // c ,l, r -> l, r, c
518
{ 1, 1, 2, 0, 3, }, // c, l, r, bc -> l, r, c, bc
519
{ 1, 1, 2, 0, 3, 4, }, // c, l, r, bl, br -> l, r, c, bl, br
520
{ 1, 1, 2, 0, 5, 3, 4 } // c, l, r, bl, br, lfe -> l, r, c, lfe, bl, br
523
// ----------------------------------------------------------------------------
525
bool CCoreAACDecoder::Decode(BYTE *pSrc, DWORD SrcLength, BYTE *pDst, DWORD DstLength, DWORD *ActualDstLength)
527
faacDecFrameInfo frameInfo;
528
short *outsamples = (short *)faacDecDecode(m_decHandle, &frameInfo, pSrc, DstLength);
532
NOTE2("CCoreAACDecoder::Decode Error %d [%s]\n",
533
frameInfo.error, faacDecGetErrorMessage(frameInfo.error));
539
m_brBytesConsumed += SrcLength;
541
if(m_brCalcFrames == 43)
543
m_Bitrate = (int)((m_brBytesConsumed * 8) / (m_DecodedFrames / 43.07));
547
if (!frameInfo.error && outsamples)
549
int channelidx = frameInfo.channels-1;
550
if(chmap[channelidx][0])
553
short *dstBuffer = (short*)pDst;
554
for(unsigned int i = 0;
555
i < frameInfo.samples;
556
i += frameInfo.channels, outsamples += frameInfo.channels)
558
for(unsigned int j=1; j <= frameInfo.channels; j++)
560
*dstBuffer++ = outsamples[chmap[channelidx][j]];
566
memcpy(pDst, outsamples, frameInfo.samples * sizeof(short));
572
*ActualDstLength = frameInfo.samples * sizeof(short);
576
// ============================================================================
578
// ============================================================================
580
STDMETHODIMP CCoreAACDecoder::get_ProfileName(char** name)
582
CheckPointer(name,E_POINTER);
583
*name = m_ProfileName;
587
STDMETHODIMP CCoreAACDecoder::get_SampleRate(int* sample_rate)
589
CheckPointer(sample_rate,E_POINTER);
590
*sample_rate = m_SamplesPerSec;
594
STDMETHODIMP CCoreAACDecoder::get_Channels(int *channels)
596
CheckPointer(channels,E_POINTER);
597
*channels = m_Channels;
601
STDMETHODIMP CCoreAACDecoder::get_BitsPerSample(int *bits_per_sample)
603
CheckPointer(bits_per_sample,E_POINTER);
604
*bits_per_sample = m_BitsPerSample;
608
STDMETHODIMP CCoreAACDecoder::get_Bitrate(int *bitrate)
610
CheckPointer(bitrate,E_POINTER);
611
*bitrate = m_Bitrate;
615
STDMETHODIMP CCoreAACDecoder::get_FramesDecoded(unsigned int *frames_decoded)
617
CheckPointer(frames_decoded,E_POINTER);
618
*frames_decoded = m_DecodedFrames;
622
STDMETHODIMP CCoreAACDecoder::get_DownMatrix(bool *down_matrix)
624
CheckPointer(down_matrix,E_POINTER);
625
*down_matrix = m_DownMatrix;
629
STDMETHODIMP CCoreAACDecoder::set_DownMatrix(bool down_matrix)
631
m_DownMatrix = down_matrix;
635
// ============================================================================