C++ 在DirectShow中保持纵横比?(带窗口的)C++;

C++ 在DirectShow中保持纵横比?(带窗口的)C++;,c++,directshow,C++,Directshow,编辑:更新了代码,调用DLL的应用程序不再崩溃 当show_video()的第四个参数设置为true时,我希望DirectShow播放的视频保持其纵横比。以下是我的DLL的源代码: #include <windows.h> #include <dshow.h> #pragma comment (lib, "strmiids.lib") #define DLL extern "C" _declspec(dllexport) wchar_t *convertCharArr

编辑:更新了代码,调用DLL的应用程序不再崩溃

当show_video()的第四个参数设置为true时,我希望DirectShow播放的视频保持其纵横比。以下是我的DLL的源代码:

#include <windows.h>
#include <dshow.h>

#pragma comment (lib, "strmiids.lib")
#define DLL extern "C" _declspec(dllexport)

wchar_t *convertCharArrayToLPCWSTR(const char* charArray) {
    wchar_t* wString = new wchar_t[4096];

    MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);

    return wString;
}

DLL void show_video(double window1, HWND window2, char *fname, double keep_aspect_ratio) {
    CoInitialize(NULL);

    HRESULT hr = S_OK;

    IGraphBuilder *pGraph = NULL;
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
    hr = pGraph->RenderFile(convertCharArrayToLPCWSTR(fname), NULL);

    IBaseFilter *pVideoRenderer = NULL;
    hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoRenderer);

    IVMRAspectRatioControl *pAspectRatio = NULL;
    hr = pVideoRenderer->QueryInterface(IID_IVMRAspectRatioControl, (void**)&pAspectRatio);

    if ((bool)keep_aspect_ratio == true) {
        hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
    }
    else {
        hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_NONE);
    }

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

    RECT rect;
    if ((HWND)(DWORD)window1 != NULL) {
        SetWindowLong((HWND)(DWORD)window1, GWL_STYLE, GetWindowLong((HWND)(DWORD)window1, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
        hr = pVidWin->put_Owner((OAHWND)(HWND)(DWORD)window1);
        GetClientRect((HWND)(DWORD)window1, &rect);
    }
    else {
        SetWindowLong(window2, GWL_STYLE, GetWindowLong(window2, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
        hr = pVidWin->put_Owner((OAHWND)window2);
        GetClientRect(window2, &rect);
    }

    hr = pVidWin->SetWindowPosition(0, 0, rect.right - rect.left, rect.bottom - rect.top);
    hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
    hr = pVidWin->SetWindowForeground(OATRUE);
    hr = pVidWin->HideCursor(OATRUE);

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

    IMediaEvent *pEvent = NULL;
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
    long evCode;

    hr = pEvent->WaitForCompletion(INFINITE, &evCode);

    hr = pControl->Stop();
    hr = pVidWin->put_Visible(OAFALSE);
    hr = pVidWin->put_Owner(NULL);

    pEvent->Release();
    pControl->Release();
    pVidWin->Release();

    pAspectRatio->Release();
    pVideoRenderer->Release();
    pGraph->Release();

    CoUninitialize();
}
#包括
#包括
#pragma注释(lib,“strmids.lib”)
#定义DLL外部“C”\u declspec(dllexport)
wchar_t*convertChararray-ytolpcwstr(const char*charArray){
wchar_t*wString=新的wchar_t[4096];
MultiByteToWideChar(CP_ACP,0,charArray,-1,wString,4096);
回流环;
}
DLL无效显示视频(双窗口1,HWND窗口2,字符*fname,双保持纵横比){
共初始化(空);
HRESULT hr=S_正常;
IGraphBuilder*pGraph=NULL;
hr=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_服务器,IID_IGraphBuilder,(void**)和pGraph);
hr=pGraph->RenderFile(convertChararray-ytolpcwstr(fname),NULL);
IBaseFilter*PVIDEORDER=NULL;
hr=CoCreateInstance(CLSID\u VideoMixingRenderer,NULL,CLSCTX\u INPROC\u服务器,IID\u IBaseFilter,(void**)和pVideoRenderer);
IVMRASpectatioControl*pAspectRatio=NULL;
hr=pvideorederer->QueryInterface(IID_IVMRAspectRatioControl,(void**)和pAspectRatio);
if((bool)keep_aspect_ratio==true){
hr=pAspectRatio->SetAspectRatioMode(VMR\u ARMODE\u字母盒);
}
否则{
hr=pAspectRatio->SetAspectRatioMode(VMR\u ARMODE\u NONE);
}
IVideoWindow*pVidWin=NULL;
hr=pGraph->QueryInterface(IID_IVideoWindow,(void**)和pVidWin);
RECT-RECT;
如果((HWND)(DWORD)窗口1!=NULL){
SetWindowLong((HWND)(DWORD)window1,GWL_样式,GetWindowLong((HWND)(DWORD)window1,GWL_样式)| WS|u clipcchildren | WS|u CLIPSIBLINGS);
hr=pVidWin->put_Owner((OAHWND)(HWND)(DWORD)窗口1);
GetClientRect((HWND)(DWORD)窗口1和rect);
}
否则{
SetWindowLong(window2,GWL_样式,GetWindowLong(window2,GWL_样式)| WS|u CLIPCHILDREN | WS|u clipSpilings);
hr=pVidWin->put_Owner((OAHWND)window2);
GetClientRect(window2,&rect);
}
hr=pVidWin->SetWindowPosition(0,0,rect.right-rect.left,rect.bottom-rect.top);
hr=pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
hr=pVidWin->设置窗口前景(OATRUE);
hr=pVidWin->HideCursor(OATRUE);
IMediaControl*pControl=NULL;
hr=pGraph->QueryInterface(IID_IMediaControl,(void**)和pControl);
hr=pControl->Run();
IMediaEvent*pEvent=NULL;
hr=pGraph->QueryInterface(IID_imediavent,(void**)和pEvent);
长EV码;
hr=pEvent->WaitForCompletion(无限,&evCode);
hr=pControl->Stop();
hr=pVidWin->put\u可见(OAFALSE);
hr=pVidWin->put\u Owner(空);
pEvent->Release();
pControl->Release();
pVidWin->Release();
pAspectRatio->Release();
pvideorederer->Release();
pGraph->Release();
coninitialize();
}
目前,从我的应用程序调用DLL时,我为第三个参数选择的视频播放得很好,但视频没有保持其原始纵横比。有人知道我做错了什么吗

…调用DLL的进程现在崩溃

流程崩溃假设您可以提供其他详细信息,如崩溃点、异常详细信息等

可能的原因是前面的
QueryInterface
调用失败以及缺少
IVMRaspectatioControl
指针

筛选器图形管理器不应实现
IVMRASpectatioControl
。如果在过滤器图中有视频混合渲染器过滤器,请直接从中选择
QueryInterface


UPD。另一个答案中的解决方案是一个不应该做事情的例子。如果对VR执行了
CoCreateInstance
,则应将其添加到图形中,并将其包括到渲染过程中。否则,您根本不需要
CoCreateInstance
,也不应该按名称查找筛选器-而是枚举筛选器,并通过查找实现相关接口的筛选器来识别您的VR。

找到了解决方案。初始化pvideorederer后,我需要添加以下行:

pGraph->FindFilterByName(L"Video Renderer", &pVideoRenderer);
因此,生成的代码如下所示:

#include <windows.h>
#include <dshow.h>

#pragma comment (lib, "strmiids.lib")
#define DLL extern "C" _declspec(dllexport)

wchar_t *convertCharArrayToLPCWSTR(const char* charArray) {
    wchar_t* wString = new wchar_t[4096];

    MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);

    return wString;
}

DLL void show_video(double window1, HWND window2, char *fname, double keep_aspect_ratio) {
    CoInitialize(NULL);

    HRESULT hr = S_OK;

    IGraphBuilder *pGraph = NULL;
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
    hr = pGraph->RenderFile(convertCharArrayToLPCWSTR(fname), NULL);

    IBaseFilter *pVideoRenderer = NULL;
    hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoRenderer);
    pGraph->FindFilterByName(L"Video Renderer", &pVideoRenderer);

    IVMRAspectRatioControl *pAspectRatio = NULL;
    hr = pVideoRenderer->QueryInterface(IID_IVMRAspectRatioControl, (void**)&pAspectRatio);

    if ((bool)keep_aspect_ratio == true) {
        hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
    }
    else {
        hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_NONE);
    }

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

    RECT rect;
    if ((HWND)(DWORD)window1 != NULL) {
        SetWindowLong((HWND)(DWORD)window1, GWL_STYLE, GetWindowLong((HWND)(DWORD)window1, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
        hr = pVidWin->put_Owner((OAHWND)(HWND)(DWORD)window1);
        GetClientRect((HWND)(DWORD)window1, &rect);
    }
    else {
        SetWindowLong(window2, GWL_STYLE, GetWindowLong(window2, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
        hr = pVidWin->put_Owner((OAHWND)window2);
        GetClientRect(window2, &rect);
    }

    hr = pVidWin->SetWindowPosition(0, 0, rect.right - rect.left, rect.bottom - rect.top);
    hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
    hr = pVidWin->SetWindowForeground(OATRUE);
    hr = pVidWin->HideCursor(OATRUE);

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

    IMediaEvent *pEvent = NULL;
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
    long evCode;

    hr = pEvent->WaitForCompletion(INFINITE, &evCode);

    hr = pControl->Stop();
    hr = pVidWin->put_Visible(OAFALSE);
    hr = pVidWin->put_Owner(NULL);

    pEvent->Release();
    pControl->Release();
    pVidWin->Release();

    pAspectRatio->Release();
    pVideoRenderer->Release();
    pGraph->Release();

    CoUninitialize();
}
#包括
#包括
#pragma注释(lib,“strmids.lib”)
#定义DLL外部“C”\u declspec(dllexport)
wchar_t*convertChararray-ytolpcwstr(const char*charArray){
wchar_t*wString=新的wchar_t[4096];
MultiByteToWideChar(CP_ACP,0,charArray,-1,wString,4096);
回流环;
}
DLL无效显示视频(双窗口1,HWND窗口2,字符*fname,双保持纵横比){
共初始化(空);
HRESULT hr=S_正常;
IGraphBuilder*pGraph=NULL;
hr=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_服务器,IID_IGraphBuilder,(void**)和pGraph);
hr=pGraph->RenderFile(convertChararray-ytolpcwstr(fname),NULL);
IBaseFilter*PVIDEORDER=NULL;
hr=CoCreateInstance(CLSID\u VideoMixingRenderer,NULL,CLSCTX\u INPROC\u服务器,IID\u IBaseFilter,(void**)和pVideoRenderer);
pGraph->FindFilterByName(L“视频渲染器”和pvideRenderer);
IVMRASpectatioControl*pAspectRatio=NULL;
hr=pvideorederer->QueryInterface(IID_IVMRAspectRatioControl,(void**)和pAspectRatio);
if((bool)keep_aspect_ratio==true){
hr=pAspectRatio->SetAspectRatioMode(VMR\u ARMODE\u字母盒);
}
否则{
hr=pAspectRatio->SetAspectRatioMode(VMR\u ARMODE\u NONE);
}
IVideoWindow*pVidWin=NULL;
hr=pGraph->QueryInterface(IID_IVideoWindow,(void**)和pVidWin);
RECT-RECT;
如果((HWND)(DWORD)窗口1!=NULL){
SetWindowLong((HWND)(DWORD)window1,GWL_样式,GetWindowLong((HWND)(DWORD)window1,GWL_样式)| WS|u clipcchildren | WS|u CLIPSIBLINGS);
hr=pVidWin->put_Owner((OAHWND)(HWND)(DWORD)窗口1);
GetClientRect((HWND)(DWORD)窗口1和rect);
}
否则{
SetWindowLong(window2,GWL_样式,GetWindowLong(window2,GWL_样式)| WS_CL