I'm using the Windows build in AAC MFTransform filter for decoding AAC audio. Using the methods described in "AAC Decoder" and "Basic MFTransform usage". The method works fine for other codecs, like Dolby.
However for AAC audio I get the error MF_E_TRANSFORM_NEED_MORE_INPUT for every even frame I send. So I send another frame, these frames gives OK. But on output the filter delivers only each second frame, the other is lost. I tried a lot of additional sample parameters and tried to get out the other frame, but no success. Could also not find any hint on the Internet.
My shortest code sample (some parameters are hard wired - 2 channel, 48 kHz)
# include <windows.h> # include <Mfapi.h> # include <Mfidl.h> # include <Mfreadwrite.h> # include <wmcodecdsp.h> void main () { HRESULT hrError ; ULONG dwFlags ; IMFTransform * pDecoder = 0 ; IMFMediaType * pMediaTypeIn = 0 ; IMFMediaType * pOutType = 0 ; IMFSourceReader * pReader = 0 ; IMFMediaType * partialMediaType = 0 ; unsigned int unChannel, unSampling ; // init MF decoder, using Microsoft hard wired GUID hrError = CoInitializeEx (0, COINIT_APARTMENTTHREADED) ; hrError = MFStartup (MF_VERSION, MFSTARTUP_FULL) ; hrError = CoCreateInstance (IID_CMSAACDecMFT, 0, CLSCTX_INPROC_SERVER, IID_IMFTransform, (void **) & pDecoder) ; // setup decoder input type, hard wired for given sample audio clip unChannel = 2 ; unSampling = 48000 ; hrError = MFCreateMediaType (& pMediaTypeIn) ; hrError = pMediaTypeIn->SetGUID (MF_MT_MAJOR_TYPE, MFMediaType_Audio) ; hrError = pMediaTypeIn->SetGUID (MF_MT_SUBTYPE, MFAudioFormat_AAC) ; hrError = pMediaTypeIn->SetUINT32 (MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0x2A /*DP4MEDIA_MP4A_AUDIO_PLI_AAC_L4*/) ; hrError = pMediaTypeIn->SetUINT32 (MF_MT_AAC_PAYLOAD_TYPE, 1) ; // payload 1 = ADTS header hrError = pMediaTypeIn->SetUINT32 (MF_MT_AUDIO_BITS_PER_SAMPLE, 16) ; hrError = pMediaTypeIn->SetUINT32 (MF_MT_AUDIO_CHANNEL_MASK, (unChannel == 2 ? 0x03 : 0x3F)) ; hrError = pMediaTypeIn->SetUINT32 (MF_MT_AUDIO_NUM_CHANNELS, (UINT32) unChannel) ; hrError = pMediaTypeIn->SetUINT32 (MF_MT_AUDIO_SAMPLES_PER_SECOND, (UINT32) unSampling) ; // prepare additional user data (according to MS documentation for AAC decoder) byte arrUser [] = {0x01, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x90} ; // hard wired for 2 channel, 48000 kHz pMediaTypeIn->SetBlob (MF_MT_USER_DATA, arrUser, 14) ; hrError = pDecoder->SetInputType (0, pMediaTypeIn, 0) ; pMediaTypeIn->Release () ; // set out type MFCreateMediaType (& pOutType) ; pOutType->SetGUID (MF_MT_MAJOR_TYPE, MFMediaType_Audio) ; pOutType->SetGUID (MF_MT_SUBTYPE, MFAudioFormat_PCM) ; pOutType->SetUINT32 (MF_MT_AUDIO_BITS_PER_SAMPLE, 16) ; pOutType->SetUINT32 (MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000) ; pOutType->SetUINT32 (MF_MT_AUDIO_NUM_CHANNELS, 2) ; hrError = pDecoder->SetOutputType (0, pOutType, 0) ; pOutType->Release () ; // get source reader - will read AAC samples hrError = MFCreateSourceReaderFromURL (L"Sand.aac", 0, & pReader) ; hrError = MFCreateMediaType (& partialMediaType) ; partialMediaType->SetGUID (MF_MT_MAJOR_TYPE, MFMediaType_Audio) ; partialMediaType->SetGUID (MF_MT_SUBTYPE, MFAudioFormat_AAC) ; // create AAC from AAC -> frame reader pReader->SetCurrentMediaType (MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, partialMediaType) ; partialMediaType->Release () ; // write wave file header // ... // get input buffer hrError = pDecoder->ProcessMessage (MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0) ; hrError = pDecoder->ProcessMessage (MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0) ; do { // read sample IMFSample * pSampleIn, * pSampleOut ; LONGLONG timestamp; DWORD actualStreamIndex; IMFMediaBuffer * pBufferOut ; IMFMediaBuffer * pBuffer ; MFT_OUTPUT_STREAM_INFO xOutputInfo ; MFT_OUTPUT_DATA_BUFFER arrOutput [1] ; DWORD dwStatus ; DWORD dwLength ; BYTE * pAudioData ; DWORD cbBuffer; DWORD pcbMaxLength; pReader->ReadSample (MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, & actualStreamIndex, & dwFlags, & timestamp, & pSampleIn); if (dwFlags != 0) break ; // process input buffer hrError = pDecoder->ProcessInput (0, pSampleIn, 0) ; pSampleIn->Release () ; // get LPCM output pSampleOut = 0 ; pBufferOut = 0 ; hrError = pDecoder->GetOutputStreamInfo (0, & xOutputInfo) ; hrError = MFCreateSample (& pSampleOut) ; hrError = MFCreateMemoryBuffer (xOutputInfo.cbSize, & pBufferOut) ; hrError = pBufferOut->SetCurrentLength (0) ; hrError = pSampleOut->AddBuffer (pBufferOut) ; arrOutput [0].dwStreamID = 0 ; arrOutput [0].dwStatus = 0 ; arrOutput [0].pEvents = 0 ; arrOutput [0].pSample = pSampleOut ; dwStatus = 0 ; // output gives only each second frame :( hrError = pDecoder->ProcessOutput (0, 1, arrOutput, & dwStatus) ; hrError = pBufferOut->GetCurrentLength (& dwLength) ; pSampleOut->ConvertToContiguousBuffer (& pBuffer); pBuffer->Lock (& pAudioData, & pcbMaxLength, & cbBuffer); // write wave file pBuffer->Unlock (); pBuffer->Release () ; pBufferOut->Release () ; pSampleOut->Release () ; } while (dwFlags == 0) ; }