Michael Schwab
2005-01-06 23:16:42 UTC
Even though I believe I'm releasing all the DirectShow objects correctly
after usage, I still lose over 1 Mb of heap space every time I run the
sample code (from Pesce, etc.). And Run() still can't find enough space to
run, even the first time.
Note, I see this problem on WinCE4.2 because it has a limited heap space,
but I don't know that it's specific to CE so I'm posting this in both
groups. (WinXP seems to have an unlimited heap.) I'm trying to increase my
heap space under CE, but this leak will always create a limit to the number
of times I could play a movie.
I wrote a function dwHeapFreeSpace(), that returns the currently available
free space in the heap (or at least the largest contiguous space), by doing
a bunch of malloc()/free() calls (in a "binary search" pattern) to see
what's the largest single chunk of memory I can allocate, down to a
resolution of 8kb. (If anybody knows of a better way to query the free
space in the heap, I'd like to hear it).
Here's the DirectShow example code I'm using, with most error checking
removed for brevity. All the calls are successful except for the Run()
call, until the fifth iteration where the CoCreateInstance() call fails. I
use my debugPrint() call to capture the results of dwHeapFreeSpace() between
DirectShow calls. The 2-second Sleep(2000) calls (before the debugPrint()s)
I found were needed to give the COM objects time to settle out their usage
of heap space.
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
Sleep(2000);
debugPrint(TEXT(" - after
CoInitialize"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
Sleep(2000);
debugPrint(TEXT(" - after
CoCreateInstance"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph.
hr = pGraph->RenderFile(szFilename, NULL);
Sleep(2000);
debugPrint(TEXT(""),TEXT(" - after pGraph->RenderFile -
HeapFree="),dwHeapFreeSpace(),hr,S_OK,S_FALSE);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
Sleep(2000);
debugPrint(TEXT(""),TEXT(" - after pControl->Run -
HeapFree="),dwHeapFreeSpace(),hr,S_OK,S_FALSE);
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
} else {
msgBoxWithAbort(TEXT(" - Run failed"), szFilename);
}
hr = pControl->Stop();
} else {
msgBoxWithAbort(TEXT(" - RenderFile failed"), szFilename);
}
Sleep(2000);
debugPrint(TEXT(" - before
cleanup"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
pControl->Release();
pEvent->Release();
pGraph->Release();
pControl = NULL;
pEvent = NULL;
pGraph = NULL;
CoUninitialize();
Sleep(2000);
debugPrint(TEXT(" - after
cleanup"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
And here's the result of running this code 5 times (first number is the
millisecond timer, all other numbers are printed both in decimal and (hex):
4469650-, HeapFree=, 5619712(0x55c000), 0(0x0), 0(0x0), 0(0x0)
4476363- - after CoInitialize, HeapFree=, 5619712(0x55c000), 0(0x0), 0(0x0),
0(0x0)
4479007- - after CoCreateInstance, HeapFree=, 3522560(0x35c000), 0(0x0),
0(0x0), 0(0x0)
4482683- - after pGraph->RenderFile - HeapFree=, 3391488(0x33c000), 0(0x0),
0(0x0), 1(0x1)
4485141- - after pControl->Run - HeapFree=,
1818624(0x1bc000), -2147024888(0x80070008), 0(0x0), 1(0x1)
4494261- - before cleanup, HeapFree=, 1818624(0x1bc000), 0(0x0), 0(0x0),
0(0x0)
4496887- - after cleanup, HeapFree=, 4571136(0x45c000), 0(0x0), 0(0x0),
0(0x0)
4498411-, HeapFree=, 4571136(0x45c000), 0(0x0), 0(0x0), 0(0x0)
4504937- - after CoInitialize, HeapFree=, 4571136(0x45c000), 0(0x0), 0(0x0),
0(0x0)
4507419- - after CoCreateInstance, HeapFree=, 2473984(0x25c000), 0(0x0),
0(0x0), 0(0x0)
4510923- - after pGraph->RenderFile - HeapFree=, 2342912(0x23c000), 0(0x0),
0(0x0), 1(0x1)
4513249- - after pControl->Run - HeapFree=,
1032192(0xfc000), -2147024882(0x8007000e), 0(0x0), 1(0x1)
4518257- - before cleanup, HeapFree=, 1032192(0xfc000), 0(0x0), 0(0x0),
0(0x0)
4520667- - after cleanup, HeapFree=, 3260416(0x31c000), 0(0x0), 0(0x0),
0(0x0)
4522856-, HeapFree=, 3260416(0x31c000), 0(0x0), 0(0x0), 0(0x0)
4528363- - after CoInitialize, HeapFree=, 3260416(0x31c000), 0(0x0), 0(0x0),
0(0x0)
4530673- - after CoCreateInstance, HeapFree=, 1163264(0x11c000), 0(0x0),
0(0x0), 0(0x0)
4534049- - after pGraph->RenderFile - HeapFree=, 1032192(0xfc000), 0(0x0),
0(0x0), 1(0x1)
4536102- - after pControl->Run - HeapFree=,
16384(0x4000), -2147024882(0x8007000e), 0(0x0), 1(0x1)
4540449- - before cleanup, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0), 0(0x0)
4542745- - after cleanup, HeapFree=, 2211840(0x21c000), 0(0x0), 0(0x0),
0(0x0)
4544027-, HeapFree=, 2211840(0x21c000), 0(0x0), 0(0x0), 0(0x0)
4549652- - after CoInitialize, HeapFree=, 2211840(0x21c000), 0(0x0), 0(0x0),
0(0x0)
4551859- - after CoCreateInstance, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0),
0(0x0)
4555117- - after pGraph->RenderFile - HeapFree=, 16384(0x4000), 0(0x0),
0(0x0), 1(0x1)
4557165- - after pControl->Run - HeapFree=,
16384(0x4000), -2147024882(0x8007000e), 0(0x0), 1(0x1)
4562057- - before cleanup, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0), 0(0x0)
4564256- - after cleanup, HeapFree=, 1163264(0x11c000), 0(0x0), 0(0x0),
0(0x0)
4565585-, HeapFree=, 1163264(0x11c000), 0(0x0), 0(0x0), 0(0x0)
4571273- - after CoInitialize, HeapFree=, 1163264(0x11c000), 0(0x0), 0(0x0),
0(0x0)
4576059-, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0), 0(0x0)
The first time, Run() returned an error code of 0x80070008, which I can't
find anywhere. The rest of the time it returned 0x8007000e, which is
E_OUTOFMEMORY.
In summary, CoCreateInstance allocates 2.097 Mb of heap space each time,
RenderFile uses 131kb, and the failed Run() uses 1.572 Mb then 1.31 Mb then
nothing.
The Releases aren't freeing up all the heap space used, leaving 1.049,
1.311, 1.048, and 1.049 Mb behind for the 4 iterations.
Is there some other Release call I'm missing? Or is it because of the fact
that IMediaControl->Run() is returning an out-of-memory error, and it has
some bug that doesn't release whatever space it allocated if it errors out?
And does the size of the mpg/avi file effect the amount of heap space that
Run() allocates? I'm only using a 1 Mb file in this case, but I'd want to
play bigger movies as well.
Thanks,
Michael Schwab
after usage, I still lose over 1 Mb of heap space every time I run the
sample code (from Pesce, etc.). And Run() still can't find enough space to
run, even the first time.
Note, I see this problem on WinCE4.2 because it has a limited heap space,
but I don't know that it's specific to CE so I'm posting this in both
groups. (WinXP seems to have an unlimited heap.) I'm trying to increase my
heap space under CE, but this leak will always create a limit to the number
of times I could play a movie.
I wrote a function dwHeapFreeSpace(), that returns the currently available
free space in the heap (or at least the largest contiguous space), by doing
a bunch of malloc()/free() calls (in a "binary search" pattern) to see
what's the largest single chunk of memory I can allocate, down to a
resolution of 8kb. (If anybody knows of a better way to query the free
space in the heap, I'd like to hear it).
Here's the DirectShow example code I'm using, with most error checking
removed for brevity. All the calls are successful except for the Run()
call, until the fifth iteration where the CoCreateInstance() call fails. I
use my debugPrint() call to capture the results of dwHeapFreeSpace() between
DirectShow calls. The 2-second Sleep(2000) calls (before the debugPrint()s)
I found were needed to give the COM objects time to settle out their usage
of heap space.
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
Sleep(2000);
debugPrint(TEXT(" - after
CoInitialize"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
Sleep(2000);
debugPrint(TEXT(" - after
CoCreateInstance"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph.
hr = pGraph->RenderFile(szFilename, NULL);
Sleep(2000);
debugPrint(TEXT(""),TEXT(" - after pGraph->RenderFile -
HeapFree="),dwHeapFreeSpace(),hr,S_OK,S_FALSE);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
Sleep(2000);
debugPrint(TEXT(""),TEXT(" - after pControl->Run -
HeapFree="),dwHeapFreeSpace(),hr,S_OK,S_FALSE);
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
} else {
msgBoxWithAbort(TEXT(" - Run failed"), szFilename);
}
hr = pControl->Stop();
} else {
msgBoxWithAbort(TEXT(" - RenderFile failed"), szFilename);
}
Sleep(2000);
debugPrint(TEXT(" - before
cleanup"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
pControl->Release();
pEvent->Release();
pGraph->Release();
pControl = NULL;
pEvent = NULL;
pGraph = NULL;
CoUninitialize();
Sleep(2000);
debugPrint(TEXT(" - after
cleanup"),TEXT("HeapFree="),dwHeapFreeSpace(),0,0,0);
And here's the result of running this code 5 times (first number is the
millisecond timer, all other numbers are printed both in decimal and (hex):
4469650-, HeapFree=, 5619712(0x55c000), 0(0x0), 0(0x0), 0(0x0)
4476363- - after CoInitialize, HeapFree=, 5619712(0x55c000), 0(0x0), 0(0x0),
0(0x0)
4479007- - after CoCreateInstance, HeapFree=, 3522560(0x35c000), 0(0x0),
0(0x0), 0(0x0)
4482683- - after pGraph->RenderFile - HeapFree=, 3391488(0x33c000), 0(0x0),
0(0x0), 1(0x1)
4485141- - after pControl->Run - HeapFree=,
1818624(0x1bc000), -2147024888(0x80070008), 0(0x0), 1(0x1)
4494261- - before cleanup, HeapFree=, 1818624(0x1bc000), 0(0x0), 0(0x0),
0(0x0)
4496887- - after cleanup, HeapFree=, 4571136(0x45c000), 0(0x0), 0(0x0),
0(0x0)
4498411-, HeapFree=, 4571136(0x45c000), 0(0x0), 0(0x0), 0(0x0)
4504937- - after CoInitialize, HeapFree=, 4571136(0x45c000), 0(0x0), 0(0x0),
0(0x0)
4507419- - after CoCreateInstance, HeapFree=, 2473984(0x25c000), 0(0x0),
0(0x0), 0(0x0)
4510923- - after pGraph->RenderFile - HeapFree=, 2342912(0x23c000), 0(0x0),
0(0x0), 1(0x1)
4513249- - after pControl->Run - HeapFree=,
1032192(0xfc000), -2147024882(0x8007000e), 0(0x0), 1(0x1)
4518257- - before cleanup, HeapFree=, 1032192(0xfc000), 0(0x0), 0(0x0),
0(0x0)
4520667- - after cleanup, HeapFree=, 3260416(0x31c000), 0(0x0), 0(0x0),
0(0x0)
4522856-, HeapFree=, 3260416(0x31c000), 0(0x0), 0(0x0), 0(0x0)
4528363- - after CoInitialize, HeapFree=, 3260416(0x31c000), 0(0x0), 0(0x0),
0(0x0)
4530673- - after CoCreateInstance, HeapFree=, 1163264(0x11c000), 0(0x0),
0(0x0), 0(0x0)
4534049- - after pGraph->RenderFile - HeapFree=, 1032192(0xfc000), 0(0x0),
0(0x0), 1(0x1)
4536102- - after pControl->Run - HeapFree=,
16384(0x4000), -2147024882(0x8007000e), 0(0x0), 1(0x1)
4540449- - before cleanup, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0), 0(0x0)
4542745- - after cleanup, HeapFree=, 2211840(0x21c000), 0(0x0), 0(0x0),
0(0x0)
4544027-, HeapFree=, 2211840(0x21c000), 0(0x0), 0(0x0), 0(0x0)
4549652- - after CoInitialize, HeapFree=, 2211840(0x21c000), 0(0x0), 0(0x0),
0(0x0)
4551859- - after CoCreateInstance, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0),
0(0x0)
4555117- - after pGraph->RenderFile - HeapFree=, 16384(0x4000), 0(0x0),
0(0x0), 1(0x1)
4557165- - after pControl->Run - HeapFree=,
16384(0x4000), -2147024882(0x8007000e), 0(0x0), 1(0x1)
4562057- - before cleanup, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0), 0(0x0)
4564256- - after cleanup, HeapFree=, 1163264(0x11c000), 0(0x0), 0(0x0),
0(0x0)
4565585-, HeapFree=, 1163264(0x11c000), 0(0x0), 0(0x0), 0(0x0)
4571273- - after CoInitialize, HeapFree=, 1163264(0x11c000), 0(0x0), 0(0x0),
0(0x0)
4576059-, HeapFree=, 16384(0x4000), 0(0x0), 0(0x0), 0(0x0)
The first time, Run() returned an error code of 0x80070008, which I can't
find anywhere. The rest of the time it returned 0x8007000e, which is
E_OUTOFMEMORY.
In summary, CoCreateInstance allocates 2.097 Mb of heap space each time,
RenderFile uses 131kb, and the failed Run() uses 1.572 Mb then 1.31 Mb then
nothing.
The Releases aren't freeing up all the heap space used, leaving 1.049,
1.311, 1.048, and 1.049 Mb behind for the 4 iterations.
Is there some other Release call I'm missing? Or is it because of the fact
that IMediaControl->Run() is returning an out-of-memory error, and it has
some bug that doesn't release whatever space it allocated if it errors out?
And does the size of the mpg/avi file effect the amount of heap space that
Run() allocates? I'm only using a 1 Mb file in this case, but I'd want to
play bigger movies as well.
Thanks,
Michael Schwab