我正在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, ¶m1, ¶m2, 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
请给我建议我在这里想念的东西。
答案 0 :(得分:0)
在COM STA线程上,您负责分派窗口消息,WaitForCompletion
是一个阻塞调用,没有承诺实现消息循环。
请参见DShow Sample Code for playing video does not play the video
找出问题2的一种简单方法是在Run和WaitForCompletion之间放置MessageBox调用。 MessageBox会为您调度消息,并且只要您保持打开状态,视频也会播放(或者,即使关闭此框,播放也会开始播放并保持播放状态)。正确的解决方案是同时等待和发送消息(WaitDispatchingMessages,此SO问题或类似问题)。
这也适用于您的情况,更改为有限超时,发送消息并返回到另一个等待尝试。