2

これを機能させるために私が試みたすべての手順を公開したいので、これは長い投稿になるでしょう :)

Media Foundation API を使用してビデオを表示する VideoPlayer クラスを含む C++ COM dll があります。

VideoPlayer クラスは、IDL ファイルを使用して定義されます。

[
    object,
    uuid(74FDBBB1-BFFB-4F7E-ACA3-ADB0C7232790),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IVideoPlayer : IDispatch {

    [id(1)] HRESULT Initialize([in] HWND* video_hwnd, [in] HWND* event_hwnd);
    [id(2)] HRESULT OpenUrl([in] BSTR url_path);
    [id(3)] HRESULT Play();
    [id(4)] HRESULT HandleEvent([in] INT pEventPtr);
    [id(5)] HRESULT Repaint(void);
    [id(6)] HRESULT Resize([in] LONG width, [in] LONG height);
};

このクラスは、IDirect3DSurface9 オブジェクト内のビデオ フレームを出力するカスタム プレゼンター ( WPFMediaKitプロジェクトに基づく) を内部的に使用します。

カスタム プレゼンターには、次のように定義されているタイプ IEVRPresenterCallback のコールバックが必要です。

MIDL_INTERFACE("B92D8991-6C42-4e51-B942-E61CB8696FCB")
IEVRPresenterCallback : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE PresentSurfaceCB(IDirect3DSurface9 *pSurface) = 0;
};

ご覧のとおり、IDL ファイルでは定義されていませんが、ヘッダー ファイルで宣言されています。

VideoPlayer クラスに新しい関数を追加する必要があります。これにより、呼び出し元の C# コードが、カスタム プレゼンターに設定される IEVRPresenterCallback から継承するクラスのインスタンスを渡すことができます。

この行を VideoPlayer の IDL ファイルに追加しようとしました。

[id(7)] HRESULT RegisterCallback2([in] IEVRPresenterCallback * p_PresenterCallback);

しかし、私はエラーが発生します:

エラー MIDL2025: 構文エラー: "IEVRPresenterCallback" の近くに型指定が必要です

IDL に何もインポートしていないので、これは正常だと思います。IEVRPresenterCallback はヘッダー ファイルで定義されているため、これは正常です。

ヘッダー ファイルをインポートしようとしましたが、IEVRPresenterCallback 定義の MIDL_INTERFACE マクロがエラーを生成します。

エラー MIDL2025: 構文エラー: インターフェイス名、DispatchInterfaceName、CoclassName、ModuleName、LibraryName、ContractName、または "MIDL_INTERFACE" の近くの型指定が必要です

次に、インターフェイスを前方宣言しようとしましたが、次のエラーが発生しました。

エラー MIDL2011: 未解決の型宣言: IEVRPresenterCallback [プロシージャ 'RegisterCallback2' のパラメータ 'p_PresenterCallback' (インターフェース 'IVideoPlayer') ]

私の最後の試みは、RegisterCallback の定義を変更し、IEVRPresenterCallback の代わりに IUnknown へのポインターを持ち、関数の宣言で、ポインターを正しいインターフェイスにキャストすることでした。

これにより、C++ dll が正しくコンパイルされます。

C# アプリケーションでは、次のようにコールバックを設定しました。

[ComVisible(true), ComImport, SuppressUnmanagedCodeSecurity, Guid("B92D8991-6C42-4e51-B942-E61CB8696FCB"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IEVRPresenterCallback
{
    [PreserveSig]
    int PresentSurfaceCB(IntPtr pSurface);
}

internal class EVRPresenterCallback : IEVRPresenterCallback
{
    public int PresentSurfaceCB(IntPtr pSurface)
    {
        return 0;
    }
}

public partial class MainWindow : Window
{
    private EmideeMediaFoundationLib.IVideoPlayer videoPlayer = new EmideeMediaFoundationLib.VideoPlayer();
    private EVRPresenterCallback callback = new EVRPresenterCallback();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        videoHost.VideoPlayer.RegisterCallback(callback);
        videoHost.VideoPlayer.OpenUrl(@"C:\Users\Public\Videos\Sample Videos\wildlife.wmv");
    }
}

私が得る問題は、カスタム プレゼンターがコールバックを呼び出しているにもかかわらず、C# の PresentSurfaceCB 関数に戻らないことです。

私は今完全に立ち往生しており、問題がどこにあるのか、それを解決する方法もわかりません:(

何か案は?

前もって感謝します

4

1 に答える 1

0

ハンスのおかげで、私はそれを機能させることができました。

IDL ファイルでインターフェイスを移動し、コールバックで ID3D9Surface ポインターを返す代わりに、DOWRD_PTR を返します。

[
    uuid(B92D8991-6C42-4e51-B942-E61CB8696FCB),
]
interface IEVRPresenterCallback : IUnknown {
    [id(1)] HRESULT PresentSurfaceCB( DWORD_PTR pSurface);
}

[
    object,
    uuid(74FDBBB1-BFFB-4F7E-ACA3-ADB0C7232790),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IVideoPlayer : IDispatch {

    [id(1)] HRESULT Initialize([in] HWND* video_hwnd, [in] HWND* event_hwnd);
    [id(2)] HRESULT OpenUrl([in] BSTR url_path);
    [id(3)] HRESULT Play();
    [id(4)] HRESULT HandleEvent([in] INT pEventPtr);
    [id(5)] HRESULT Repaint(void);
    [id(6)] HRESULT Resize([in] LONG width, [in] LONG height);
    [id(7)] HRESULT RegisterCallback([in] IEVRPresenterCallback * p_PresenterCallback);
};

私の WPF アプリケーションでは、IEVRCallback から派生するクラスを作成します。

internal class EVRPresenterCallback : EmideeMediaFoundationLib.IEVRPresenterCallback
{
    public void PresentSurfaceCB(uint pSurface)
    {
    }
}

このインスタンスを VideoPlayer オブジェクトに渡します。

于 2011-11-09T13:32:38.850 に答える