在 C# 中编组自定义 directshow 过滤器接口

发布于 2024-08-19 00:52:27 字数 5172 浏览 3 评论 0原文

大家好,这几天我一直被这个问题困扰。我有一个可以转换为的自定义 COM 接口,但是当我调用一个函数(如果它是函数)时,我会收到 AccessViolationException,因为 this 指针已更改。

下面的代码代表我正在编组的两个接口。所有方法都会导致同样的问题。

任何帮助将不胜感激。

/*
    struct SourceConfig {       
        LONGLONG                            llBufferDuration;           // The buffer duration to use while receiving samples from the network, measured in 100nsec units
        REFERENCE_TIME                      rtStartTime;
        FLOAT                               fRate;                      // Negative: rewind, Positive: forward
        BYTE                                btConnectionTimeout;        // The time to wait for a connection to be established, measured in seconds
        BOOL                                bKeyFramesOnly;
        CHAR                                pIP[128];
        WORD                                wPort;
        CHAR                                pChannel[64];
        BYTE                                pbtCertificate[96];
        SAMPLE_TIME                         eSampleTime;// Indicates weather to directly route the samples with the absolute UTC 
                                                        // time OR to make all generated samples relative to zero, default value
                                                        // is 'RELATIVE'.
        HANDLE                              hEvent;                     // Used to wait for the operation completion ( optional )
        BYTE                                bAutoSeekToNextAvailPos;    // If seeking into a hole automatically resume streaming from the next available position
        DWORD                               dwSampleStarvationTimeout;  // The maximal amount of seconds ( and not msec ) the filter might wait for incoming data
    };


    interface
    __declspec(uuid("{9331DC40-40F5-438a-B9C0-44B479246C98}"))
    IStreamingSourceCallback : IUnknown {
        virtual STDMETHODIMP OnStreamingSourceEvent(IN STREAMING_SRC_EVENT eCode, IN const VARIANT* pvar1 = 0, IN const VARIANT* pvar2 = 0, IN const VARIANT* pvar3 = 0) = 0;
    };

    interface
    __declspec(uuid("{ECF7715E-E973-4bb9-AEED-389845F0E297}"))
    IStreamingSource : IUnknown {
        virtual HRESULT GetConfig(OUT SourceConfig* pCfg) = 0;
        virtual HRESULT SetConfig(IN const SourceConfig* pCfg) = 0;
        virtual HRESULT SetCallback(IN IStreamingSourceCallback* pCallback) = 0;
        virtual HRESULT UpdateAbsoluteRefTime(IN LONGLONG& llRefTime) = 0;

        virtual HRESULT GetSeekPos(IN OUT REFERENCE_TIME& rtSeek) = 0;
    };

 */

public enum SAMPLE_TIME : byte
{
    Relative,
    Absolute
};

[StructLayout(LayoutKind.Sequential)]
public struct SourceConfig
{
    long BufferDuration;
    long StartTime;
    float Rate;
    byte ConnectionTimeout;
    [MarshalAs(UnmanagedType.Bool)]
    bool KeyFramesOnly;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string Ip;
    UInt16 Port;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string Channel;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
    public byte[] Certificate;
    SAMPLE_TIME SampleTime;
    IntPtr Event;
    byte AutoSeekToNextAvailPos;
    uint SampleStarvationTimeout;
};

public enum STREAMING_SRC_EVENT : int
{
    SRC_NONE,
    SRC_CONNECTED,
    SRC_DISCONNECTED,
    SRC_ERROR,
    SRC_STARTTIME,
    SRC_STREAM_CLOSE2LIVE,
    SRC_STREAM_FAR_LIVE,
    SRC_NEARESTSEEK
};  

