2017-08-01 81 views
0

EDIT:コードを更新し、DLLを呼び出すアプリケーションがクラッシュしなくなりました。DirectShowで縦横比を維持しますか? (ウィンドウ)C++

show_video()の4番目の引数がtrueに設定されている場合、DirectShowで再生されているビデオのアスペクト比を維持します。ここに私のDLLのソースです:それは私のアプリケーションから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(); 
} 

、私は第三引数のために選択したビデオは、罰金果たしているが、ビデオは元の縦横比を保持しません。誰かが私が間違っていることを知っていますか?

+0

QueryInterfaceのhr結果を確認しましたか?おそらく、pAspectRatioはNULLです。レンダラのインターフェイスに直接クエリを行う必要があります。たとえばEVRの場合、IMFVideoDisplayControlを照会してSetAspectRatioModeを使用する必要があります。 – VuVirt

+0

@VuVirtコードを更新して、レンダラのインターフェイスに直接照会するようにしました(少なくとも、これは私がやったと思います)。そして、もはやクラッシュすることなく、アスペクト比を維持していません。 4番目の引数はtrueに設定されます。 –

答えて

1

解決策が見つかりました。

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

問題が解決pVideoRendererを初期化した後、私は次の行を追加するために必要な! :D

0

... DLLを呼び出すプロセスがクラッシュする。

プロセスのクラッシュがクラッシュポイントのような追加の詳細を提供できることを前提とし、例外の詳細など

可能性の高い原因は、IVMRAspectRatioControlポインタの前のQueryInterface呼び出しや不在にE_NOINTERFACE障害です。

フィルタグラフマネージャーはIVMRAspectRatioControlを実装していません。フィルタグラフにVideo Mixing Rendererフィルタがある場合は、QueryInterfaceをそのまま使用します。

UPD。もう一つの答えの中の解決策は、物事をどうしたらいいのかという例です。 VRの場合CoCreateInstanceを行う場合は、それをグラフに追加し、それをレンダリングプロセスに含める必要があります。それ以外の場合は、CoCreateInstanceはまったく必要ありません。名前でフィルタを検索するのではなく、代わりにフィルタを列挙し、問題のインターフェイスを実装するフィルタを検索してVRを特定してください。

+0

Windows XP以上のDirectShowのデフォルトのビデオミキシングレンダラー(VMR7)を使用しています。コードスニペットを提供する可能性はありますか? –

+0

私はコードを更新し、クラッシュの問題を修正することができました。しかし、ビデオはまだ元のアスペクト比を保持していません。 –

関連する問題