PDA

View Full Version : Playing multiple graphs simultaniously


PRemmerswaal
06-29-2006, 11:40 AM
Hi All, I'm trying to do the following:

A DV camera preview split up in 16 pieces (4X4) and seperately being able to pause the individual streams.

In the code I first give a preview in one screen of 720 by 576, next people can press the folowing keys:

1 2 3 4
q w e r
a s d f
z x c v

These keys correspond with the individual video screens.

If for example you press one, window one pauses, when you press one again, the image starts playing real time again.

Currently the code is such that when you press a key, the corresponding video freezes, but all the other screen dissappear. I really need the other 15 to remain visible as well.

This is the code for now, it's a lot though... :-)

I hope someone knows something about this, because all the c++ forums are siomply nog very graphically minded. Thanks a million in advance for reading this :-)


#include <atlbase.h>
#include <windows.h>
#include <dshow.h>
#include <stdio.h>
#include <qedit.h>

#include "PlayCap.h"

// An application can advertise the existence of its filter graph
// by registering the graph with a global Running Object Table (ROT).
// The GraphEdit application can detect and remotely view the running
// filter graph, allowing you to 'spy' on the graph with GraphEdit.
//
// To enable registration in this sample, define REGISTER_FILTERGRAPH.
//
#define REGISTER_FILTERGRAPH


//
// Global data
//
HWND ghApp=0;
HWND ghPic=0;
DWORD g_dwGraphRegister=0;
int VidWidth = 720;
int VidHeight = 576;

BOOL Grabber[16];

IVideoWindow * g_pVW = NULL;
IBasicVideo * g_pBV = NULL;
IMediaControl * g_pMC = NULL;
IMediaEventEx * g_pME = NULL;
IGraphBuilder * g_pGraph = NULL;
IBaseFilter * pSrcFilter=NULL;
IBaseFilter * pGrabberF = NULL;
ISampleGrabber * pGrabber;
ICaptureGraphBuilder2 * g_pCapture = NULL;
PLAYSTATE g_psCurrent = Stopped;

HRESULT CaptureVideo()
{
HRESULT hr;

// Get DirectShow interfaces
hr = GetInterfaces();
if (FAILED(hr))
{
Msg(TEXT("Failed to get video interfaces! hr=0x%x"), hr);
return hr;
}

// Attach the filter graph to the capture graph
hr = g_pCapture->SetFiltergraph(g_pGraph);
if (FAILED(hr))
{
Msg(TEXT("Failed to set capture filter graph! hr=0x%x"), hr);
return hr;
}

// Use the system device enumerator and class enumerator to find
// a video capture/preview device, such as a desktop USB video camera.
hr = FindCaptureDevice(&pSrcFilter);
if (FAILED(hr))
{
// Don't display a message because FindCaptureDevice will handle it
return hr;
}

// Add Capture filter to our graph.
hr = g_pGraph->AddFilter(pSrcFilter, L"Video Capture");

if (FAILED(hr))
{
Msg(TEXT("Couldn't add the capture filter to the graph! hr=0x%x\r\n\r\n")
TEXT("If you have a working video capture device, please make sure\r\n")
TEXT("that it is connected and is not being used by another application.\r\n\r\n")
TEXT("The sample will now close."), hr);
pSrcFilter->Release();
return hr;
}

hr = g_pGraph->AddFilter(pGrabberF, L"Sample Grabber");

if (FAILED(hr))
{
return hr;
}

// Render the preview pin on the video capture filter
// Use this instead of g_pGraph->RenderFile
hr = g_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pSrcFilter, NULL, NULL);


if (FAILED(hr))
{
Msg(TEXT("Couldn't render the video capture stream. hr=0x%x\r\n")
TEXT("The capture device may already be in use by another application.\r\n\r\n")
TEXT("The sample will now close."), hr);
pSrcFilter->Release();
return hr;
}

// Now that the filter has been added to the graph and we have
// rendered its stream, we can release this reference to the filter.
pSrcFilter->Release();


// Set video window style and position
hr = SetupVideoWindow();

if (FAILED(hr))
{
Msg(TEXT("Couldn't initialize video window! hr=0x%x"), hr);
return hr;
}


#ifdef REGISTER_FILTERGRAPH
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
hr = AddGraphToRot(g_pGraph, &g_dwGraphRegister);
if (FAILED(hr))
{
Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr);
g_dwGraphRegister = 0;
}
#endif

// Start previewing video data
hr = g_pMC->Run();
if (FAILED(hr))
{
Msg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}

// Remember current state
g_psCurrent = Running;

return S_OK;
}


HRESULT FindCaptureDevice(IBaseFilter ** ppSrcFilter)
{
HRESULT hr;
IBaseFilter * pSrc = NULL;
CComPtr <IMoniker> pMoniker =NULL;
ULONG cFetched;

if (!ppSrcFilter)
return E_POINTER;

// Create the system device enumerator
CComPtr <ICreateDevEnum> pDevEnum =NULL;

hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **) &pDevEnum);
if (FAILED(hr))
{
Msg(TEXT("Couldn't create system enumerator! hr=0x%x"), hr);
return hr;
}

// Create an enumerator for the video capture devices
CComPtr <IEnumMoniker> pClassEnum = NULL;

hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
if (FAILED(hr))
{
Msg(TEXT("Couldn't create class enumerator! hr=0x%x"), hr);
return hr;
}

// If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but pClassEnum will be NULL.
if (pClassEnum == NULL)
{
MessageBox(ghApp,TEXT("No video capture device was detected.\r\n\r\n")
TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n")
TEXT("to be installed and working properly. The sample will now close."),
TEXT("No Video Capture Hardware"), MB_OK | MB_ICONINFORMATION);
return E_FAIL;
}

