quartz: Add a Disconnect function to the parser and use it to clean up allocated memory in avisplitter.
diff --git a/dlls/quartz/avisplit.c b/dlls/quartz/avisplit.c
index 0d15c75..24f487c 100644
--- a/dlls/quartz/avisplit.c
+++ b/dlls/quartz/avisplit.c
@@ -22,6 +22,7 @@
/* FIXME:
* - we don't do anything with indices yet (we could use them when seeking)
* - we don't support multiple RIFF sections (i.e. large AVI files > 2Gb)
+ * - Memory leaks, and lots of them
*/
#include "quartz_private.h"
@@ -55,6 +56,10 @@
DWORD dwSampleSize;
FLOAT fSamplesPerSec;
DWORD dwLength;
+
+ AVISUPERINDEX *superindex;
+ DWORD entries;
+ AVISTDINDEX **stdindex;
} StreamData;
typedef struct AVISplitterImpl
@@ -65,6 +70,11 @@
LONGLONG CurrentChunkOffset; /* in media time */
LONGLONG EndOfFile;
AVIMAINHEADER AviHeader;
+ AVIEXTHEADER ExtHeader;
+
+ /* TODO: Handle old style index, probably by creating an opendml style new index from it for within StreamData */
+ AVIOLDINDEX *oldindex;
+
StreamData *streams;
} AVISplitterImpl;
@@ -404,6 +414,61 @@
return S_OK;
}
+static HRESULT AVISplitter_ProcessOldIndex(AVISplitterImpl *This)
+{
+ AVIOLDINDEX *pAviOldIndex = This->oldindex;
+ int relative = -1;
+ int x;
+
+ for (x = 0; x < pAviOldIndex->cb / sizeof(pAviOldIndex->aIndex[0]); ++x)
+ {
+ DWORD temp, temp2 = 0, offset, chunkid;
+ ULONGLONG mov_pos = BYTES_FROM_MEDIATIME(This->CurrentChunkOffset) - sizeof(DWORD);
+ PullPin *pin = This->Parser.pInputPin;
+
+ offset = pAviOldIndex->aIndex[x].dwOffset;
+ chunkid = pAviOldIndex->aIndex[x].dwChunkId;
+
+ /* Only scan once, or else this will take too long */
+ if (relative == -1)
+ {
+ IAsyncReader_SyncRead(pin->pReader, offset, sizeof(DWORD), (BYTE *)&temp);
+ relative = (chunkid != temp);
+
+ if (chunkid == mmioFOURCC('7','F','x','x')
+ && ((char *)&temp)[0] == 'i' && ((char *)&temp)[1] == 'x')
+ relative = FALSE;
+
+ if (relative)
+ {
+ if (offset + mov_pos < BYTES_FROM_MEDIATIME(This->EndOfFile))
+ IAsyncReader_SyncRead(pin->pReader, offset + mov_pos, sizeof(DWORD), (BYTE *)&temp2);
+
+ if (chunkid == mmioFOURCC('7','F','x','x')
+ && ((char *)&temp2)[0] == 'i' && ((char *)&temp2)[1] == 'x')
+ {
+ /* Do nothing, all is great */
+ }
+ else if (temp2 != chunkid)
+ {
+ ERR("Faulty index or bug in handling: Wanted FCC: %s, Abs FCC: %s (@ %x), Rel FCC: %s (@ %.0x%08x)\n",
+ debugstr_an((char *)&chunkid, 4), debugstr_an((char *)&temp, 4), offset,
+ debugstr_an((char *)&temp2, 4), (DWORD)((mov_pos + offset) >> 32), (DWORD)(mov_pos + offset));
+ relative = -1;
+ }
+ }
+ }
+
+ TRACE("Scanned dwChunkId: %s\n", debugstr_an((char *)&temp, 4));
+ TRACE("dwChunkId: %.4s\n", (char *)&chunkid);
+ TRACE("dwFlags: %08x\n", pAviOldIndex->aIndex[x].dwFlags);
+ TRACE("dwOffset (%s): %08x\n", relative ? "relative" : "absolute", offset);
+ TRACE("dwSize: %08x\n", pAviOldIndex->aIndex[x].dwSize);
+ }
+
+ return S_OK;
+}
+
static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE * pData, DWORD cb)
{
PIN_INFO piOutput;
@@ -585,6 +650,7 @@
stream->dwLength = dwLength; /* TODO: Use this for mediaseeking */
hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt);
+ CoTaskMemFree(amt.pbFormat);
return hr;
}
@@ -615,6 +681,7 @@
for (x = 0; x < 61; ++x)
if (pExtHdr->dwFuture[x])
FIXME("dwFuture[%i] = %u (0x%08x)\n", x, pExtHdr->dwFuture[x], pExtHdr->dwFuture[x]);
+ This->ExtHeader = *pExtHdr;
break;
}
default:
@@ -753,60 +820,20 @@
hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
if (list.fcc == ckidAVIOLDINDEX)
{
- int x = 0;
- AVIOLDINDEX * pAviOldIndex = CoTaskMemAlloc(list.cb + sizeof(RIFFCHUNK));
- if (!pAviOldIndex)
+ pAviSplit->oldindex = CoTaskMemRealloc(pAviSplit->oldindex, list.cb + sizeof(RIFFCHUNK));
+ if (!pAviSplit->oldindex)
return E_OUTOFMEMORY;
- hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(RIFFCHUNK) + list.cb, (BYTE *)pAviOldIndex);
+
+ hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(RIFFCHUNK) + list.cb, (BYTE *)pAviSplit->oldindex);
if (hr == S_OK)
{
- for (x = 0; x < list.cb / sizeof(pAviOldIndex->aIndex[0]); ++x)
- {
- DWORD temp, temp2, offset, chunkid;
- ULONGLONG mov_pos = BYTES_FROM_MEDIATIME(pAviSplit->CurrentChunkOffset) - sizeof(DWORD);
- BOOL relative;
-
- offset = pAviOldIndex->aIndex[x].dwOffset;
- chunkid = pAviOldIndex->aIndex[x].dwChunkId;
-
- IAsyncReader_SyncRead(This->pReader, offset, sizeof(DWORD), (BYTE *)&temp);
- relative = (chunkid != temp);
-
- if (chunkid == mmioFOURCC('7','F','x','x')
- && ((char *)&temp)[0] == 'i' && ((char *)&temp)[1] == 'x')
- relative = FALSE;
-
- if (relative)
- {
- if (offset + mov_pos < BYTES_FROM_MEDIATIME(pAviSplit->EndOfFile))
- hr = IAsyncReader_SyncRead(This->pReader, offset + mov_pos, sizeof(DWORD), (BYTE *)&temp2);
- else hr = S_FALSE;
-
- if (hr == S_OK && chunkid == mmioFOURCC('7','F','x','x')
- && ((char *)&temp2)[0] == 'i' && ((char *)&temp2)[1] == 'x')
- {
- /* Do nothing, all is great */
- }
- else if (hr == S_OK && temp2 != chunkid)
- {
- ERR("Faulty index or bug in handling: Wanted FOURCC: %s, Absolute FOURCC: %s (@ %u), Relative FOURCC: %s (@ %lld)\n",
- debugstr_an((char *)&chunkid, 4), debugstr_an((char *)&temp, 4), offset, debugstr_an((char *)&temp2, 4), mov_pos + offset);
- }
- else if (hr != S_OK)
- {
- TRACE("hr: %08x\n", hr);
- }
- }
-
- TRACE("Scanned dwChunkId: %s\n", debugstr_an((char *)&temp, 4));
- TRACE("dwChunkId: %.4s\n", (char *)&chunkid);
- TRACE("dwFlags: %08x\n", pAviOldIndex->aIndex[x].dwFlags);
- TRACE("dwOffset (%s): %08x\n", relative ? "relative" : "absolute", offset);
- TRACE("dwSize: %08x\n", pAviOldIndex->aIndex[x].dwSize);
- }
+ AVISplitter_ProcessOldIndex(pAviSplit);
}
-
- CoTaskMemFree(pAviOldIndex);
+ else
+ {
+ CoTaskMemFree(pAviSplit->oldindex);
+ pAviSplit->oldindex = NULL;
+ }
}
hr = S_OK;
}
@@ -832,6 +859,17 @@
return S_OK;
}
+static HRESULT AVISplitter_Disconnect(LPVOID iface)
+{
+ AVISplitterImpl *This = iface;
+
+ /* TODO: Remove other memory that's allocated during connect */
+ CoTaskMemFree(This->oldindex);
+ This->oldindex = NULL;
+
+ return S_OK;
+}
+
HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
HRESULT hr;
@@ -849,8 +887,9 @@
This->pCurrentSample = NULL;
This->streams = NULL;
+ This->oldindex = NULL;
- hr = Parser_Create(&(This->Parser), &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect, AVISplitter_Cleanup, NULL, NULL, NULL);
+ hr = Parser_Create(&(This->Parser), &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect, AVISplitter_Cleanup, AVISplitter_Disconnect, NULL, NULL, NULL);
if (FAILED(hr))
return hr;
diff --git a/dlls/quartz/mpegsplit.c b/dlls/quartz/mpegsplit.c
index 7577174..8daafea 100644
--- a/dlls/quartz/mpegsplit.c
+++ b/dlls/quartz/mpegsplit.c
@@ -865,6 +865,12 @@
return hr;
}
+static HRESULT MPEGSplitter_destroy(LPVOID iface)
+{
+ /* TODO: Find memory leaks etc */
+ return S_OK;
+}
+
HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
MPEGSplitterImpl *This;
@@ -890,7 +896,7 @@
}
This->seek_entries = 64;
- hr = Parser_Create(&(This->Parser), &CLSID_MPEG1Splitter, MPEGSplitter_process_sample, MPEGSplitter_query_accept, MPEGSplitter_pre_connect, MPEGSplitter_cleanup, NULL, MPEGSplitter_seek, NULL);
+ hr = Parser_Create(&(This->Parser), &CLSID_MPEG1Splitter, MPEGSplitter_process_sample, MPEGSplitter_query_accept, MPEGSplitter_pre_connect, MPEGSplitter_cleanup, MPEGSplitter_destroy, NULL, MPEGSplitter_seek, NULL);
if (FAILED(hr))
{
CoTaskMemFree(This);
diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c
index 37cf8ee..a0e14f1 100644
--- a/dlls/quartz/parser.c
+++ b/dlls/quartz/parser.c
@@ -53,7 +53,7 @@
}
-HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate)
+HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate)
{
HRESULT hr;
PIN_INFO piInput;
@@ -68,6 +68,7 @@
pParser->state = State_Stopped;
pParser->pClock = NULL;
pParser->fnCleanup = fnCleanup;
+ pParser->fnDisconnect = fnDisconnect;
ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
pParser->cStreams = 0;
@@ -680,7 +681,7 @@
OutputPin_NewSegment
};
-static HRESULT WINAPI Parser_InputPin_Disconnect(IPin * iface)
+static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
{
HRESULT hr;
IPinImpl *This = (IPinImpl *)iface;
@@ -692,10 +693,11 @@
if (This->pConnectedTo)
{
FILTER_STATE state;
+ ParserImpl *Parser = (ParserImpl *)This->pinInfo.pFilter;
hr = IBaseFilter_GetState(This->pinInfo.pFilter, 0, &state);
- if (SUCCEEDED(hr) && (state == State_Stopped))
+ if (SUCCEEDED(hr) && (state == State_Stopped) && SUCCEEDED(Parser->fnDisconnect(Parser)))
{
IPin_Release(This->pConnectedTo);
This->pConnectedTo = NULL;
@@ -738,7 +740,7 @@
PullPin_Release,
OutputPin_Connect,
Parser_PullPin_ReceiveConnection,
- Parser_InputPin_Disconnect,
+ Parser_PullPin_Disconnect,
IPinImpl_ConnectedTo,
IPinImpl_ConnectionMediaType,
IPinImpl_QueryPinInfo,
diff --git a/dlls/quartz/parser.h b/dlls/quartz/parser.h
index 0bba062..3ca342e 100644
--- a/dlls/quartz/parser.h
+++ b/dlls/quartz/parser.h
@@ -24,6 +24,7 @@
typedef HRESULT (*PFN_QUERY_ACCEPT) (LPVOID iface, const AM_MEDIA_TYPE * pmt);
typedef HRESULT (*PFN_PRE_CONNECT) (IPin * iface, IPin * pConnectPin);
typedef HRESULT (*PFN_CLEANUP) (LPVOID iface);
+typedef HRESULT (*PFN_DISCONNECT) (LPVOID iface);
struct ParserImpl
{
@@ -35,6 +36,7 @@
REFERENCE_TIME rtStreamStart;
IReferenceClock * pClock;
PFN_CLEANUP fnCleanup;
+ PFN_DISCONNECT fnDisconnect;
FILTER_INFO filterInfo;
CLSID clsid;
@@ -54,4 +56,5 @@
HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt);
-HRESULT Parser_Create(ParserImpl*, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT, PFN_CLEANUP, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate);
+HRESULT Parser_Create(ParserImpl*, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT,
+ PFN_CLEANUP, PFN_DISCONNECT, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate);
diff --git a/dlls/quartz/waveparser.c b/dlls/quartz/waveparser.c
index 965db5c..544fa4c 100644
--- a/dlls/quartz/waveparser.c
+++ b/dlls/quartz/waveparser.c
@@ -418,6 +418,12 @@
return S_OK;
}
+static HRESULT WAVEParser_disconnect(LPVOID iface)
+{
+ /* TODO: Find and plug memory leaks */
+ return S_OK;
+}
+
HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
HRESULT hr;
@@ -435,7 +441,7 @@
This->pCurrentSample = NULL;
- hr = Parser_Create(&(This->Parser), &CLSID_WAVEParser, WAVEParser_Sample, WAVEParser_QueryAccept, WAVEParser_InputPin_PreConnect, WAVEParser_Cleanup, NULL, WAVEParserImpl_seek, NULL);
+ hr = Parser_Create(&(This->Parser), &CLSID_WAVEParser, WAVEParser_Sample, WAVEParser_QueryAccept, WAVEParser_InputPin_PreConnect, WAVEParser_Cleanup, WAVEParser_disconnect, NULL, WAVEParserImpl_seek, NULL);
if (FAILED(hr))
return hr;