Intel® Integrated Performance Primitives
Community support and discussions relating to developing high-performance vision, signal, security, and storage applications.
6615 Discussions

AAC encoding and muxing does not produce valid mp4 file

There are many examples of H264 encoding and muxing. But not many for AAC encoding and muxing. I am trying to mux AAC data to a mp4 file.

The data I obtain is from Directshow samplegrabber callback.

This is my setting for the muxer:
[bash]m_AudioEncoderParams.m_info_in.sample_frequency = 44100; m_AudioEncoderParams.m_info_in.channels = 2; m_AudioEncoderParams.m_info_in.bitPerSample = 16; m_AudioEncoderParams.m_info_in.bitrate = (audioFormat->nSamplesPerSec * audioFormat->nChannels * audioFormat->wBitsPerSample); m_AudioEncoderParams.m_info_out.bitrate = 192000; m_AudioEncoderParams.m_info_out.stream_type = UMC :: AAC_AUDIO;[/bash]
[cpp]m_mp4muxerParams.m_lpDataWriter = &m_fileWriter; m_mp4muxerParams.m_SystemType = UMC :: MPEG4_SYSTEM_STREAM; m_mp4muxerParams.m_nNumberOfTracks = 1; m_mp4muxerParams.pTrackParams = new UMC::TrackParams[m_mp4muxerParams.m_nNumberOfTracks]; m_mp4muxerParams.pTrackParams[0].type = UMC :: AUDIO_TRACK; m_mp4muxerParams.pTrackParams[0] = &m_AudioEncoderParams.m_info_out; m_mp4muxerParams.pTrackParams[0].bufferParams.m_prefInputBufferSize = (m_AudioEncoderParams.m_info_out.bitrate * 2); m_mp4muxerParams.pTrackParams[0].bufferParams.m_prefOutputBufferSize = (m_AudioEncoderParams.m_info_out.bitrate * 2);[/cpp]
Then I have my function from callback:

[cpp]HRESULT CaptureGraphBuilder :: AddAudioSample(double Time, IMediaSample * pSample) { HRESULT hr = S_OK; UMC :: Status status; BYTE * inBuffer; hr = pSample->GetPointer(&inBuffer); if (FAILED(hr)) { printf("Fail at getting input audio data buffer"); goto done; } status = m_inAudioData.SetBufferPointer(inBuffer, pSample->GetActualDataLength()); printf("Audio data length is %d", pSample->GetActualDataLength()); m_inAudioData.SetDataSize(pSample->GetActualDataLength()); if (m_AudioStartTime == 0) { m_AudioStartTime = Time; } Time -= m_AudioStartTime; status = m_mp4Muxer.LockBuffer(&m_outAudioData, m_mp4Muxer.GetTrackIndex(UMC :: AUDIO_TRACK)); if (status == UMC :: UMC_OK) { status = m_AudioEncoder.GetFrame(&m_inAudioData, &m_outAudioData); m_outAudioData.SetTime(Time); if (status == UMC :: UMC_OK) { m_mp4Muxer.UnlockBuffer(&m_outAudioData, m_mp4Muxer.GetTrackIndex(UMC :: AUDIO_TRACK)); } else { printf("FATAL. FAIL AT AAC ENCODING"); } } else { printf("Error in Audio status = %d", status); } done: return hr; }[/cpp]
The audio mp4 file is not valid. I can hear sound for a split second and then nothing else.

What am I doing wrong? I am attaching the mp4 file for reference.
0 Kudos
6 Replies
Some more investigation.

In my AAC encoder parameters, if I set this:

m_AudioEncoderParams.m_info_out.stream_subtype = UMC :: AAC_LC_PROFILE;

(consequently, this is also set for the mp4 muxer track parameters info)

then the audio file produced is as attached in my previous post.

if I don't set it, (just commented out the line), then the audio file just runs as if in fast forword mode. A 10 second file would just zip past in a second or so.

I'd really appreciate some insight from folks here.
It looks like only one sample is written to the file using this AAC encoding/Muxing method. At least that is what I think looking at the mp4 file.
Anybody have a clue?

I have set output bit rate to be 192kbps.

After every encoder GetFrame run, the output data size is around 515 bytes where as the input size is 88200 bytes. The compression ratio is around 170!

That is a lot of compression. The output birate seems to be around 9000 bps or only 9kbps.

Seems low.

Some more sample compression comparison data:

Input data size (bytes) bitrate set date size in bytes from AAC encoder GetFrame (average)
-------------------------- ------------ --------------------------------------------
88200 96kpbs 170
88200 128kbps 240
88200 192kbps 500

Can anybody point me somewhere I can debug? Is there a bug in the AAC encoder? doesn't seem likely!

Hi Aditya,
How do you handle the end of your input stream?
According to codec source code you need to do one else GetFrame call with first argument (MediaData *pDataIn) set to NULL.
Hi Sergey

I don't handle that currently. You are correct, I need to do that.

Perhaps I could handle it outside of the loop explicitly in the end? The reason I could do so is that my input source is the microphone and data is coming in continuously. When I press "stop", I could execute this code sequence?

[cpp]status = m_mp4Muxer.LockBuffer(&m_outAudioData, m_mp4Muxer.GetTrackIndex(UMC :: AUDIO_TRACK)) if (status == UMC :: UMC_OK) { status = m_AudioEncoder.GetFrame(NULL, &m_outAudioData); m_mp4Muxer.UnlockBuffer(&m_outAudioData, m_mp4Muxer.GetTrackIndex(UMC :: AUDIO_TRACK)); }[/cpp]

The interesting thing would be, how would I do SetTime() call. Or perhaps I won't need it since it is just clearing of buffered frames?
I got excellent help from Intel Premier support. I am posting the soution here:
Basically, the AAC encoder needs to look atm_SuggestedInputSize parameter from the AAC encoding parameters structure. I need to feedm_SuggestedInputSize amount of data to GetFrame. In my case,m_SuggestedInputSize was 4096 and hence 1024 samples.
So looping over GetFrame and muxing 4096 bytes at a time fixed the issue.