繁体   English   中英

DirectShow-将IGraphBuilder *转换为double(C ++)

[英]DirectShow - convert IGraphBuilder * to double (C++)

我正在使用DLL为GameMaker Studio创建扩展。 GameMaker Studio仅支持void,char *或double的函数返回类型。 至于参数,仅支持char *和double。 这意味着我必须将我需要的所有其他类型转换为这些类型之一。

问题是,我不确定是否要以最佳方式进行处理。 当试图通过标题栏拖动DirectShow所有者窗口时,会发生非常奇怪的行为。 嵌入式视频不会随父窗口移动; 它保持在相同的位置。

仅当窗口暂停或停止时这才是问题。 当前正在播放视频时,DirectShow窗口将与其父窗口一起移动。 但我希望用户能够暂停和停止视频,因此需要修复此问题。 这是我的DLL的代码:

#include <windows.h>
#include <DShow.h>

#define DLL extern "C" _declspec(dllexport)
using namespace std;

wchar_t *convertCharArrayToLPCWSTR(const char* charArray) {
    wchar_t* wString = new wchar_t[4096];
    MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
    return wString;
}

DLL double video_init() {
    if(FAILED(CoInitialize(NULL))){
        MessageBox(NULL,L"Failed to initialize COM library.",L"ERROR", MB_ICONERROR | MB_OK);
        return false;
    }

    return true;
}

DLL void video_uninit() {
    CoUninitialize();
}

DLL double video_add(HWND window, char *fname) {
    IGraphBuilder *pGraph = NULL;
    HRESULT hr = S_OK;

    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

    hr = pGraph->RenderFile(convertCharArrayToLPCWSTR(fname), NULL);
    if(FAILED(hr)) return NULL;

    IVideoWindow *pVidWin = NULL;
    hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);

    hr = pVidWin->put_Owner((OAHWND)window);
    hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
    pVidWin->Release();

    IMediaControl *pControl = NULL;
    hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
    hr = pControl->Run();
    hr = pControl->Pause();

    pControl->Release();

    return (double)(DWORD)(void *)pGraph;
}

DLL void video_start(double video) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IMediaControl *pControl = NULL;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pControl->Run();
    pControl->Release();
}

DLL void video_stop(double video) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IMediaControl *pControl = NULL;
    IMediaSeeking *pSeek = NULL;
    REFERENCE_TIME stoptime = 0;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);

    OAFilterState fs;
    hr = pControl->GetState(100,&fs);

    switch(fs){
    case State_Running:
        hr = pControl->Pause();

    case State_Paused:
        pGraph->QueryInterface(IID_IMediaSeeking,(void**)&pSeek);   
        hr = pSeek->SetPositions(&stoptime,AM_SEEKING_AbsolutePositioning,0,AM_SEEKING_NoPositioning);
    }

    pControl->Release();
    pSeek->Release();
}

DLL void video_pause(double video) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IMediaControl *pControl = NULL;
    HRESULT hr = S_OK;

    pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
    hr = pControl->Pause();
    pControl->Release();
}

DLL void video_delete(double video) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    pGraph->Release();
}

DLL void video_set_rectangle(double video,double x,double y,double w,double h) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IVideoWindow *pVidWin = NULL;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IVideoWindow,(void**)&pVidWin);
    hr = pVidWin->SetWindowPosition((long)x, (long)y, (long)w, (long)h);
    pVidWin->Release();
}

DLL double video_is_playing(double video) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IMediaControl *pControl = NULL;
    IMediaPosition *pPos = NULL;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);

    OAFilterState fs;
    hr = pControl->GetState(100, &fs);

    switch (fs){
    case State_Running:

        pGraph->QueryInterface(IID_IMediaPosition, (void**)&pPos);

        REFTIME currentPos;
        hr = pPos->get_CurrentPosition(&currentPos);

        REFTIME duration;
        hr = pPos->get_Duration(&duration);

        if (currentPos < duration) {

            return true;
        }
        else {

            video_stop(video);
            return false;
        }

    case State_Paused:
        return false;

    case State_Stopped:
        return false;
    }

    pControl->Release();
    pPos->Release();

    return false;
}

DLL double video_is_cursor_hidden(double video) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IVideoWindow *pVidWin = NULL;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);

    long hidden;
    hr = pVidWin->IsCursorHidden(&hidden);

    if (hidden == OATRUE) {
        return true;
    } else {
        return false;
    }

    pVidWin->Release();
}

DLL void video_hide_cursor(double video, double hide) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IVideoWindow *pVidWin = NULL;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);

    if (hide == (double)true) {
        hr = pVidWin->HideCursor(OATRUE);
    }
    else {
        hr = pVidWin->HideCursor(OAFALSE);
    }

    pVidWin->Release();
}

DLL void video_set_foreground(double video, double focus) {
    IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
    IVideoWindow *pVidWin = NULL;
    HRESULT hr = S_OK;

    hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);

    if (focus == (double)true) {
        hr = pVidWin->SetWindowForeground(OATRUE);
    }
    else {
        hr = pVidWin->SetWindowForeground(OAFALSE);
    }

    pVidWin->Release();
}

DLL void video_update(HWND window) {

    if (!(GetWindowLong(window, GWL_STYLE) & WS_CLIPCHILDREN)) {
        SetWindowLong(window, GWL_STYLE,
            GetWindowLong(window, GWL_STYLE) | WS_CLIPCHILDREN);
    }
}

我会提供调用DLL以及所有其他内容的GameMaker Studio代码,但我严重怀疑我是否会在这里遇到GameMaker Studio用户。 这是我能做的最好的。 我不知道这是否是导致问题的原因,但是我一直在思考转换类型的方式,这就是为什么它表现得很时髦的原因。 要将IGraphBuilder *转换为双精度值作为返回值,我进行了如下转换:

return (double)(DWORD)(void *)pGraph;

我也尝试过:

return (double)(DWORD)pGraph;

两者都给了我上述相同的问题。

至于论点,我这样投:

(double)(DWORD)pGraph

我应该如何将IGraphBuilder *转换为double? 或者,这不是我的问题吗?

非常感谢所有建议,纠正和帮助。

塞缪尔

切勿将指针转换为(DWORD) ,如果将代码编译为64位,它将截断该指针! 如果需要,请使用指针大小的整数类型,例如SIZE_T,UINT_PTR或DWORD_PTR。

char*是您可用的最好的类型,并保证与其他指针类型兼容。

double是有问题的,因为它的大小可能与指针的大小不匹配,并且在64位Windows程序中的另一个CPU寄存器中传递它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM