无法在#include中使用WaitForCompletion()

问题描述 投票:0回答:1

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

希亚。 ^ 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 

请建议我在这里缺少什么。

c++ visual-studio qt video-streaming directshow
1个回答
0
投票

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

DShow Sample Code for playing video does not play the video

找出#2是否有问题的简单方法是在Run和WaitForCompletion之间放置MessageBox调用。 MessageBox会为您发送消息,只要您打开盒子,视频就会播放(或者即使在关闭盒子后也能继续播放并继续播放)。正确的解决方案是在同一时间等待并替换消息(WaitDispatchingMessages,此SO问题或类似问题)。

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

© www.soinside.com 2019 - 2024. All rights reserved.