Results 1 to 3 of 3

Thread: VMR9 (DirectShow) Windowless and QAxWidget

  1. #1
    Join Date
    Jun 2011
    Posts
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default VMR9 (DirectShow) Windowless and QAxWidget

    I've gone through examples online, searched Google, and browsed these forums; however, I can't figure out how to get my code to work. Unfortunately, I am limited to using DirectShow.

    Essentially, I am using a QAxWidget to build a directshow filtergraph with video playback handled by a vmr9 filter.

    - The graph is completely connected
    - Running the program without windowless mode on results in a separate window opening and playing information properly
    - Running the program in windowless mode results in no video (although the frame the QAxWidget is in does appear)
    - The video (trying a simple file atm) does play in windowless mode (I can check via an ffdshow utility), I just can't see it.


    I've attached the files, and included them below for convenience.


    Main.cpp
    Qt Code:
    1. #include <qapplication.h>
    2. #include "playerwindow.h"
    3. int main(int argc, char *argv[])
    4. {
    5. RedirectIOToConsole();
    6.  
    7. QApplication app(argc, argv);
    8. PlayerWindow playerWin;
    9. playerWin.show();
    10. return app.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 


    playerwindow.cpp
    Qt Code:
    1. #include "playerwindow.h"
    2. #include <ActiveQt\qaxbase.h>
    3. #include <ActiveQt\qaxwidget.h>
    4. #include <QtGui>
    5. PlayerWindow::PlayerWindow()
    6. {
    7. long lWidth, lHeight;
    8. IMediaEventEx *pMediaEvent;
    9. IMediaControl *pControl;
    10. IGraphBuilder *gBuilder;
    11. IVMRWindowlessControl9* pWindowlessControl;
    12. HRESULT hr = 0;
    13. DWORD reg;
    14. HDC hdc;
    15.  
    16. CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
    17.  
    18. setWindowTitle(tr("Capture Preview"));
    19. setMouseTracking(true);
    20.  
    21. wmp = new QAxWidget(this);
    22. wmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    23. wmp->setGeometry( QRect( 0, 0, 640, 480 ) );
    24.  
    25. QVBoxLayout *mainLayout = new QVBoxLayout;
    26. mainLayout->addWidget(wmp);
    27. setLayout(mainLayout);
    28.  
    29. hr = wmp->setControl( QUuid( CLSID_FilterGraph ) );
    30. hr = wmp->queryInterface(QUuid( IID_IGraphBuilder ), (void**) &gBuilder );
    31.  
    32. hr = gBuilder->QueryInterface(IID_IMediaControl, (void **)&pControl);
    33. hr = gBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent);
    34.  
    35. hr = InitWindowlessVMR((HWND) wmp->winId(), gBuilder, &pWindowlessControl );
    36.  
    37.  
    38. hr = gBuilder->RenderFile(L"C:/AVI_DivX.avi", NULL);
    39. hr = pWindowlessControl->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
    40. if ( SUCCEEDED( hr ) )
    41. {
    42. RECT rcSrc, rcDest;
    43. SetRect( &rcSrc, 0, 0, lWidth, lHeight );
    44.  
    45. GetClientRect( (HWND) wmp->winId( ), &rcDest );
    46. SetRect(&rcDest, 0, 0, rcDest.right, rcDest.bottom);
    47.  
    48. hr = pWindowlessControl->SetVideoPosition( &rcSrc, &rcDest );
    49.  
    50. PAINTSTRUCT ps;
    51. RECT rcClient;
    52. GetClientRect( (HWND) wmp->winId( ), &rcClient );
    53. hdc = BeginPaint( (HWND) wmp->winId( ), &ps );
    54. if( pWindowlessControl != NULL )
    55. {
    56. // Find the region where the application can paint by subtracting
    57. // the video destination rectangle from the client area.
    58. // (Assume that g_rcDest was calculated previously.)
    59. HRGN rgnClient = CreateRectRgnIndirect( &rcClient );
    60. HRGN rgnVideo = CreateRectRgnIndirect( &rcDest );
    61. CombineRgn( rgnClient, rgnClient, rgnVideo, RGN_DIFF );
    62.  
    63. // Paint on window.
    64. HBRUSH hbr = GetSysColorBrush( COLOR_BTNFACE );
    65. FillRgn( hdc, rgnClient, hbr );
    66.  
    67. // Clean up.
    68. DeleteObject( hbr );
    69. DeleteObject( rgnClient );
    70. DeleteObject( rgnVideo );
    71.  
    72. // Request the VMR to paint the video.
    73. HRESULT hr = pWindowlessControl->RepaintVideo( (HWND) wmp->winId( ), hdc );
    74. }
    75. }
    76.  
    77. hr = pControl->Run();
    78. OAFilterState pfs;
    79. hr = pControl->GetState(INFINITE, &pfs);
    80. reg;
    81. AddGraphToRot(gBuilder, &reg);
    82.  
    83. wmp->repaint();
    84. //while(true){
    85. //hr = pWindowlessControl->RepaintVideo((HWND) wmp->winId( ), hdc);
    86. //Sleep(1000);
    87. //}
    88. }
    89.  
    90.  
    91.  
    92. void PlayerWindow::timerEvent(QTimerEvent *event)
    93. {
    94. if (event->timerId() == updateTimer) {
    95. double curPos = wmp->property("CurrentPosition").toDouble();
    96. onPositionChange(-1, curPos);
    97. } else {
    98. QWidget::timerEvent(event);
    99. }
    100. }
    101.  
    102. HRESULT PlayerWindow::InitWindowlessVMR(
    103. HWND hwndApp, // Window to hold the video.
    104. IGraphBuilder* pGraph, // Pointer to the Filter Graph Manager.
    105. IVMRWindowlessControl9** ppWc // Receives a pointer to the VMR.
    106. )
    107. {
    108. if (!pGraph || !ppWc) return E_POINTER;
    109. pVmr = NULL;
    110. IVMRWindowlessControl9* pWc = NULL;
    111. // Create the VMR.
    112. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL,
    113. CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
    114. if (FAILED(hr))
    115. {
    116. return hr;
    117. }
    118.  
    119. // Add the VMR to the filter graph.
    120. hr = pGraph->AddFilter(pVmr, L"Teague Bick");
    121. if (FAILED(hr))
    122. {
    123. pVmr->Release();
    124. return hr;
    125. }
    126. // Set the rendering mode.
    127. IVMRFilterConfig9* pConfig;
    128. hr = pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig);
    129. if (SUCCEEDED(hr))
    130. {
    131. hr = pConfig->SetNumberOfStreams( 1 );
    132. hr = pConfig->SetRenderingMode(VMR9Mode_Windowless);
    133. pConfig->Release();
    134. }
    135. if (SUCCEEDED(hr))
    136. {
    137. // Set the window.
    138. hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWc);
    139. if( SUCCEEDED(hr))
    140. {
    141. hr = pWc->SetVideoClippingWindow(hwndApp);
    142. if (SUCCEEDED(hr))
    143. {
    144. *ppWc = pWc; // Return this as an AddRef'd pointer.
    145. }
    146. else
    147. {
    148. // An error occurred, so release the interface.
    149. pWc->Release();
    150. }
    151. }
    152. }
    153. pVmr->Release();
    154. return hr;
    155. }
    156.  
    157. void PlayerWindow::onPlayStateChange(int, int newState)
    158. {
    159. cout << " Stop hit\n";
    160. }
    161.  
    162. void PlayerWindow::onReadyStateChange(ReadyStateConstants ready)
    163. {
    164. if (ready == Complete) {
    165. double duration = 60 * wmp->property("Duration").toDouble();
    166. seekSlider->setMinimum(0);
    167. seekSlider->setMaximum(int(duration));
    168. seekSlider->setEnabled(true);
    169. }
    170. }
    171.  
    172. void PlayerWindow::onPositionChange(double, double newPos)
    173. {
    174. seekSlider->blockSignals(true);
    175. seekSlider->setValue(int(newPos * 60));
    176. seekSlider->blockSignals(false);
    177. }
    178. void PlayerWindow::sliderValueChanged(int newValue)
    179. {
    180. seekSlider->blockSignals(true);
    181. wmp->setProperty("CurrentPosition", double(newValue) / 60);
    182. seekSlider->blockSignals(false);
    183. }
    184.  
    185. void PlayerWindow::stopFile(){
    186. cout << "Stopping record\n";
    187.  
    188. card->stopRecording();
    189. }
    190.  
    191. void PlayerWindow::openFile()
    192. {
    193.  
    194.  
    195. cout << "Starting to record\n";
    196. card->startRecording();
    197.  
    198. //QString fileName = QFileDialog::getOpenFileName(this,
    199. // tr("Select File"), ".", fileFilters);
    200. //if (!fileName.isEmpty())
    201. // wmp->setProperty("FileName",
    202. // QDir::toNativeSeparators(fileName));
    203. }
    To copy to clipboard, switch view to plain text mode 

    playerwindow.h

    Qt Code:
    1. #pragma once
    2. #ifndef PLAYERWINDOW_H
    3. #define PLAYERWINDOW_H
    4.  
    5. #ifndef _M_IX86
    6. #define _M_IX86 600
    7. #endif
    8.  
    9.  
    10. #ifndef _USE_OLD_IOSTREAMS
    11. using namespace std;
    12. #endif
    13. #include <d3d9.h>
    14. #include <QWidget>
    15. #include <windows.h>
    16. #include <stdio.h>
    17. #include <fcntl.h>
    18. #include <io.h>
    19. #include <iostream>
    20. #include <fstream>
    21. #include <dshow.h>
    22. #include "Video_Header.h"
    23. #include <conio.h>
    24. #include <vmr9.h>
    25.  
    26.  
    27. class QAxWidget;
    28. class QSlider;
    29.  
    30. class PlayerWindow : public QWidget
    31. {
    32. Q_OBJECT
    33. Q_ENUMS(ReadyStateConstants)
    34.  
    35. public:
    36. enum PlayStateConstants { Stopped = 0, Paused = 1, Playing = 2 };
    37. enum ReadyStateConstants { Uninitialized = 0, Loading = 1,
    38. Interactive = 3, Complete = 4 };
    39.  
    40. PlayerWindow();
    41.  
    42. protected:
    43. void timerEvent(QTimerEvent *event);
    44.  
    45. private:
    46. HRESULT InitWindowlessVMR(HWND hwndApp, IGraphBuilder* pGraph,
    47. IVMRWindowlessControl9** ppWc) ;
    48. QAxWidget *wmp;
    49. QToolButton *playPauseButton;
    50. QToolButton *openButton;
    51. QSlider *seekSlider;
    52. QToolButton *stopButton;
    53. QString fileFilters;
    54. int updateTimer;
    55. VideoCard *card;
    56. IBaseFilter* pVmr;
    57. };
    58.  
    59.  
    60. #ifdef _DEBUG
    61.  
    62. // maximum mumber of lines the output console should have
    63. static const WORD MAX_CONSOLE_LINES = 500;
    64. static void RedirectIOToConsole(){
    65. int hConHandle;
    66. long lStdHandle;
    67. CONSOLE_SCREEN_BUFFER_INFO coninfo;
    68. FILE *fp;
    69.  
    70. // allocate a console for this app
    71. AllocConsole();
    72.  
    73. // set the screen buffer to be big enough to let us scroll text
    74. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
    75. coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    76. SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize);
    77.  
    78. // redirect unbuffered STDOUT to the console
    79. lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    80. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    81. fp = _fdopen( hConHandle, "w" );
    82. *stdout = *fp;
    83. setvbuf( stdout, NULL, _IONBF, 0 );
    84.  
    85. // redirect unbuffered STDIN to the console
    86. lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
    87. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    88. fp = _fdopen( hConHandle, "r" );
    89. *stdin = *fp;
    90. setvbuf( stdin, NULL, _IONBF, 0 );
    91.  
    92. // redirect unbuffered STDERR to the console
    93. lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    94. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    95. fp = _fdopen( hConHandle, "w" );
    96. *stderr = *fp;
    97. setvbuf( stderr, NULL, _IONBF, 0 );
    98.  
    99. // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
    100. // point to console as well
    101. ios::sync_with_stdio();
    102. }
    103. #endif
    104. #endif
    To copy to clipboard, switch view to plain text mode 
    Attached Files Attached Files

  2. #2
    Join Date
    Jun 2011
    Posts
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: VMR9 (DirectShow) Windowless and QAxWidget

    After several more hours of banging my head against the wall, I discovered that using the setControl method for the QAxWidget has to be IGNORED in order to display the VMR9 output in the widget. setControl(FilterGraph) just gives the widget control of the filtergraph, not the widget's window.

  3. #3
    Join Date
    Jul 2011
    Posts
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: VMR9 (DirectShow) Windowless and QAxWidget

    Thank you for this. The code samples were helpful, and I got DirectShow video to play inside a QAxWidget. Currently I am using the IVMRWindowlessControl versus the IVMRWindowlessControl9, though. However, I think I'll change this.

    There are a couple of problems with my implementation that I wanted to bring up here to see if you (or anyone else) encountered them.

    First, I have the video playing in a QAxWidget that is placed into a QVBoxLayout. Like so:

    Qt Code:
    1. DirectShowWidget dShowWidget; //my subclassed QAxWidget that is responsible for rendering the video.
    2. QVBoxLayout * pLayout = new QVBoxLayout();
    3. pLayout->addWidget(&dShowWidget);
    4. QWidget * pWidget = new QWidget();
    5. pWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    6. pWidget->setLayout(pLayout);
    7.  
    8. dShowWidget.OpenFile(); //gets a video file name and stores to a member variable
    9. dShowWidget.CreateVideo(); //creates and plays the video.
    10.  
    11. pWidget->show();
    To copy to clipboard, switch view to plain text mode 

    The problem is that the layout does not resize to fit the entire video. This isn't a big problem, though, I'm sure I can putz around with the layout itself and get it to work.
    A larger problem is that when resizing the window (while the application is running, not in code), the video disappears and only reappears after I finish resizing and then single click on the window again. Also, clicking on another application window (i.e., a console, browser window, etc) causes the video to disappear. Basically, the video disappears when the application window loses focus. It only reappears when the window regains focus.

    Do these issues have something to do with the QWidget's paintEvent perhaps overriding the video on a repaint? Will I need to subclass QWidget and implement my own paintEvent to make sure the video is always repainted correctly on the widget's repaint? Any thoughts?

    Thanks,
    EH
    Last edited by hootener; 20th July 2011 at 15:32.

Similar Threads

  1. DirectShow Qt Project
    By srsr in forum Qt-based Software
    Replies: 1
    Last Post: 27th August 2011, 20:56
  2. Webcam DirectShow
    By Sahab in forum General Programming
    Replies: 4
    Last Post: 27th August 2011, 19:34
  3. :: I can to use library DirectShow with Qt? ::
    By CarlosPhelippe in forum Qt Programming
    Replies: 4
    Last Post: 31st August 2009, 13:13
  4. DirectShow and Qt
    By Rayven in forum Qt Programming
    Replies: 2
    Last Post: 24th April 2006, 22:36
  5. Creating a "windowless" software
    By Yorma in forum Qt Programming
    Replies: 7
    Last Post: 9th January 2006, 15:21

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.