I am writing directshow application. Below is the code that works fine but crashes with the error message "App.exe has stopped working". The entire code is written below. Please note that I am using Windows SDK 7.0 which does not have atlbase.h
and hence I cannot use CComPtr<IBaseFilter> myFilter;
type of pointer declaration which is supposed to clear memory at exit.
EDIT: The application crashes only if I connect all filters explicitly. In this case, the destructor of my filter is not called. If I just connect source filter to renderer (which will internally connect my filter and a demux filter), the destructor of my filter is called and there is no crash. I have put the macro MANUAL_CONNECT
over the code which causes the crash. I have removed RemoveFilter
call and replaced it with Release
call.
I am writing the application code here:
void main(WORD32 argc, CHAR *argv[])
{
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
{
IGraphBuilder *pGraph = NULL;
IFileSourceFilter *pFileSourceFilter = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
IBaseFilter *pSource = NULL;
IBaseFilter *pVideoDecode = NULL;
IBaseFilter *pVideoRenderer = NULL;
IEnumPins *pEnumPins = NULL;
IPin *pPinIn = NULL;
IPin *pPinOut = NULL;
ULONG fetched;
PIN_INFO PinInfo;
IEnumFilters *pEnum = NULL;
BOOL stop = FALSE;
int i;
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pSource);
hr = pGraph->AddFilter(pSource, NULL);
hr = pSource->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSourceFilter);
hr = pFileSourceFilter->Load(L"input.mp4", NULL);
// Create Ittiam HEVC Decoder instance
hr = CoCreateInstance(CLSID_ivdec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoDecode);
// Create Video Renderer instance. We have used default video renderer
hr = CoCreateInstance(CLSID_VideoRendererDefault, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoRenderer);
// Add decoder filter to the filter graph
hr = pGraph->AddFilter(pVideoDecode, NULL);
// Add renderer filter to the filter graph
hr = pGraph->AddFilter(pVideoRenderer, NULL);
/**************************************************************/
/* -- Connecting source filter to demux filter starts here -- */
/**************************************************************/
// Enumerate pins of the source filter
hr = pSource->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of source filter. Source filter has only output pin, so no check required
hr = pEnumPins->Next(1, &pPinOut, &fetched);
hr = pEnumPins->Release();
#if MANUAL_CONNECT
// Enumerate pins of the decoder filter
hr = pVideoDecode->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of decoder filter. Decoder filter has 2 pins, so ensure the selected pin is input pin.
// If not, get another pin
hr = pEnumPins->Next(1, &pPinIn, &fetched);
hr = pPinIn->QueryPinInfo(&PinInfo);
if(PINDIR_OUTPUT == PinInfo.dir)
{
hr = pPinIn->Release();
hr = pEnumPins->Next(1, &pPinIn, &fetched);
}
// Connect output pin of demux filter to input pin of decoder filter
hr = pGraph->Connect(pPinOut, pPinIn);
/*************************************************************/
/* -- Connecting demux filter to decoder filter ends here -- */
/*************************************************************/
/******************************************************************/
/* -- Connecting decoder filter to renderer filter starts here -- */
/******************************************************************/
// Enumerate pins of the decoder filter
hr = pVideoDecode->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of decoder filter. Decoder filter has 2 pins, so ensure the selected pin is output pin.
// If not, get another pin
hr = pEnumPins->Next(1, &pPinOut, &fetched);
hr = pPinOut->QueryPinInfo(&PinInfo);
if(PINDIR_INPUT == PinInfo.dir)
{
hr = pPinOut->Release();
hr = pEnumPins->Next(1, &pPinOut, &fetched);
}
hr = pEnumPins->Release();
#endif
// Enumerate pins of the renderer filter
hr = pVideoRenderer->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of renderer filter. Renderer filter has only input pin, so no check required
hr = pEnumPins->Next(1, &pPinIn, &fetched);
hr = pPinIn->QueryPinInfo(&PinInfo);
// Connect output pin of decoder filter to input pin of renderer filter
hr = pGraph->Connect(pPinOut, pPinIn);
/****************************************************************/
/* -- Connecting decoder filter to renderer filter ends here -- */
/****************************************************************/
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
hr = pControl->Stop();
hr = pSource->Release();
hr = pVideoDecode->Release();
hr = pControl->Release();
hr = pEvent->Release();
hr = pGraph->Release();
}
CoUninitialize();
printf("Exiting main!!\n");
}
I have removed error checks from the post but I have all error checks in my code. I can see the Exiting main!!
print but than the application crashes. Any suggestions on how to debug this? Please let me know if any information is missing. I am using Microsoft Visual C++ 2010 Express for my development.