Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various problems... #25

Closed
Steph55 opened this issue Dec 3, 2021 · 8 comments
Closed

Various problems... #25

Steph55 opened this issue Dec 3, 2021 · 8 comments

Comments

@Steph55
Copy link

Steph55 commented Dec 3, 2021

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(); }

@smourier
Copy link
Owner

smourier commented Dec 4, 2021

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.

@Steph55
Copy link
Author

Steph55 commented Dec 7, 2021

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?

smourier added a commit that referenced this issue Dec 7, 2021
@smourier
Copy link
Owner

smourier commented Dec 7, 2021

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

@Steph55
Copy link
Author

Steph55 commented Dec 7, 2021 via email

@smourier
Copy link
Owner

smourier commented Dec 7, 2021

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

@Steph55
Copy link
Author

Steph55 commented Dec 8, 2021

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...

@smourier
Copy link
Owner

smourier commented Dec 8, 2021

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);

@smourier
Copy link
Owner

Closing due to inactivity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants