smourier/DirectN

Various problems...

Steph55 opened this issue · 8 comments

Thank you for your last correction! I was able to progress in my test of DirectN.

  1. Now it seems that DMOs are missing, like this one, for instance:

CColorConvertDMO (CLSID_CColorConvertDMO)

  1. Guids are missing like: CODECAPI_AVEncCommonQuality

  2. This enum of DirectN is far from user friendly:

public enum __MIDL___MIDL_itf_mfreadwrite_0000_0001_0001 { MF_SOURCE_READER_INVALID_STREAM_INDEX = -1, MF_SOURCE_READER_ALL_STREAMS = -2, MF_SOURCE_READER_ANY_STREAM = -2, MF_SOURCE_READER_FIRST_AUDIO_STREAM = -3, MF_SOURCE_READER_FIRST_VIDEO_STREAM = -4, MF_SOURCE_READER_MEDIASOURCE = -1, }

  1. When I call the following function with valid parameters:

Functions.MFGetAttributeRatio(pType, MFConstants.MF_MT_FRAME_RATE_RANGE_MAX, out uint frameRateNum, out uint frameRateDem).ThrowOnError();

I get the error:

System.EntryPointNotFoundException : 'Unable to find an entry point named 'MFGetAttributeRatio' in DLL 'mfplat'.'

  1. Also, in order to replace the C++ function __uuidof, I wrote the following, because I did not find how in DirectN. You can include it, if needed:

public Guid __uuidof<T>() { var attribs = Attribute.GetCustomAttributes(typeof(T), typeof(GuidAttribute)); foreach (GuidAttribute attrib in attribs) { if (attrib.GetType() == typeof(GuidAttribute)) return new Guid(attrib.Value); } return new Guid(); }

Hi,

  1. Yes, not all guids are declared in DirectN. You get get all guid values from headers or from this online tool here: https://www.magnumdb.com

  2. Same for this: https://www.magnumdb.com/search?q=*AVEncCommonQuality

  3. This depends on how they are declared in the original header files. And actually, this is how it's declared in Windows Kits\10\Include\10.0.22000.0\um\mfreadwrite.h:

enum __MIDL___MIDL_itf_mfreadwrite_0000_0001_0001
{
	MF_SOURCE_READER_INVALID_STREAM_INDEX	= 0xffffffff,
	MF_SOURCE_READER_ALL_STREAMS	= 0xfffffffe,
	MF_SOURCE_READER_ANY_STREAM	= 0xfffffffe,
	MF_SOURCE_READER_FIRST_AUDIO_STREAM	= 0xfffffffd,
	MF_SOURCE_READER_FIRST_VIDEO_STREAM	= 0xfffffffc,
	MF_SOURCE_READER_MEDIASOURCE	= 0xffffffff
} ;
  1. The generator kinda guess where functions are defined, but there's unfortunately no magic here. In fact this one is not a function exported from a DLL, it's a native utility function implemented directly in the header, so I've updated Functions.cs to remove it. Here is its corresponding native code in Windows Kits\10\Include\10.0.22000.0\um\mfapi.h, it can be easily adapted to C#:
MFGetAttributeRatio(
    IMFAttributes*  pAttributes,
    REFGUID         guidKey,
    _Out_ UINT32*   punNumerator,
    _Out_ UINT32*   punDenominator
    )
{
    return MFGetAttribute2UINT32asUINT64(pAttributes, guidKey, punNumerator, punDenominator);
}

MFGetAttribute2UINT32asUINT64(
    IMFAttributes*  pAttributes,
    REFGUID         guidKey,
    _Out_ UINT32*   punHigh32,
    _Out_ UINT32*   punLow32
    )
{
    UINT64 unPacked;
    HRESULT hr = S_OK;

    hr = pAttributes->GetUINT64(guidKey, &unPacked);
    if (FAILED(hr)) {
        return hr;
    }
    Unpack2UINT32AsUINT64(unPacked, punHigh32, punLow32);

    return hr;
}

Unpack2UINT32AsUINT64(UINT64 unPacked, _Out_ UINT32* punHigh, _Out_ UINT32* punLow)
{
    *punHigh = HI32(unPacked);
    *punLow = LO32(unPacked);
}

HI32(UINT64 unPacked)
{
    return (UINT32)(unPacked >> 32);
}

LO32(UINT64 unPacked)
{
    return (UINT32)unPacked;
}

  1. This is not needed, in C#, typeof(AnyType).Guid will give you an interface guid.

Thank you very much for your answer, it is much useful! You are quite generous. Now I still have a few other things.

  1. A little correction for the future version of DirectN: The following seems to be the proper signature for SetCurrentMediaType of IMFSourceReader for it to work :
[PreserveSig]
HRESULT SetCurrentMediaType(/* [annotation][in] _In_ */ uint dwStreamIndex, /* [annotation][out][in] _Reserved_ */ IntPtr pdwReserved, /* [annotation][in] _In_ */ IMFMediaType pMediaType);

When we call it, we need to pass IntPtr.Zero as the second parameter.

  1. I'm having trouble with the codecApi->GetValue() and codecApi->SetValue() functions. I did not find any helper function in DirectN for the Variant type.

I saw on the following page that you already studied the subject: https://stackoverflow.com/questions/49323410/com-interop-and-marshaling-of-variantvt-ptr

Did you do something for this in DirectN, maybe I did not find it?

Hi,

  1. true. This is a bug in the .h declaration of SetCurrentMediaType in the Windows SDK. The annotation specifies it as [out][in], not optional, so the generator doesn't generate an IntPtr where it should... I've fixed the .cs.

  2. VARIANTs are normally handled by .NET (this is not the case with PROPVARIANTs). The SO post is very specific as the VARIANT used there was an invalid one.

You can use GetObjectForNativeVariant to convert from IntPtr into an object and the opposite: GetNativeVariantForObject

From .NET this is fairly simple, just use the functions and ask again if you face any real issue.

Here is the code I'm trying to use:

           var codecApi = pWriter.GetServiceForStream<ICodecAPI>(writerVideoStreamIndex, new Guid(), typeof(ICodecAPI).GUID);
            if (codecApi != null)
            {
                codecApi.Object.GetValue(CODECAPI_AVEncCommonQuality, out IntPtr intPtrQualité);
                var o = Marshal.GetObjectForNativeVariant(intPtrQualité);

But the value I get for intPtrQualité is 0x0000000000000013 and I get an execution Engine Exception...

That may be an issue with ICodecAPI definition, the most simple way is to redefine it like this:

    ...
    [PreserveSig]
    HRESULT GetValue(/* [in] */ [MarshalAs(UnmanagedType.LPStruct)] Guid Api, /* [annotation][out] _Out_ */ out object Value);
    
    ...
    [PreserveSig]
    HRESULT SetValue(/* [in] */ [MarshalAs(UnmanagedType.LPStruct)] Guid Api, /* [annotation][in] _In_ */ ref object Value);

Closing due to inactivity