2009-05-27 9 views
0

Tatsächlich schlägt es nur das zweite Mal fehl, wenn es aufgerufen wird. Ich verwende ein fensterloses Steuerelement, um Videoinhalte abzuspielen, wobei sich das abgespielte Video ändern kann, während das Steuerelement noch auf dem Bildschirm angezeigt wird. Sobald das Diagramm das erste Mal erstellt wurde, wechseln wir das Medium, indem wir die Wiedergabe anhalten, den Filter SOURCE ersetzen und das Diagramm erneut ausführen. Dies funktioniert unter Vista gut, aber wenn Sie auf XP laufen, gibt der zweite Anruf an Run()E_UNEXPECTED zurück.IMovieControl :: Run schlägt auf Windows XP fehl?

Die Initialisierung geht ungefähr so:

// Get the interface for DirectShow's GraphBuilder 
mGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER); 

// Create the Video Mixing Renderer and add it to the graph 
ATL::CComPtr<IBaseFilter> pVmr; 
pVmr.CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC); 
mGB->AddFilter(pVmr, L"Video Mixing Renderer 9"); 

// Set the rendering mode and number of streams 
ATL::CComPtr<IVMRFilterConfig9> pConfig; 
pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig); 
pConfig->SetRenderingMode(VMR9Mode_Windowless); 
pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&mWC); 

Und hier ist es, was wir tun, wenn wir einen Film spielen entscheiden. RenderFileToVideoRenderer ist von dshowutil.h im DirectShow-Beispielbereich geliehen.

// Release the source filter, if it exists, so we can replace it. 
IBaseFilter *pSource = NULL; 
if (SUCCEEDED(mpGB->FindFilterByName(L"SOURCE", &pSource)) && pSource) 
{ 
    mpGB->RemoveFilter(pSource); 
    pSource->Release(); 
    pSource = NULL; 
} 

// Render the file. 
hr = RenderFileToVideoRenderer(mpGB, mPlayPath.c_str(), FALSE); 

// QueryInterface for DirectShow interfaces 
hr = mpGB->QueryInterface(&mMC); 
hr = mpGB->QueryInterface(&mME); 
hr = mpGB->QueryInterface(&mMS); 

// Read the default video size 
hr = mpWC->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL); 
if (hr != E_NOINTERFACE) 
{ 
    if (FAILED(hr)) 
    { 
     return hr; 
    } 

    // Play video at native resolution, anchored at top-left corner. 
    RECT r; 
    r.left = 0; 
    r.top = 0; 
    r.right = lWidth; 
    r.bottom = lHeight; 
    hr = mpWC->SetVideoPosition(NULL, &r); 
} 

// Run the graph to play the media file 
if (mMC) 
{ 
    hr = mMC->Run(); 
    if (FAILED(hr)) 
    { 
     // We get here the second time this code is executed. 
     return hr; 
    } 
    mState = Running; 
} 

if (mME) 
{ 
    mME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0); 
} 

Jeder weiß, was hier vor sich geht?

Antwort

0

Niemals eine Lösung zu diesem Thema. Die Produktionslösung sollte einfach IGraphBuilder::Release aufrufen und den gesamten Graph von Grund auf neu erstellen. Es gibt einen CPU-Spike und eine leichte Neuzeichnungsverzögerung beim Wechsel der Videos, aber es ist weniger ausgeprägt als wir befürchtet hatten.

0
  1. Versuchen Sie, IMediaControl::StopWhenReady aufzurufen, bevor Sie den Quellfilter entfernen.
  2. Wann rufen Sie QueryInterface direkt auf? Sie können CComQIPtr <> verwenden, um das QI für Sie zu verzerren. Auf diese Weise müssen Sie Release nicht aufrufen, da es automatisch aufgerufen wird.
    Die Syntax sieht wie folgt aus: CComPtr<IMediaControl> mediaControl = pGraph;
  3. In FindFilterByName() statt Live-Zeiger übergeben ein CComPtr, erneut, so dass Sie Release nicht explizit aufrufen müssen.
+0

1. Wir rufen bereits IMediaControl :: Stop auf, bevor wir den Quellfilter entfernen, und der Aufruf von IMediaControl :: GetState sagt mir, dass der Wiedergabestatus State_Stopped ist. Irgendwelche anderen Ideen? 2/3. Gute Vorschläge, das räumt den Code ziemlich auf. –

Verwandte Themen