I have been trying to figure out the cause of an read access memory exception and could track down the problem a bit but didn't find its exact source. The problem seems to be triggered in the following code
HRESULT MCMyOutputPin::EnumMediaTypes(IEnumMediaTypes** types)
{
MyMediaHandler* myhandler;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_MyMediaHandler, NULL, CLSCTX_INPROC_SERVER, IID_IEnumMediaTypes, (void **) & myhandler);
ASSERT(types[0] != NULL);
types[0] = myhandler; //This causes the error
return hr;
}
If i replace that line with
CBaseOutputPin::EnumMediaTypes(types);
The error is not caused, but i also don't have the desired functionality
Using the debugger and integrated disassembler i can see that the cpu reads the invalid address in the
RtlFreeHeap function.
So I guess it tries to free something that doesn't exit there any more.
For completeness here is the whole class:
#include "CMyOutPutPin.h"
#include <fstream>
#include <dvdmedia.h>
#include "MyMediaHandler.h"
MCMyOutputPin::MCMyOutputPin(MyFilter* parent, HRESULT *phr, LPCWSTR pName) : CBaseOutputPin(NAME("MyOutPutPin"), parent, &parent->m_lock_filter, phr, pName)
{
myLogger = new MyLogger();
this->isConnected = FALSE;
}
BOOL MCMyOutputPin::IsConnected()
{
return this->isConnected;
}
MCMyOutputPin::~MCMyOutputPin()
{
delete myLogger;
}
HRESULT MCMyOutputPin::Connect(IPin* pPin, const AM_MEDIA_TYPE *pmt)
{
/*VIDEOINFOHEADER2* header2 = (VIDEOINFOHEADER2 *)CoTaskMemAlloc(112);
RECT rSource = {
0,
0,
256,
240
};
RECT rcTarget = {
0,
0,
256,
240
};
header2->rcSource = rSource;
header2->rcTarget = rcTarget;
header2->dwBitRate = 0;
header2->dwBitErrorRate = 0;
header2->AvgTimePerFrame = 333333;
header2->dwInterlaceFlags = NULL;
header2->dwCopyProtectFlags = NULL;
header2->dwPictAspectRatioX = 0x00000010;
header2->dwPictAspectRatioY = 0x0000000f;
this->isConnected = TRUE;
const AM_MEDIA_TYPE constType = {
MEDIATYPE_Video,
MEDIASUBTYPE_NV12,
TRUE,
FALSE,
92160,
FORMAT_VIDEOINFO2,
NULL,
112,
(BYTE *)header2
};*/
/*IEnumMediaTypes **pEnum = new IEnumMediaTypes*[10];
HRESULT hr = this->EnumMediaTypes(pEnum);
if (FAILED(hr)) return hr;
AM_MEDIA_TYPE **mediapmt = NULL;
while (hr = (*pEnum)->Next(1, mediapmt, NULL))
{
if (mediapmt == NULL)
{
break;
}
hr = pPin->ReceiveConnection(this, *mediapmt);
if (hr == S_OK)
{
return S_OK;
}
}
return VFW_E_TYPE_NOT_ACCEPTED;*/
return VFW_E_TYPE_NOT_ACCEPTED;
}
HRESULT MCMyOutputPin::CheckMediaType(const CMediaType *pmt)
{
myLogger->LogDebug("On CheckMediaType", L"D:\\TEMP\\yc.log");
return S_OK;
}
HRESULT MCMyOutputPin::SetMediaType(const CMediaType *pmt)
{
return CBaseOutputPin::SetMediaType(pmt);
}
HRESULT MCMyOutputPin::CompleteConnect(IPin *pReceivePin)
{
return CBaseOutputPin::CompleteConnect(pReceivePin);
}
HRESULT MCMyOutputPin::BreakConnect()
{
return CBaseOutputPin::BreakConnect();
}
HRESULT MCMyOutputPin::GetMediaType(int i, CMediaType *pmt)
{
if (i < 0)
{
myLogger->LogDebug("Invalid arg in getmediatype", L"D:\\TEMP\\yc.log");
return E_INVALIDARG;
}
if (i == 0)
{
myLogger->LogDebug("On GetMediaType", L"D:\\TEMP\\yc.log");
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_NV12;
pmt->formattype = GUID_NULL;
pmt->bFixedSizeSamples = TRUE;
pmt->bTemporalCompression = FALSE;
pmt->lSampleSize = 1;
pmt->cbFormat = 0;
return S_OK;
}
return VFW_S_NO_MORE_ITEMS;
}
HRESULT MCMyOutputPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProps)
{
myLogger->LogDebug("On DecideBufferSIze", L"D:\\TEMP\\yc.log");
ALLOCATOR_PROPERTIES act;
HRESULT hr;
// by default we do something like this...
pProps->cbAlign = 1;
pProps->cBuffers = 1;
pProps->cbBuffer = this->CurrentMediaType().lSampleSize;
pProps->cbPrefix = 0;
hr = pAlloc->SetProperties(pProps, &act);
if (FAILED(hr)) return hr;
// make sure the allocator is OK with it.
if ((pProps->cBuffers > act.cBuffers) ||
(pProps->cbBuffer > act.cbBuffer) ||
(pProps->cbAlign > act.cbAlign))
return E_FAIL;
return NOERROR;
}
STDMETHODIMP MCMyOutputPin::Notify(IBaseFilter *pSender, Quality q)
{
// right now we don't do anything ...
return NOERROR;
}
HRESULT MCMyOutputPin::Deliver(IMediaSample* sample)
{
myLogger->LogDebug("In Outputpin Deliver", L"D:\\TEMP\\yc.log");
HRESULT hr = m_pInputPin->Receive(sample);
return CBaseOutputPin::Deliver(sample);
//Forward to filter
}
HRESULT MCMyOutputPin::AgreeMediaType(IPin * pin, const CMediaType* pmt)
{
myLogger->LogDebug("On AgreeMediaType", L"D:\\TEMP\\yc.log");
ASSERT(pmt != NULL);
if (pmt->majortype == MEDIATYPE_Video || pmt->majortype == MEDIATYPE_Stream)
{
return S_OK;
}
myLogger->LogDebug("AgreeMediaType cuould not agree", L"D:\\TEMP\\yc.log");
return VFW_E_NO_ACCEPTABLE_TYPES;
}
HRESULT MCMyOutputPin::EnumMediaTypes(IEnumMediaTypes** types)
{
MyMediaHandler* myhandler;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_MyMediaHandler, NULL, CLSCTX_INPROC_SERVER, IID_IEnumMediaTypes, (void **) & myhandler);
ASSERT(types[0] != NULL);
types[0] = myhandler;
return hr;
}
Also here is the code for the used com component
#include "MediaHandler.h"
MediaHandler::MediaHandler(const TCHAR* name, LPUNKNOWN pUnk) :CUnknown(name, pUnk)
{
InitMediaTypes();
}
MediaHandler::~MediaHandler()
{
}
HRESULT MediaHandler::Clone(IEnumMediaTypes **pEnum)
{
return S_OK;
}
HRESULT MediaHandler::Next(ULONG cMediaTypes,
AM_MEDIA_TYPE **ppMediaTypes,
ULONG *pcFetched)
{
for (int i = 0; i < cMediaTypes; i++)
{
ppMediaTypes[i] = *m_pMediaType;
m_pMediaType++;
}
return S_OK;
}
HRESULT MediaHandler::Reset()
{
return S_OK;
*m_pMediaType = m_pMediaTypeStart;
}
HRESULT MediaHandler::Skip(
ULONG cMediaTypes)
{
for (int i = 0; i < cMediaTypes; i++)
{
m_pMediaType++;
}
return S_OK;
}
void MediaHandler::InitMediaTypes()
{
m_pMediaType = new AM_MEDIA_TYPE*[10];
AM_MEDIA_TYPE *first = new AM_MEDIA_TYPE();
first->majortype = MEDIATYPE_Video;
first->majortype = MEDIASUBTYPE_NV12;
first->bFixedSizeSamples = TRUE;
first->bTemporalCompression = FALSE;
first->lSampleSize = 0;
first->formattype = FORMAT_VideoInfo;
RECT rSource = {
0,
0,
256,
240
};
RECT rcTarget = {
0,
0,
256,
240
};
BITMAPINFOHEADER bitmapinfo = {
40,
256,
240,
2,
12,
0x3231564e,
92160,
0,
0,
0,
0
};
VIDEOINFOHEADER *header = (VIDEOINFOHEADER *)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
header->rcSource = rSource;
header->rcTarget = rcTarget;
header->dwBitErrorRate = 0;
header->dwBitRate = 0;
header->AvgTimePerFrame = 333333;
first->pbFormat = (BYTE *)header;
first->cbFormat = sizeof(header);
m_pMediaType[0] = first;
m_pMediaTypeStart = m_pMediaType[0];
}
STDMETHODIMP MediaHandler::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
if (riid == IID_IEnumMediaTypes) {
return GetInterface((IEnumMediaTypes *)this, ppv);
}
return S_FALSE;
}
Why does the call to RtlFreeHeap triggers a memory acces exception? When is RtlFreeHeap called? What objects in my code could have been initialized or destroyed the wrong way?
I hope I included everything relevant and that you can understand my problem
Thanks for any answers
Apart from pretty unexpected desire to override EnumMediaTypes
this way, the following is incorrect:
HRESULT MCMyOutputPin::EnumMediaTypes(IEnumMediaTypes** types)
{
// 1 - This has to be IEnumMediaTypes*, or rather even
// QzCComPtr<IEnumMediaTypes> since you request IID_IEnumMediaTypes
// in the argument below
MyMediaHandler* myhandler;
// 2 - This is totally incorrect: this has to be always matched by
// CoUninitialize and there is no way it has to be there in first
// place; simply remove and never add inside any COM method ever
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_MyMediaHandler, NULL,
CLSCTX_INPROC_SERVER, IID_IEnumMediaTypes, (void **) & myhandler);
UPD. It is typical to override CBasePin.GetMediaType method:
From the pin's list of preferred media types, this method returns the type with an index value of iPosition. [...] Override this method in your derived class.
User contributions licensed under CC BY-SA 3.0