Search code examples
c++audioaacms-media-foundationdata-extraction

Windows Media Foundation: getting AAC decoded data


I want to use Windows Media Foundation to get the audio data of an AAC-encoded file. I figured out that the right way is to declare an IMFSample* where the single sample of the audio will be kept. In VS2015 I see that this class has a method getDouble(), but there is nothing about it in the MSDN documentation.

Here is the part of example I am trying to do:

    IMFSample *pSample(NULL);

    hr = m_pReader->ReadSample(
        MF_SOURCE_READER_FIRST_AUDIO_STREAM, // [in] DWORD dwStreamIndex,
        0,                                   // [in] DWORD dwControlFlags,
        NULL,                                // [out] DWORD *pdwActualStreamIndex,
        &dwFlags,                            // [out] DWORD *pdwStreamFlags,
        &timestamp,                          // [out] LONGLONG *pllTimestamp,
        &pSample);                           // [out] IMFSample **ppSample

The last argument pSample is what I want.

Now, I want to get double, float or byte pointer to the current decoded sample data.

How can this be done?

Thanks in advance.


Solution

  • First convert the sample to a buffer:

    Microsoft::WRL::ComPtr<IMFMediaBuffer> mediaBuffer;
    sample->ConvertToContiguousBuffer(&mediaBuffer)
    

    Then lock the buffer to get a pointer to its internals:

    BYTE *audioData = nullptr;
    DWORD sampleBufferLength = 0;
    mediaBuffer->Lock(&audioData, nullptr, &sampleBufferLength);
    // use audioData...
    mediaBuffer->Unlock();
    

    To specify what the format of the data is returned to you use SetCurrentMediaType on your reader (do this once at the beginning)

        Microsoft::WRL::ComPtr<IMFMediaType> pPartialType;
        MFCreateMediaType(&pPartialType);
        pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
        pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
        reader->SetCurrentMediaType(
            (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
            NULL, pPartialType.Get());
    

    And please use smart pointers everywhere with MF or you'll enter a world of pain. Microsoft::WRL::ComPtr<XXX> is your friend! I've missed out checking the HRESULTs in this example code but you'll definitely want to do that.