[ComImport, Guid("9331DC40-40F5-438a-B9C0-44B479246C98"), SuppressUnmanagedCodeSecurity, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStreamingSourceCallback
{
    [PreserveSig]
    int OnStreamingSourceEvent(
        [In, MarshalAs(UnmanagedType.I4)] STREAMING_SRC_EVENT code,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var1,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var2,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var3);
}

[ComImport, Guid("ECF7715E-E973-4bb9-AEED-389845F0E297"), SuppressUnmanagedCodeSecurity, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStreamingSource
{
    [PreserveSig]
    int GetConfig([Out, MarshalAs(UnmanagedType.Struct)] out SourceConfig config);
    [PreserveSig]
    int SetConfig([In, MarshalAs(UnmanagedType.Struct)] SourceConfig config);
    [PreserveSig]
    int SetCallback([In, MarshalAs(UnmanagedType.Interface)] IStreamingSourceCallback callback);
    [PreserveSig]
    int UpdateAbsoluteRefTime([In, MarshalAs(UnmanagedType.I8)] ref long refTime);
    [PreserveSig]
    int GetSeekPos([In, Out, MarshalAs(UnmanagedType.I8)] ref long seekTime);
}

下面的代码显示了用法:

IStreamingSource ssInterface = vosFilter as IStreamingSource;
        if (ssInterface == null)
        {
            throw new ApplicationException("Could not get IStreamingSource. ");
        }

        if ((hr = ssInterface.SetCallback(_ssCallback)) < 0)
        {
            throw new ApplicationException("Could not set streaming source callback. " + DirectShowLib.DsError.GetErrorText(hr));
        }

ssInterface 指向正确的结构,一旦单步执行到 SetCallback,它就指向垃圾。

谢谢。

Hey folks, I've been stuck on this for the past few days. I have a custom COM interface that I am able to cast to, but when I call one if it's functions I get an AccessViolationException because the this pointer has changed.

The below code represents the two interfaces that I am marshalling. All methods result in the same problem.

Any help will be greatly appreciated.

/*
    struct SourceConfig {       
        LONGLONG                            llBufferDuration;           // The buffer duration to use while receiving samples from the network, measured in 100nsec units
        REFERENCE_TIME                      rtStartTime;
        FLOAT                               fRate;                      // Negative: rewind, Positive: forward
        BYTE                                btConnectionTimeout;        // The time to wait for a connection to be established, measured in seconds
        BOOL                                bKeyFramesOnly;
        CHAR                                pIP[128];
        WORD                                wPort;
        CHAR                                pChannel[64];
        BYTE                                pbtCertificate[96];
        SAMPLE_TIME                         eSampleTime;// Indicates weather to directly route the samples with the absolute UTC 
                                                        // time OR to make all generated samples relative to zero, default value
                                                        // is 'RELATIVE'.
        HANDLE                              hEvent;                     // Used to wait for the operation completion ( optional )
        BYTE                                bAutoSeekToNextAvailPos;    // If seeking into a hole automatically resume streaming from the next available position
        DWORD                               dwSampleStarvationTimeout;  // The maximal amount of seconds ( and not msec ) the filter might wait for incoming data
    };


    interface
    __declspec(uuid("{9331DC40-40F5-438a-B9C0-44B479246C98}"))
    IStreamingSourceCallback : IUnknown {
        virtual STDMETHODIMP OnStreamingSourceEvent(IN STREAMING_SRC_EVENT eCode, IN const VARIANT* pvar1 = 0, IN const VARIANT* pvar2 = 0, IN const VARIANT* pvar3 = 0) = 0;
    };

    interface
    __declspec(uuid("{ECF7715E-E973-4bb9-AEED-389845F0E297}"))
    IStreamingSource : IUnknown {
        virtual HRESULT GetConfig(OUT SourceConfig* pCfg) = 0;
        virtual HRESULT SetConfig(IN const SourceConfig* pCfg) = 0;
        virtual HRESULT SetCallback(IN IStreamingSourceCallback* pCallback) = 0;
        virtual HRESULT UpdateAbsoluteRefTime(IN LONGLONG& llRefTime) = 0;

        virtual HRESULT GetSeekPos(IN OUT REFERENCE_TIME& rtSeek) = 0;
    };

 */

public enum SAMPLE_TIME : byte
{
    Relative,
    Absolute
};

[StructLayout(LayoutKind.Sequential)]
public struct SourceConfig
{
    long BufferDuration;
    long StartTime;
    float Rate;
    byte ConnectionTimeout;
    [MarshalAs(UnmanagedType.Bool)]
    bool KeyFramesOnly;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string Ip;
    UInt16 Port;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string Channel;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
    public byte[] Certificate;
    SAMPLE_TIME SampleTime;
    IntPtr Event;
    byte AutoSeekToNextAvailPos;
    uint SampleStarvationTimeout;
};

public enum STREAMING_SRC_EVENT : int
{
    SRC_NONE,
    SRC_CONNECTED,
    SRC_DISCONNECTED,
    SRC_ERROR,
    SRC_STARTTIME,
    SRC_STREAM_CLOSE2LIVE,
    SRC_STREAM_FAR_LIVE,
    SRC_NEARESTSEEK
};  

[ComImport, Guid("9331DC40-40F5-438a-B9C0-44B479246C98"), SuppressUnmanagedCodeSecurity, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStreamingSourceCallback
{
    [PreserveSig]
    int OnStreamingSourceEvent(
        [In, MarshalAs(UnmanagedType.I4)] STREAMING_SRC_EVENT code,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var1,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var2,
        [In, MarshalAs(UnmanagedType.IUnknown)] object var3);
}

[ComImport, Guid("ECF7715E-E973-4bb9-AEED-389845F0E297"), SuppressUnmanagedCodeSecurity, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStreamingSource
{
    [PreserveSig]
    int GetConfig([Out, MarshalAs(UnmanagedType.Struct)] out SourceConfig config);
    [PreserveSig]
    int SetConfig([In, MarshalAs(UnmanagedType.Struct)] SourceConfig config);
    [PreserveSig]
    int SetCallback([In, MarshalAs(UnmanagedType.Interface)] IStreamingSourceCallback callback);
    [PreserveSig]
    int UpdateAbsoluteRefTime([In, MarshalAs(UnmanagedType.I8)] ref long refTime);
    [PreserveSig]
    int GetSeekPos([In, Out, MarshalAs(UnmanagedType.I8)] ref long seekTime);
}

The following code shows the usage:

IStreamingSource ssInterface = vosFilter as IStreamingSource;
        if (ssInterface == null)
        {
            throw new ApplicationException("Could not get IStreamingSource. ");
        }

        if ((hr = ssInterface.SetCallback(_ssCallback)) < 0)
        {
            throw new ApplicationException("Could not set streaming source callback. " + DirectShowLib.DsError.GetErrorText(hr));
        }

ssInterface points to the right structure, as soon as stepping through to SetCallback, this points to garbage.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦过后 2024-08-26 00:52:27

如果您在 SetCallback 方法 sig 中的 IStreamingSourceCallback 参数上取出 MarshalAs(UnmanagedType.Interface) ,您还会收到错误吗?

Do you still get the error if you take out the MarshalAs(UnmanagedType.Interface) on the IStreamingSourceCallback argument in your SetCallback method sig?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文