Search code examples
c#ms-media-foundationsharpdx

How to retrieve VideoMediaType from a MediaType in MediaFoundation with SharpDX


I'm trying to capture video from a WebCam using SharpDX.MediaFoundation (4.2.0). I'm able to render the default media type, but I want to be able to select between the different available formats of the device.

I can enumerate the device sources but I'm unable to get information about the video media types.

var attributes = new MediaAttributes(1);
attributes.Set(CaptureDeviceAttributeKeys.SourceType.Guid, CaptureDeviceAttributeKeys.SourceTypeVideoCapture.Guid);

var mediaSource = MediaFactory.EnumDeviceSources(attributes)[0].ActivateObject<MediaSource>();
mediaSource.CreatePresentationDescriptor(out var presentationDescriptor);

for (int d = 0; d < presentationDescriptor.StreamDescriptorCount; d++)
{
    presentationDescriptor.GetStreamDescriptorByIndex(d, out var isSelected, out var streamDescriptor);
    for (int i = 0; i < streamDescriptor.MediaTypeHandler.MediaTypeCount; i++)
    {
        var type = streamDescriptor.MediaTypeHandler.GetMediaTypeByIndex(i);
        if (type.MajorType == MediaTypeGuids.Video)
        {
            var v = type.QueryInterface<VideoMediaType>();
            // contains always empty values
            var x = v.VideoFormat;
        }
    }
}

QueryInterface was not working. so I tried

new VideoMediaType(type.NativePointer)

But the result is the same.

Additionally I tried the same with a SourceReader

 var reader = new SourceReader(mediaSource);
 var mediaTypeIndex = 0;

 using (var mt = reader.GetNativeMediaType(0, mediaTypeIndex))
 {
     if (mt.MajorType == MediaTypeGuids.Video)
     {
         //var vmt = new VideoMediaType(mt.NativePointer);
         var v = mt.QueryInterface<VideoMediaType>();
         var x = v.VideoFormat;
     }
 }

Same result. Any advises?


Solution

  • You should cast to SharpDX MediaType instead as it corresponds to IMFMediaType, but you already have it in mt variable anyway. It's IMFMediaType that describes the video and audio media types provided by sources. VideoMediaType or IMFVideoMediaType is not guaranteed to be available.

    You should be able to access different properties of the video media type contained in mt by using it like this:

    using (var mt = reader.GetNativeMediaType(0, mediaTypeIndex))
    {
        UnpackLong(mt.Get(MediaTypeAttributeKeys.FrameSize), out var width, out var height);
    }
    
    //Gets two integers from a long.
    private void UnpackLong(long value, out int left, out int right)
    {
        left = (int)(value >> 32);
        right = (int)(value & 0xffffffffL);
    }
    

    Check the SharpDX interfaces here (search for IMFMediaType).