How to check if Media Foundation can actually play a file and not just load it

0

I'm having some problems with MPEG1 videos and Media Foundation: So Media Foundation doesn't support playback of MPEG1 video streams (see here), but for some reason it will still open them and it will even report the correct duration and frame size. So at opening time everything looks like it can play those files.

But it can't! Once you try to actually play the MPEG1 video file, IMFAsyncCallback::Invoke() will be called with a status of MESessionTopologySet and then IMFMediaEvent::GetStatus() will return 0xc004f011 and that's about it.

So is there any way to check if a video format can actually be played by Media Foundation after opening it or is there any way to make Media Foundation only open files that it can actually play? Currently I can only tell if a file can be played or not by attempting to start playback and then see if it works or not which is somewhat inconvenient. I'd like to be able to tell if a file can be played or not much earlier.

c++
windows
winapi
video
ms-media-foundation
asked on Stack Overflow Oct 24, 2020 by Andreas • edited Oct 31, 2020 by Roman R.

1 Answer

0

I have solved this now by using IMFSourceReader. I have found out that trying to set the media type to MFVideoFormat_RGB32 will fail with MPEG1 video streams but it will work fine with MPEG4 so this is probably a feasible way to check if Media Foundation can actually play a file. In code, the solution looks like this:

hr = MFCreateAttributes(&pAttr, 1);
if(SUCCEEDED(hr)) {
            
    IMFAttributes_SetUINT32(pAttr, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
    IMFAttributes_SetUINT32(pAttr, &MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE);

    hr = MFCreateSourceReaderFromURL(filename, pAttr, &pReader);
    if(SUCCEEDED(hr)) {
            
        hr = IMFSourceReader_GetCurrentMediaType(pReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pFileVideoMediaType);
        if(SUCCEEDED(hr)) {
                        
            hr = MFCreateMediaType(&pTypeUncomp);
            if(SUCCEEDED(hr)) {
                        
                IMFMediaType_CopyAllItems(pFileVideoMediaType, (IMFAttributes *) pTypeUncomp);

                IMFMediaType_SetGUID(pTypeUncomp, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
                IMFMediaType_SetUINT32(pTypeUncomp, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
                IMFMediaType_SetUINT32(pTypeUncomp, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);

                hr = IMFSourceReader_SetCurrentMediaType(pReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, pTypeUncomp);
                if(SUCCEEDED(hr)) printf("NOT AN MPEG1 STREAM!\n");
            }
        }
    }
    
    SAFERELEASE(&pAttr);
}
answered on Stack Overflow Oct 31, 2020 by Andreas

User contributions licensed under CC BY-SA 3.0