locked
Using MP3 decoder directly, without session RRS feed

  • Question

  • Hello,

    I wish to use the MP3 decoder object on Windows 7, to feed him some MP3 data, and read back some PCM samples. I'm having a hard time using the API to make it work. I'm wondering if anyone could manage something like this, or if anyone knows of an exemple where it is used like that. I've look into many open source project, but found no one using this...

    I've read from http://social.msdn.microsoft.com/Forums/en-US/a7dd62e4-6d65-433c-a715-43b4a39230bd/mp3-decoder-filter-missing-in-vista?forum=windowsdirectshowdevelopment that the decoder might be deliberately crippled, but if so, why put it in the documentation ? Maybe I have to use it with the DirectShow APIs  ?? 

    So here is my problem. I successfully instantiate the CLSID_CMP3DecMediaObject object with CoCreateInstance, I can use GetStreamCount which gives me 1 input and 0 output :

    hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, &mp3CoObject);
    hr = mp3CoObject->GetStreamCount(mp3CoObject, &cInputStreams,&cOutputStreams);

    Then, I cannot configure it further.

    When I call SetInputType with MP3 format on it, I get a MF_E_INVALIDMEDIATYPE error. Maybe I give him a bad media type (see next lines), but I don't really know what to give...

    MFCreateMediaType(&inputMediaType);
    hr = inputMediaType->SetGUID(inputMediaType, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
    hr = inputMediaType->SetGUID(inputMediaType, &MF_MT_SUBTYPE, &MFAudioFormat_MP3);
    hr = inputMediaType->SetUINT32(inputMediaType, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);

    Then, ignoring this error, I get MF_E_TRANSFORM_TYPE_NOT_SET on SetOutputType or GetOutputAvailableType call.

    I've got the same kind of problem using the DMO apis btw...

    Any idea please ?

    Fred

    Monday, February 17, 2014 1:26 PM

Answers

  • Hello.

    I think you have to give more information to the decoder :

    // You need a valid WAVEFORMATEX from the mp3 file
    WAVEFORMATEX fmt;
    
    ...
    
    const UINT32 uiBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8);
    const UINT32 uiAvgBytePerSec = uiBlockAlign * fmt.nSamplesPerSec;
    
    MFCreateMediaType(&inputMediaType);
    
    hr = inputMediaType->SetGUID(&MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
    
    hr = inputMediaType->SetGUID(&MF_MT_SUBTYPE, &MFAudioFormat_MP3);
    
    hr = inputMediaType->SetUINT32(&MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, fmt.nSamplesPerSec);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, fmt.nChannels);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, fmt.wBitsPerSample);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, uiBlockAlign);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, uiAvgBytePerSec);

    If you don't know how to get this information from mp3 file, check MFNode Project. There is source code to read mpeg audio header. You will have few changes to handle Layer 3.


    • Edited by Miaou77 Monday, February 17, 2014 9:09 PM
    • Marked as answer by FredGermain Tuesday, February 18, 2014 2:51 PM
    Monday, February 17, 2014 9:08 PM

All replies

  • Hello.

    I think you have to give more information to the decoder :

    // You need a valid WAVEFORMATEX from the mp3 file
    WAVEFORMATEX fmt;
    
    ...
    
    const UINT32 uiBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8);
    const UINT32 uiAvgBytePerSec = uiBlockAlign * fmt.nSamplesPerSec;
    
    MFCreateMediaType(&inputMediaType);
    
    hr = inputMediaType->SetGUID(&MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
    
    hr = inputMediaType->SetGUID(&MF_MT_SUBTYPE, &MFAudioFormat_MP3);
    
    hr = inputMediaType->SetUINT32(&MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, fmt.nSamplesPerSec);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, fmt.nChannels);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, fmt.wBitsPerSample);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, uiBlockAlign);
    
    hr = inputMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, uiAvgBytePerSec);

    If you don't know how to get this information from mp3 file, check MFNode Project. There is source code to read mpeg audio header. You will have few changes to handle Layer 3.


    • Edited by Miaou77 Monday, February 17, 2014 9:09 PM
    • Marked as answer by FredGermain Tuesday, February 18, 2014 2:51 PM
    Monday, February 17, 2014 9:08 PM
  • Miaou77 (David I guess :), you're the boss, that's exactly what was missing !

    Curious, I'd have thought that the codec wouldn't need these informations as it can be found in the MPEG header...

    Anyway, thanks a lot, and MFNode is a really nice project, hang in there :)

    Tuesday, February 18, 2014 2:51 PM
  • Thank you.

    Microsoft mp3 decoder

    Yes, the doc says Input Format : WAVE_FORMAT_MPEGLAYER3... only...

    The MediaFoundation's team has disappeared. So i don't know if the doc is updated or not.

    Also there is a problem with Wmcodecdsp.h. For example CLSID_AACMFTEncoder is not defined in the SDK (7.1).

    Also why the mp3 encoder (CLSID_MP3ACMCodecWrapper) is only available for Windows 8. Windows Seven is the most popular OS of the world. Why Windows Seven does not have this encoder ?

    Also why IMFMediaSourceEx, IMFMediaEngineEx and so on, are only available for Windows 8. Windows Seven is the most popular OS of the world...

    I will post a new message if needed.





    • Edited by Miaou77 Tuesday, February 18, 2014 9:57 PM
    Tuesday, February 18, 2014 9:50 PM
  • Can Miaou77 clarify this a bit more, please? 

    I am looking at MFNode and can't seem to find the file where there is example to populate WAVEFORMATEX.

    In general, I assume mp3 decoder cannot be user with Source Reader mechanism? So, I have to use IMFTransform mechanism to decode mp3 to PCM samples?

    Tuesday, February 25, 2014 6:34 AM
  • Hello.

    You can check MFTMpeg12Decoder. I use MFCreateWaveFormatExFromMFMediaType in GetOutputType.

    You can use Source Reader or MediaSession to decode mp3. But you also can do it by hand. I will provide a simple console program to do it with a source reader.




    • Edited by Miaou77 Tuesday, February 25, 2014 8:15 PM
    Tuesday, February 25, 2014 8:11 PM
  • Hi there

    In the previous post, it says "You'll need a valid WAVEFORMATEX from mp3 file".

    Now, 

    MFCreateWaveFormatExFromMFMediaType gives valid WAVEFORMATEX from MFMediaType.

    So, this is the sequence of events to be able to read PCM samples from the MP3 file (Using IMFTransform)

    Create the object (per the first post)

    hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, &mp3CoObject);
    hr = mp3CoObject->GetStreamCount(mp3CoObject, &cInputStreams,&cOutputStreams);

    Next, I need to populate WAVEFORMATEX. But to do so, I need MFMediaType input type, right?

    Next, I can set MFMediaType output type with Audio Type, PCM subtype and MHz, bits per sample,

    and number of channels (same as input type).

    Now, I could do IMFTransform type, ProcessInput and ProcessOutput methods to get the samples.

    Am I on the right track?

    I am really sorry if this sounds dense. But I have searched for documentation and examples and have

    not found much.

    Wednesday, February 26, 2014 3:17 AM
  • Hello.

    Check MFNode project. I've added a console program to decode mp3 file with source reader.

    • Proposed as answer by Kadambi Thursday, February 27, 2014 4:51 AM
    Wednesday, February 26, 2014 11:05 PM
  • Thank you very much. I will download the latest project and check it out. Really appreciate the help.
    Thursday, February 27, 2014 12:42 AM