Module: wine Branch: master Commit: 029bc761db64326e4e28f12e0901d6a249fc4826 URL: http://source.winehq.org/git/wine.git/?a=commit;h=029bc761db64326e4e28f12e09...
Author: Paul Chitescu paulc@voip.null.ro Date: Fri Mar 12 14:15:51 2010 +0200
qedit: Implement buffering in SampleGrabber.
---
dlls/qedit/samplegrabber.c | 78 ++++++++++++++++++++++++++++++++++++------- 1 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c index 327004e..1875c51 100644 --- a/dlls/qedit/samplegrabber.c +++ b/dlls/qedit/samplegrabber.c @@ -365,6 +365,7 @@ typedef struct _SG_Impl { const IMemInputPinVtbl* IMemInputPin_Vtbl; /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */ LONG refCount; + CRITICAL_SECTION critSect; FILTER_INFO info; FILTER_STATE state; AM_MEDIA_TYPE mtype; @@ -376,6 +377,8 @@ typedef struct _SG_Impl { ISampleGrabberCB *grabberIface; LONG grabberMethod; LONG oneShot; + LONG bufferLen; + void* bufferData; } SG_Impl;
enum { @@ -417,6 +420,10 @@ static void SampleGrabber_cleanup(SG_Impl *This) ISampleGrabberCB_Release(This->grabberIface); if (This->mtype.pbFormat) CoTaskMemFree(This->mtype.pbFormat); + if (This->bufferData) + CoTaskMemFree(This->bufferData); + This->critSect.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->critSect); }
/* Common helper AddRef called from all interfaces */ @@ -475,11 +482,31 @@ static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject) return E_NOINTERFACE; }
-/* Helper that calls installed sample callbacks */ +/* Helper that buffers data and/or calls installed sample callbacks */ static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample) { double time = 0.0; REFERENCE_TIME tStart, tEnd; + if (This->bufferLen >= 0) { + BYTE *data = 0; + long size = IMediaSample_GetActualDataLength(sample); + if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) { + if (!data) + size = 0; + EnterCriticalSection(&This->critSect); + if (This->bufferLen != size) { + if (This->bufferData) + CoTaskMemFree(This->bufferData); + This->bufferData = size ? CoTaskMemAlloc(size) : NULL; + This->bufferLen = size; + } + if (size) + CopyMemory(This->bufferData, data, size); + LeaveCriticalSection(&This->critSect); + } + } + if (!This->grabberIface) + return; if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd))) time = 1e-7 * tStart; switch (This->grabberMethod) { @@ -781,11 +808,16 @@ SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MED static HRESULT WINAPI SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm) { - TRACE("(%u)\n", bufferEm); + SG_Impl *This = impl_from_ISampleGrabber(iface); + TRACE("(%p)->(%u)\n", This, bufferEm); + EnterCriticalSection(&This->critSect); if (bufferEm) { - FIXME("buffering not implemented\n"); - return E_NOTIMPL; + if (This->bufferLen < 0) + This->bufferLen = 0; } + else + This->bufferLen = -1; + LeaveCriticalSection(&This->critSect); return S_OK; }
@@ -793,10 +825,29 @@ SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL buffer static HRESULT WINAPI SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer) { - FIXME("(%p, %p): stub\n", bufSize, buffer); + SG_Impl *This = impl_from_ISampleGrabber(iface); + HRESULT ret = S_OK; + TRACE("(%p)->(%p, %p)\n", This, bufSize, buffer); if (!bufSize) return E_POINTER; - return E_INVALIDARG; + EnterCriticalSection(&This->critSect); + if (!This->pin_in.pair) + ret = VFW_E_NOT_CONNECTED; + else if (This->bufferLen < 0) + ret = E_INVALIDARG; + else if (This->bufferLen == 0) + ret = VFW_E_WRONG_STATE; + else { + if (buffer) { + if (*bufSize >= This->bufferLen) + CopyMemory(buffer, This->bufferData, This->bufferLen); + else + ret = E_OUTOFMEMORY; + } + *bufSize = This->bufferLen; + } + LeaveCriticalSection(&This->critSect); + return ret; }
/* ISampleGrabber */ @@ -900,8 +951,7 @@ SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample) return E_POINTER; if ((This->state != State_Running) || (This->oneShot == OneShot_Past)) return S_FALSE; - if (This->grabberIface) - SampleGrabber_callback(This, sample); + SampleGrabber_callback(This, sample); hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK; if (This->oneShot == OneShot_Wait) { This->oneShot = OneShot_Past; @@ -917,16 +967,14 @@ static HRESULT WINAPI SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed) { SG_Impl *This = impl_from_IMemInputPin(iface); + LONG idx; TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface); if (!samples || !nProcessed) return E_POINTER; if ((This->state != State_Running) || (This->oneShot == OneShot_Past)) return S_FALSE; - if (This->grabberIface) { - LONG idx; - for (idx = 0; idx < nSamples; idx++) - SampleGrabber_callback(This, samples[idx]); - } + for (idx = 0; idx < nSamples; idx++) + SampleGrabber_callback(This, samples[idx]); return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK; }
@@ -1405,6 +1453,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv) obj->pin_out.name = pin_out_name; obj->pin_out.sg = obj; obj->pin_out.pair = NULL; + InitializeCriticalSection(&obj->critSect); + obj->critSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SG_Impl.critSect"); obj->info.achName[0] = 0; obj->info.pGraph = NULL; obj->state = State_Stopped; @@ -1417,6 +1467,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv) obj->grabberIface = NULL; obj->grabberMethod = -1; obj->oneShot = OneShot_None; + obj->bufferLen = -1; + obj->bufferData = NULL; *ppv = obj;
return S_OK;