无法在#include <dshow.h>中使用WaitForCompletion()

时间:2019-03-07 04:46:57

标签: c++ visual-studio qt video-streaming directshow

我正在Qt patch中使用visual studio 2008。我正在尝试使用#include <dshow.h>播放视频。我可以成功运行视频,但是使用WaitForCompletion()时,我的视频挂起。这是我的代码:-

MediaPlayer = new Media(ui.stackedWidget->currentWidget());
connect(ui.stackedWidget->currentWidget(), SIGNAL(videograph()), MediaPlayer,SLOT(HandleGraphEvent()));
MediaPlayer->pMediaControl->Run();
long evCode;
MediaPlayer->g_pEvent1->WaitForCompletion(INFINITE,&evCode);

我的头文件:-

Media.cpp

#include <dshow.h>
#include <commctrl.h>
#include <commdlg.h>
#include <stdio.h>
#include <tchar.h>
//#include <atlbase.h>

#include "Media.h"
#include <qtconcurrentrun.h>

Media::Media(QWidget *parent)
{

    HRESULT hr;
    CoInitialize(NULL);
    hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); 
    hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pWc); 
    hr = pWc->SetNumberOfStreams(2);
    hr = pVmr->QueryInterface(IID_IVMRMixerBitmap,(void **)&pBitMAp);

    if(SUCCEEDED(hr))
    {
        hr = pWc->SetRenderingMode(VMRMode_Windowless);
        hr = pWc->SetRenderingPrefs( RenderPrefs_ForceOffscreen| RenderPrefs_AllowOffscreen );
        pWc->Release();
    }
    if(SUCCEEDED(hr))
    {
        hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWl);
        if(SUCCEEDED(hr))
            hr = pWl->SetVideoClippingWindow(parent->winId()); 
    }

    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGraph);
    pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
    pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent);

    pGraph->QueryInterface(IID_IBasicAudio,(void **)&pAudio);
    pGraph->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking );
    pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMediaPosition);
    hr = pGraph->AddFilter(pVmr, L"Video Mixing Renderer"); 
    g_pEvent->SetNotifyWindow((OAHWND)parent->winId(), WM_GRAPHNOTIFY, 0);  
    RECT grc;
    GetWindowRect(parent->winId(), &grc);
    pGraph->RenderFile(L"/FlashDisk/test.mp4", NULL);
    long lWidth, lHeight; 
    hr = pWl->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL); 
    if (SUCCEEDED(hr))
    {
        SetRect(&g_rcSRc, 0, 0, lWidth, lHeight); 
        GetWindowRect(parent->winId(), &g_rcDest); 
        SetRect(&g_rcDest, 0, 0, g_rcDest.right, g_rcDest.bottom); 
    }
    video_rendered = 1;
    pWl->SetVideoPosition(&g_rcSRc, &g_rcDest);
}

Media::~Media()
{
    CleanUp();
}

void Media::HandleGraphEvent()
{
    if (g_pEvent == NULL)
        return;
    long evCode;
    LONG_PTR param1, param2;
    while (SUCCEEDED(g_pEvent->GetEvent(&evCode, &param1, &param2, 0)))
    {
        g_pEvent->FreeEventParams(evCode, param1, param2);
        switch (evCode)
        {
            case EC_STATE_CHANGE:           //ADDED for state change from pause to play to indiacte video paused.
                //SetEvent(sync_event);
                return;
            case EC_COMPLETE:  // Fall through.
                CleanUp();
                return;
            case EC_USERABORT: // Fall through.
            case EC_ERRORABORT: 
                CleanUp(); 
                //media.play_next_file();
                return;
        }
    } 
}
/*#######################################################################################
CleanUp
#######################################################################################*/
void Media::CleanUp(void)
{
    video_rendered = 0;
    g_pEvent->SetNotifyWindow(NULL, 0, 0);
    g_pEvent->Release();
    g_pEvent = NULL;
    pMediaControl->Release();
    pAudio->Release();
    pGraph->Release();
}

Media.h

#ifndef MEDIA_H
#define MEDIA_H
//#define max(a,b)            (((a) > (b)) ? (a) : (b))
//#define min(a,b)            (((a) < (b)) ? (a) : (b))
#include <windef.h>
#include <QObject>
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QTimer>
#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include <Phonon>
#include <dshow.h>
#include <commctrl.h>
#include <commdlg.h>
#include <stdio.h>
#include <tchar.h>
//#include <atlbase.h>
#include <qtconcurrentrun.h>
#pragma comment (lib, "strmiids.lib")
#define WM_GRAPHNOTIFY  WM_APP + 1
#define WM_AUDIOGRAPHNOTIFY WM_APP + 2

class Media: public QObject
{
    Q_OBJECT
public:
    Media(QWidget *parent);
    ~Media();
    IMediaControl         *pMediaControl;
    IMediaEventEx         *g_pEvent;
    IMediaEvent           *g_pEvent1;
    IVideoWindow          *pVidWin;
    IVMRMixerBitmap       *pBitMAp;
    IVMRMixerBitmap       *pBitMAp1;
    IMediaSeeking         *pMediaSeeking;
    IMediaPosition        *pMediaPosition;
    IVMRFilterConfig      *pWc;
    IBaseFilter           *pVmr;
    IVMRWindowlessControl *pWl;
    RECT                   g_rcSRc; 
    RECT                   g_rcDest; 
    IBasicAudio           *pAudio;
    IVMRMixerControl      *pVmc;
    IGraphBuilder         *pGraph;
    DWORD                  width;
    unsigned char          video_rendered;
    void CleanUp(void);
    public slots:
    void HandleGraphEvent(void);
};


#endif 

请给我建议我在这里想念的东西。

1 个答案:

答案 0 :(得分:0)

在COM STA线程上,您负责分派窗口消息,WaitForCompletion是一个阻塞调用,没有承诺实现消息循环。

请参见DShow Sample Code for playing video does not play the video

  

找出问题2的一种简单方法是在Run和WaitForCompletion之间放置MessageBox调用。 MessageBox会为您调度消息,并且只要您保持打开状态,视频也会播放(或者,即使关闭此框,播放也会开始播放并保持播放状态)。正确的解决方案是同时等待和发送消息(WaitDispatchingMessages,此SO问题或类似问题)。

这也适用于您的情况,更改为有限超时,发送消息并返回到另一个等待尝试。