|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article demonstrates a simple wrapper class for playing video files with the new DirectShow Video Mixing Renderer 9. In DirectX9, multimedia applications can use a new video renderer to display decoded frames, but this renderer is not the default renderer for compatibility issue. On Windows XP, the default renderer is the VMR7, but on older Windows version it's the Video Renderer. The main difference is performance and overlay mixing capabilities: as older renderer use different versions of DirectDraw API (even older API for the Video Renderer), the VMR9 is based on DirectX Graphics, so it uses the Direct3D capability of your 3D video card. The result is an improved performance on recent 3D cards, better support of overlay mixing, compatibility with all Windows versions that support DirectX9, and some new capability such as de-interlacing and ProcAmp support (contrast, saturation, etc.). So the new VMR9 looks great but it's not the default renderer, regardless of Windows version... We've to build it manually, and this is why I wrote this class. What you need...To run the demo, DirectX9 runtime has to be installed on your system, which must have a Direct3D compatible display adapter. To build, DirectX9 SDK must be installed on your system. The source code was created under Visual C++ 6 SP5. All the tests I've made is on my WinXP box, running an ATI Radeon M7 (kind of Radeon 7500). As I can't check real compatibility with many other Windows releases and video cards, please try with your system and put a word in the forum. Using the codeA first lookAll of the DirectShow graph management and VMR routines are included in one class : class CVMR9Graph { // Constructor / destructor public: CVMR9Graph(); CVMR9Graph(HWND MediaWindow, int NumberOfStream = 4); virtual ~CVMR9Graph(); // Methods public: // Graph configuration void SetNumberOfLayer(int nNumberOfLayer); BOOL SetMediaWindow(HWND MediaWindow); BOOL SetMediaFile(const char* pszFileName, int nLayer = 0); BOOL PreserveAspectRatio(BOOL bPreserve = TRUE); IBaseFilter* AddFilter(const char* pszName, const GUID& clsid); // Graph control BOOL PlayGraph(); BOOL StopGraph(); BOOL ResetGraph(); IMediaEvent* GetPtrMediaEvent(); IMediaControl* GetPtrMediaControl(); IMediaSeeking* GetPtrMediaSeeking(); IBasicAudio* GetPtrBasicAudio(); // Layer control BOOL GetVideoRect(LPRECT pRect); int GetAlphaLayer(int nLayer); BOOL SetAlphaLayer(int nLayer, int nAlpha); DWORD GetLayerZOrder(int nLayer); BOOL SetLayerZOrder(int nLayer, DWORD dwZOrder); BOOL SetLayerRect(int nLayer, RECT layerRect); // Bitmap control BOOL SetBitmap(const char* pszBitmapFileName, int nAlpha, COLORREF cTransColor, RECT bitmapRect); BOOL SetBitmapParams(int nAlpha, COLORREF cTransColor, RECT bitmapRect); // Reflected from window BOOL Repaint(); BOOL Resize(); // helper LPCTSTR GetLastError(); protected: // [...] }; For convenience, header and implementation files contains the DirectShow includes, Direct3D includes, and Step 1 : Building a simple playerBuilding a very simple video player is quite easy:
At this point video playback works but the video wasn't resized with your window... Step 2 : Forwarding eventsYour application have to tell to the graph when the video has to repaint or size:
You can notice that video playback preserves aspect ratio by default. You can change this by a call to Ok, that looks much better... time to play with video mixing. Step 3: Mixing videoMultiple file playback was handled by layers. Each layer plays a video and supports several properties such as ordering, alpha blending, size and position. The video produced by multiple layers is called a composition, and takes the size of the biggest media. Each layer you insert is identified by it's layer index; The following example loads 2 video files and sets an alpha value of 50% to the first: // load media files myGraph.SetMediaFile(0, "C:\\Video1.avi"); myGraph.SetMediaFile(1, "C:\\Video2.mpg"); // set alpha value to video1 myGraph.SetAlphaLayer(0, 50); Alpha value can be set in real time, as show in the demo app. Note 1: I have not been able to mix two DivX files, but only one DivX and other codecs such as MPEG... Don't know why... perhaps a hardware lack, since DirectShow samples seems to have the same troubles. Note 2: The Looks cool on a recent computers... Can we add more? Step 4 : Setting an overlay bitmapOverlay bitmap in To set an overlay bitmap, call
Overlay bitmap is a cool feature that can be used to:
Last step: Go further awayTo keep the class simple, playback control is minimal, but you can do more by getting some DirectShow COM interfaces:
Note: After the use of an interface, you have to release it by a call to Known issueWhen the graph is running, a call to A call to When resizing video window in demo app, there is some flickering... That's because it's a MFC window with the standard // TODO : some improvementsThe There's no support for de-interlacing or ProcAmp control (ProcAmp don't work on my current ATI display drivers... Grrr) There's no support for dynamic overlay bitmap... As a Direct3D surface can be locked and modified by a device context handle or even directly, this can be quite simple...don't know why I din't code it... probably a small lack of sleep.
|
||||||||||||||||||||||