Quantcast
Channel: Media Foundation Development for Windows Desktop forum
Viewing all articles
Browse latest Browse all 1079

Decoding AAC with MFT gives only every second audio frame

$
0
0

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) ;
}


Viewing all articles
Browse latest Browse all 1079

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>