Before I begin, this article is not going to get too intensive in the use of DirectShow. DirectShow has a lot of potential, but since many of it's features which could be used with gaming are so obscure or just plain useless and complex, I will not really touch on them. Instead, I will focus mainly on setting up DirectShow and achieving basic use which could produce good game functionality.
As far as there being a future for this article, as I have seen no other articles which touch specifically on DirectShow there is a good chance I will extend on this furthur in the near, and possibly later future, getting into more detail in each additional article.
This article, although not necessarily limited to it, will be written with the DirectX 8.0 API in mind, including the DirectShow API which is not distributed by default with DirectX 8.
[size="5"]Introduction to DirectShow
Prior to DirectX 8.0 you would to have downloaded DirectShow as a seperate SDK, although I will be dealing with the DirectX 8 release of DShow. To use this article, you should have some primitive comprehension of how the COM interface works.
Without DirectShow it would be difficult, although not impossible, to create a video and play it to a screen. One possibility would be to create a 3D object and render an audio-visual interleave as a texture. This, however, creates a problem with playing the audio, and synching the two sources when necessary. With DirectShow, all you have to do is create the control interfaces, at the very minimum, in which you can play the video. DirectShow will then take care of splitting the video and audio, synching it, and handling most events which could arise within the playback of the file. Of course one could attempt to write their own timers, and library to render, play, and synch the video with the audio on a DirectDraw surface, or in any other manner, but this would be a hassle when DirectShow already provides that functionality.
[size="5"]The Very Basics
The very first thing you are going to want to do is to create a windows application which includes a window layout, registers the callback, and registers the window class. To use DirectShow you will require that dshow.h is included in the source file, and that the project is linked to strmiids.lib
Next, we will need to create a few globals which we will use to control the playback and create the interface to playback with.
You should get this:
source.cpp:
#include
#include
//Globals:
static IGraphBuilder *pGB = NULL;
static IMediaControl *pMC = NULL;
static IVideoWindow *pVW = NULL;
static IMediaEventEx *pME = NULL;
static HWND g_hwnd = 0;
...
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR lpCmdLine, int mCmdShow){
CoInitialize(NULL);
...
}
Now we need to create the component interface in which we will initialize all other objects and eventually play the file. To initialize DirectShow you make this call:
//This creates the filter graph manager
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGB);
//Query COM interface
pGB->QueryInterface(IID_IMediaControl, (void **)&pMC);
pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW);
pGB->RenderFile(L"test.avi",NULL);
- The "L" is used to convert the filename from an ASCII string to a Wide Character string.
- The only compression types of playable media thus far supported by DirectShow are:
- Microsoft Windows Media Video codec version 7.0*
- ISO MPEG-4 video version 1.0*
- Microsoft MPEG-4 version 3*
- Sipro Labs ACELP*
- Windows Media Audio*
- MPEG Audio Layer-3 (MP3) (decompression only)
- Digital Video (DV)
- MPEG-1
- MJPEG
- Indeo
- Voxware*
- Cinepak
All you have to do now when the file stops is cleanup.//Set the parents window
pVW->put_Owner((OAHWND)g_hwnd);
//Sets the child window
pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
//here we create a RECT in which to draw the child window on
RECT vwrect;
//get the size of the Parent
GetClientRect(g_hwnd,&vwrect);
//Set the Child to this position
pVW->SetWindowPosition(0,0,vwrect.right,vwrect.bottom);
//and now the long awaited play
pGB->Run();
pVW->put_Visible(OAFALSE);
pVW->put_Owner(NULL);
pMC->Release();
pVW->Release();
pGB->Release();
[size="5"]Handling Events
This is great, now with the information that was specified, it is possible to load and play a video file to the screen with minimal effort, so long as the compression format of the file is one of those supported by DirectShow. The only problem now remains that when the file plays, the application stops, and, well, nothing else occures. This brings on the question of using event handlers to aid in controlling the playback of the video.
This is where ImediaEventEx comes into play. You may want to revisit the globals uptop and add the following line:
Windows will allow private messages to be specified to the callback function with the values of WM_APP through 0xBFFF. The define above will define one of those callback events.#define WM_P_GRAPHNOTIFY WM_APP + 1
When initializing the component interfaces, you will have to add the following code:
Setting WM_P_GRAPHNOTIFY as a valid windows callback message is just as simple as executing the following line:pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME);
The first argument would be the window in which to send the messages to, in this case the parent window, also g_hwnd. The second argument is the message that will be sent, and the third argument is which instance of DirectShow to send this for.pME->SetNotifyWindow((OAHWND)g_hwnd, WM_P_GRAPHNOTIFY, 0);
Because Windows does not include any useful information in the wparam or lparams at this point, we have to create another function which will check the DirectShow message Queue for us.
In this situation, because Windows messages and DirectShow messages are asynchronous, we will keep checking the queue for messages so there is never a flood or pool of unchecked messages until there is an error, when we know it is empty and safe to stop. Because we know that there is a message waiting for use, when we call GetEvent, we will pass 0 as the fourth argument to specify no timeout. After we retreive an event, we will call FreeEventParams to release any resources used to check the queue.case(msg) WM_P_GRAPHNOTIFY:
HandleEvent();
break;
...
void HandleEvent(){
long evCode, param1, param2;
HRESULT hr;
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
hr = pEvent->FreeEventParams(evCode, param1, param2);
if ((EC_COMPLETE == evCode) || (EC_USERABORT == evCode))
{
CleanUp();
break;
}
}
}
[size="5"]Conclusion
There are many more methods of applying DirectShow for use om a game, for instance for playing video trailers, cutscenes, or any media, would be that it can be rendered to a FullScreen DirectDraw surface while in Exclusive mode.
Although I have not attempted it at this point, it is in my belief that it is possible to render the video similarly to what I have shown above to a non-exclusive DirectDraw environment. My best guess would be to set the window to the entire screen, and remove the borders; let me know if this works for anyone.
I am greatly considering adding to this article in the future, if you have any comments or questions, email myself at [email="kurifu@aura-games.com"]kurifu@aura-games.com[/email]. My next idea I think I will discuss playing Fullscreen video in DirectDraw Exclusive mode.
Kurifu Roushu [email="kurifu@aura-games.com"]kurifu@aura-games.com[/email]
http://www.aura-games.com
Wise management of funds is vital in gambling. Tower. bet promotes responsible gameplay through features such as its standout slot named https://tower.bet/en-IN/game/nexus . By setting limits, making thoughtful use of bonuses, and staying within your budget, you can enjoy a well-rounded experience while also having access to several options specifically designed for those who are mindful about spending their money