// Use the first video capture device on the device list.
// Note that if the Next() call succeeds but there are no monikers,
// it will return S_FALSE (which is not a failure). Therefore, we
// check that the return code is S_OK instead of using SUCCEEDED() macro.
if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
{
// Bind Moniker to a filter object
hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);
if (FAILED(hr))
{
Msg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
return hr;
}
}
else
{
Msg(TEXT("Unable to access video capture device!"));
return E_FAIL;
}

// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
*ppSrcFilter = pSrc;

return hr;
}


HRESULT GetInterfaces(void)
{
HRESULT hr;

// Create the filter graph
hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **) &g_pGraph);
if (FAILED(hr))
return hr;


// Create the Sample Grabber filter.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pGrabberF);
if (FAILED(hr))
return hr;

// Create the capture graph builder
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **) &g_pCapture);
if (FAILED(hr))
return hr;


// Obtain interfaces for media control and Video Window
hr = g_pGraph-> QueryInterface(IID_IMediaControl,(LPVOID
*) &g_pMC);
if (FAILED(hr))
return hr;

hr = g_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &g_pVW);
if (FAILED(hr))
return hr;

hr = g_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) &g_pME);
if (FAILED(hr))
return hr;

hr = g_pGraph->QueryInterface(IID_IBasicVideo, (LPVOID *) &g_pBV);
if (FAILED(hr))
return hr;

hr = pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
if (FAILED(hr))
return hr;


// Set the window handle used to process graph events
hr = g_pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0);

return hr;
}


void CloseInterfaces(void)
{
// Stop previewing data
if (g_pMC)
g_pMC->StopWhenReady();

g_psCurrent = Stopped;

// Stop receiving events
if (g_pME)
g_pME->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0);

// Relinquish ownership (IMPORTANT!) of the video window.
// Failing to call put_Owner can lead to assert failures within
// the video renderer, as it still assumes that it has a valid
// parent window.
if(g_pVW)
{
g_pVW->put_Visible(OAFALSE);
g_pVW->put_Owner(NULL);
}

#ifdef REGISTER_FILTERGRAPH
// Remove filter graph from the running object table
if (g_dwGraphRegister)
RemoveGraphFromRot(g_dwGraphRegister);
#endif

// Release DirectShow interfaces
SAFE_RELEASE(g_pMC);
SAFE_RELEASE(g_pME);
SAFE_RELEASE(g_pVW);
SAFE_RELEASE(g_pGraph);
SAFE_RELEASE(g_pCapture);
SAFE_RELEASE(g_pBV);
}


HRESULT SetupVideoWindow(void)
{
HRESULT hr;

// Set the video window to be a child of the main window
hr = g_pVW->put_Owner((OAHWND)ghApp);
if (FAILED(hr))
return hr;

// Set video window style
hr = g_pVW->put_WindowStyle(WS_POPUP);
if (FAILED(hr))
return hr;

// Use helper function to position video window in client rect
// of main application window
ResizeVideoWindow();

// Make the video window visible, now that it is properly positioned
hr = g_pVW->put_Visible(OATRUE);
if (FAILED(hr))
return hr;

return hr;
}


void ResizeVideoWindow(void)
{
// Resize the video preview window to match owner window size
if (g_pVW)
{
RECT rc;

// Make the preview video fill our window
GetClientRect(ghApp, &rc);
g_pVW->SetWindowPosition((rc.right-VidWidth)/2,(rc.bottom-VidHeight)/2,VidWidth,VidHeight);

}
}


void PauseClip(int Screen)
{

RECT rc;

if (Grabber[Screen] == FALSE){
Grabber[Screen] = TRUE;
pGrabber->SetOneShot(TRUE);
pGrabber->SetBufferSamples(FALSE);
}
else{
Grabber[Screen] = FALSE;
g_pMC->Stop();
g_pMC->Run();
pGrabber->SetOneShot(FALSE);
}

GetClientRect(ghApp, &rc);


//this is just one, there are originally 16, but I removed them to increase readability :-)

if (Screen == 16){
g_pBV->SetSourcePosition( VidWidth/4 + VidWidth/4 + VidWidth/4, VidHeight/4 + VidHeight/4 + VidHeight/4, VidWidth/4 , VidHeight/4);
g_pVW->SetWindowPosition((rc.right-VidWidth)/2 + VidWidth/4 + VidWidth/4 + VidWidth/4,(rc.bottom-VidHeight)/2 + VidHeight/4 + VidHeight/4 + VidHeight/4,VidWidth/4,VidHeight/4);
}
}


HRESULT ChangePreviewState(int nShow)
{
HRESULT hr=S_OK;

// If the media control interface isn't ready, don't call it
if (!g_pMC)
return S_OK;

if (nShow)
{
if (g_psCurrent != Running)
{
// Start previewing video data
hr = g_pMC->Run();
g_psCurrent = Running;
}
}
else
{
// Stop previewing video data
hr = g_pMC->StopWhenReady();
g_psCurrent = Stopped;
}

return hr;
}


#ifdef REGISTER_FILTERGRAPH

HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
IMoniker * pMoniker;
IRunningObjectTable *pROT;
WCHAR wsz[128];
HRESULT hr;

if (!pUnkGraph || !pdwRegister)
return E_POINTER;

if (FAILED(GetRunningObjectTable(0, &pROT)))
return E_FAIL;

wsprintfW(wsz, L"FilterGraph %08x pid %08x

I hope someone knows something about this, because all the c++ forums are simply not very graphically minded. Thanks a millions in advance just for reading this :-)

CGTalk Moderation
06-29-2006, 11:40 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.