Commit 6165d87f authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Alexandre Julliard

quartz: Add a Disconnect function to the parser and use it to clean up allocated…

quartz: Add a Disconnect function to the parser and use it to clean up allocated memory in avisplitter.
parent aa623d2e
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
/* FIXME: /* FIXME:
* - we don't do anything with indices yet (we could use them when seeking) * - 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) * - we don't support multiple RIFF sections (i.e. large AVI files > 2Gb)
* - Memory leaks, and lots of them
*/ */
#include "quartz_private.h" #include "quartz_private.h"
...@@ -55,6 +56,10 @@ typedef struct StreamData ...@@ -55,6 +56,10 @@ typedef struct StreamData
DWORD dwSampleSize; DWORD dwSampleSize;
FLOAT fSamplesPerSec; FLOAT fSamplesPerSec;
DWORD dwLength; DWORD dwLength;
AVISUPERINDEX *superindex;
DWORD entries;
AVISTDINDEX **stdindex;
} StreamData; } StreamData;
typedef struct AVISplitterImpl typedef struct AVISplitterImpl
...@@ -65,6 +70,11 @@ typedef struct AVISplitterImpl ...@@ -65,6 +70,11 @@ typedef struct AVISplitterImpl
LONGLONG CurrentChunkOffset; /* in media time */ LONGLONG CurrentChunkOffset; /* in media time */
LONGLONG EndOfFile; LONGLONG EndOfFile;
AVIMAINHEADER AviHeader; 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; StreamData *streams;
} AVISplitterImpl; } AVISplitterImpl;
...@@ -404,6 +414,61 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, LONGLONG qwOffset ...@@ -404,6 +414,61 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, LONGLONG qwOffset
return S_OK; 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) static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE * pData, DWORD cb)
{ {
PIN_INFO piOutput; PIN_INFO piOutput;
...@@ -585,6 +650,7 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE ...@@ -585,6 +650,7 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE
stream->dwLength = dwLength; /* TODO: Use this for mediaseeking */ stream->dwLength = dwLength; /* TODO: Use this for mediaseeking */
hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt); hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt);
CoTaskMemFree(amt.pbFormat);
return hr; return hr;
} }
...@@ -615,6 +681,7 @@ static HRESULT AVISplitter_ProcessODML(AVISplitterImpl * This, const BYTE * pDat ...@@ -615,6 +681,7 @@ static HRESULT AVISplitter_ProcessODML(AVISplitterImpl * This, const BYTE * pDat
for (x = 0; x < 61; ++x) for (x = 0; x < 61; ++x)
if (pExtHdr->dwFuture[x]) if (pExtHdr->dwFuture[x])
FIXME("dwFuture[%i] = %u (0x%08x)\n", x, pExtHdr->dwFuture[x], pExtHdr->dwFuture[x]); FIXME("dwFuture[%i] = %u (0x%08x)\n", x, pExtHdr->dwFuture[x], pExtHdr->dwFuture[x]);
This->ExtHeader = *pExtHdr;
break; break;
} }
default: default:
...@@ -753,60 +820,20 @@ static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin) ...@@ -753,60 +820,20 @@ static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin)
hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list); hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
if (list.fcc == ckidAVIOLDINDEX) if (list.fcc == ckidAVIOLDINDEX)
{ {
int x = 0; pAviSplit->oldindex = CoTaskMemRealloc(pAviSplit->oldindex, list.cb + sizeof(RIFFCHUNK));
AVIOLDINDEX * pAviOldIndex = CoTaskMemAlloc(list.cb + sizeof(RIFFCHUNK)); if (!pAviSplit->oldindex)
if (!pAviOldIndex)
return E_OUTOFMEMORY; 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) if (hr == S_OK)
{ {
for (x = 0; x < list.cb / sizeof(pAviOldIndex->aIndex[0]); ++x) AVISplitter_ProcessOldIndex(pAviSplit);
{ }
DWORD temp, temp2, offset, chunkid; else
ULONGLONG mov_pos = BYTES_FROM_MEDIATIME(pAviSplit->CurrentChunkOffset) - sizeof(DWORD); {
BOOL relative; CoTaskMemFree(pAviSplit->oldindex);
pAviSplit->oldindex = NULL;
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);
}
} }
CoTaskMemFree(pAviOldIndex);
} }
hr = S_OK; hr = S_OK;
} }
...@@ -832,6 +859,17 @@ static HRESULT AVISplitter_Cleanup(LPVOID iface) ...@@ -832,6 +859,17 @@ static HRESULT AVISplitter_Cleanup(LPVOID iface)
return S_OK; 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 AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
{ {
HRESULT hr; HRESULT hr;
...@@ -849,8 +887,9 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) ...@@ -849,8 +887,9 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
This->pCurrentSample = NULL; This->pCurrentSample = NULL;
This->streams = 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)) if (FAILED(hr))
return hr; return hr;
......
...@@ -865,6 +865,12 @@ static HRESULT MPEGSplitter_seek(IBaseFilter *iface) ...@@ -865,6 +865,12 @@ static HRESULT MPEGSplitter_seek(IBaseFilter *iface)
return hr; return hr;
} }
static HRESULT MPEGSplitter_destroy(LPVOID iface)
{
/* TODO: Find memory leaks etc */
return S_OK;
}
HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
{ {
MPEGSplitterImpl *This; MPEGSplitterImpl *This;
...@@ -890,7 +896,7 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) ...@@ -890,7 +896,7 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
} }
This->seek_entries = 64; 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)) if (FAILED(hr))
{ {
CoTaskMemFree(This); CoTaskMemFree(This);
......
...@@ -53,7 +53,7 @@ static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) ...@@ -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; HRESULT hr;
PIN_INFO piInput; PIN_INFO piInput;
...@@ -68,6 +68,7 @@ HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMP ...@@ -68,6 +68,7 @@ HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMP
pParser->state = State_Stopped; pParser->state = State_Stopped;
pParser->pClock = NULL; pParser->pClock = NULL;
pParser->fnCleanup = fnCleanup; pParser->fnCleanup = fnCleanup;
pParser->fnDisconnect = fnDisconnect;
ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO)); ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
pParser->cStreams = 0; pParser->cStreams = 0;
...@@ -680,7 +681,7 @@ static const IPinVtbl Parser_OutputPin_Vtbl = ...@@ -680,7 +681,7 @@ static const IPinVtbl Parser_OutputPin_Vtbl =
OutputPin_NewSegment OutputPin_NewSegment
}; };
static HRESULT WINAPI Parser_InputPin_Disconnect(IPin * iface) static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
{ {
HRESULT hr; HRESULT hr;
IPinImpl *This = (IPinImpl *)iface; IPinImpl *This = (IPinImpl *)iface;
...@@ -692,10 +693,11 @@ static HRESULT WINAPI Parser_InputPin_Disconnect(IPin * iface) ...@@ -692,10 +693,11 @@ static HRESULT WINAPI Parser_InputPin_Disconnect(IPin * iface)
if (This->pConnectedTo) if (This->pConnectedTo)
{ {
FILTER_STATE state; FILTER_STATE state;
ParserImpl *Parser = (ParserImpl *)This->pinInfo.pFilter;
hr = IBaseFilter_GetState(This->pinInfo.pFilter, 0, &state); 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); IPin_Release(This->pConnectedTo);
This->pConnectedTo = NULL; This->pConnectedTo = NULL;
...@@ -738,7 +740,7 @@ static const IPinVtbl Parser_InputPin_Vtbl = ...@@ -738,7 +740,7 @@ static const IPinVtbl Parser_InputPin_Vtbl =
PullPin_Release, PullPin_Release,
OutputPin_Connect, OutputPin_Connect,
Parser_PullPin_ReceiveConnection, Parser_PullPin_ReceiveConnection,
Parser_InputPin_Disconnect, Parser_PullPin_Disconnect,
IPinImpl_ConnectedTo, IPinImpl_ConnectedTo,
IPinImpl_ConnectionMediaType, IPinImpl_ConnectionMediaType,
IPinImpl_QueryPinInfo, IPinImpl_QueryPinInfo,
......
...@@ -24,6 +24,7 @@ typedef HRESULT (*PFN_PROCESS_SAMPLE) (LPVOID iface, IMediaSample * pSample); ...@@ -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_QUERY_ACCEPT) (LPVOID iface, const AM_MEDIA_TYPE * pmt);
typedef HRESULT (*PFN_PRE_CONNECT) (IPin * iface, IPin * pConnectPin); typedef HRESULT (*PFN_PRE_CONNECT) (IPin * iface, IPin * pConnectPin);
typedef HRESULT (*PFN_CLEANUP) (LPVOID iface); typedef HRESULT (*PFN_CLEANUP) (LPVOID iface);
typedef HRESULT (*PFN_DISCONNECT) (LPVOID iface);
struct ParserImpl struct ParserImpl
{ {
...@@ -35,6 +36,7 @@ struct ParserImpl ...@@ -35,6 +36,7 @@ struct ParserImpl
REFERENCE_TIME rtStreamStart; REFERENCE_TIME rtStreamStart;
IReferenceClock * pClock; IReferenceClock * pClock;
PFN_CLEANUP fnCleanup; PFN_CLEANUP fnCleanup;
PFN_DISCONNECT fnDisconnect;
FILTER_INFO filterInfo; FILTER_INFO filterInfo;
CLSID clsid; CLSID clsid;
...@@ -54,4 +56,5 @@ typedef struct Parser_OutputPin ...@@ -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_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);
...@@ -418,6 +418,12 @@ static HRESULT WAVEParser_Cleanup(LPVOID iface) ...@@ -418,6 +418,12 @@ static HRESULT WAVEParser_Cleanup(LPVOID iface)
return S_OK; 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 WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv)
{ {
HRESULT hr; HRESULT hr;
...@@ -435,7 +441,7 @@ HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv) ...@@ -435,7 +441,7 @@ HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv)
This->pCurrentSample = NULL; 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)) if (FAILED(hr))
return hr; return hr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment