DirectShow filter, video renderer and filter graph manager
DirectShow video renderer and filter graph manager
The filter graph manager (FGM) may include several DirecthShow filters.
The FGM can be constructed, controlled and its event can be captured and
processed at application level.
IGraphBuilder* g_pGraphBuilder = NULL; // to access the FGM
IMediaControl* g_pMediaControl = NULL; // to control the media, run/stop
etc.
IMediaEventEx* g_pMediaEvent
= NULL; // to get event and notifications from FGM
IMediaPosition* g_pMediaPosition
= NULL;
//
to do seek function
// the following code does the init()
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void**)&g_pGraphBuilder);
if (FAILED(hr)) return -1;
g_pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&g_pMediaControl);
g_pGraphBuilder->QueryInterface(IID_IMediaEvent, (void**)&g_pMediaEvent);
g_pGraphBuilder->QueryInterface(IID_IMediaPosition, (void**)&g_pMediaPosition);
g_pMediaEvent->SetNotifyWindow((OAHWND)g_AppWindow, WM_GRAPHEVENT, 0); //
set the current window to handle GFM events
g_pMediaEvent->SetNotifyFlags(0); // turn on
notifications
//in the following WindowProc() callfaback function,
#define WM_GRAPHEVENT WM_USER // define a custom window message for graph events
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
…
switch (uMsg)
{
case WM_COMMAND: // handles windows commands and messages
switch (LOWORD(wParam))
{
case ID_FILE_OPEN:
…
}
case WM_GRAPHEVENT: // handles user defined msg, here generated by FGM
OnGraphEvent();
break;
}
//in the OnGraphEvent() we handle all the filter graph events at
application level
void OnGraphEvent()
{
long EventCode, Param1, Param2;
g_pMediaEvent->CancelDefaultHandling(EC_REPAINT); // test
by james, to remove
while
(g_pMediaEvent->GetEvent(&EventCode, &Param1, &Param2, 0) != E_ABORT)
{
switch (EventCode)
{
case EC_COMPLETE:
if (!g_Looping)
g_pMediaControl->Stop();
g_pMediaPosition->put_CurrentPosition(0); // reset
to beginning
break;
case EC_PAUSED: // just notification only to app. FGM already paused the video
Break
case EC_CONTENTPROPERTY_CHANGED: // my user defined msg OutputDebugStringW(L"EC_CONTENTPROPERTY_CHANGED recieved - james.\n");
break;
default:
break;
}
g_pMediaEvent->FreeEventParams(EventCode,
Param1, Param2);
}
Note here I captured CONTENTPROPERTY_CHANGED event here at application level. This event by default is not supported in directshow, but we could use this as user defined message. The message-data-flow will be something like below.
DirectShow filters --> Filter Graph Manager --> Application
Directshow filter such as a video renderer can generate a notification by calling the function NotifyEvent(EC_CONTENTPROPERTY_CHANGED, S_OK, 0) inside the DirectShow filter; Then, this will send notification to filter graph manager. For most messages and notifications, normally FGM will process or hide some messages such as EC_REPAINT notifications to application layer since usually this is transparent to applications. But for event such as EC_COMPLETE, FGM will forward this notification to upper levels so that application layer can capture this event, as shown in the code above. Here I am using a special event code CONTENTPROPERTY_CHANGED to implement my own task, because I know FGM will not hide or do anything when my renderer filter send this notification to FGM. And then at application layer, I can capture this event. The reason I am doing this is because for every DoRenderSample() function call, I want to notify the application layer that a video frame has changed, and then I might want to do something for example doing backlight control per frame basis. The reason why I do not want to do backlight control inside the directshow video renderer filter is because the communication to my i2c device seems to stall the video playback and affect the playback performance. So I prefer to do this separate control using a different thread at application layer, not creating any impact on the video playback.
The cleanup code is shown below.
void CleanUpDirectShow()
{
HELPER_RELEASE(g_pMediaPosition);
HELPER_RELEASE(g_pMediaEvent);
HELPER_RELEASE(g_pMediaControl);
HELPER_RELEASE(g_pGraphBuilder);
}

0 Comments:
Post a Comment
<< Home