From 99778fdb07988e62e7c8404395323b209bff544e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 15 Apr 2008 20:39:36 -0700 Subject: [PATCH] quartz: Add a Disconnect function to the parser and use it to clean up allocated memory in avisplitter --- dlls/quartz/avisplit.c | 141 +++++++++++++++++++++++++++++----------------- dlls/quartz/mpegsplit.c | 8 ++- dlls/quartz/parser.c | 10 ++- dlls/quartz/parser.h | 5 +- dlls/quartz/waveparser.c | 8 ++- 5 files changed, 114 insertions(+), 58 deletions(-) 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 @@ typedef struct StreamData DWORD dwSampleSize; FLOAT fSamplesPerSec; DWORD dwLength; + + AVISUPERINDEX *superindex; + DWORD entries; + AVISTDINDEX **stdindex; } StreamData; typedef struct AVISplitterImpl @@ -65,6 +70,11 @@ typedef struct AVISplitterImpl 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 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, LONGLONG qwOffset 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 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE 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 @@ static HRESULT AVISplitter_ProcessODML(AVISplitterImpl * This, const BYTE * pDat 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 @@ static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin) 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); + } + else + { + CoTaskMemFree(pAviSplit->oldindex); + pAviSplit->oldindex = NULL; } - - CoTaskMemFree(pAviOldIndex); } hr = S_OK; } @@ -832,6 +859,17 @@ static HRESULT AVISplitter_Cleanup(LPVOID iface) 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 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) 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 @@ static HRESULT MPEGSplitter_seek(IBaseFilter *iface) 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 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) } 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 @@ static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) } -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 @@ HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMP 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 @@ static const IPinVtbl Parser_OutputPin_Vtbl = 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 @@ static HRESULT WINAPI Parser_InputPin_Disconnect(IPin * iface) 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 @@ static const IPinVtbl Parser_InputPin_Vtbl = 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_PROCESS_SAMPLE) (LPVOID iface, IMediaSample * pSample); 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 @@ struct ParserImpl REFERENCE_TIME rtStreamStart; IReferenceClock * pClock; PFN_CLEANUP fnCleanup; + PFN_DISCONNECT fnDisconnect; FILTER_INFO filterInfo; CLSID clsid; @@ -54,4 +56,5 @@ typedef struct Parser_OutputPin 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 @@ static HRESULT WAVEParser_Cleanup(LPVOID iface) 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 @@ HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv) 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; -- 1.5.4.1