Commit 029bc761 authored by Paul Chitescu's avatar Paul Chitescu Committed by Alexandre Julliard

qedit: Implement buffering in SampleGrabber.

parent 2ad03b9b
...@@ -365,6 +365,7 @@ typedef struct _SG_Impl { ...@@ -365,6 +365,7 @@ typedef struct _SG_Impl {
const IMemInputPinVtbl* IMemInputPin_Vtbl; const IMemInputPinVtbl* IMemInputPin_Vtbl;
/* TODO: IMediaPosition, IMediaSeeking, IQualityControl */ /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
LONG refCount; LONG refCount;
CRITICAL_SECTION critSect;
FILTER_INFO info; FILTER_INFO info;
FILTER_STATE state; FILTER_STATE state;
AM_MEDIA_TYPE mtype; AM_MEDIA_TYPE mtype;
...@@ -376,6 +377,8 @@ typedef struct _SG_Impl { ...@@ -376,6 +377,8 @@ typedef struct _SG_Impl {
ISampleGrabberCB *grabberIface; ISampleGrabberCB *grabberIface;
LONG grabberMethod; LONG grabberMethod;
LONG oneShot; LONG oneShot;
LONG bufferLen;
void* bufferData;
} SG_Impl; } SG_Impl;
enum { enum {
...@@ -417,6 +420,10 @@ static void SampleGrabber_cleanup(SG_Impl *This) ...@@ -417,6 +420,10 @@ static void SampleGrabber_cleanup(SG_Impl *This)
ISampleGrabberCB_Release(This->grabberIface); ISampleGrabberCB_Release(This->grabberIface);
if (This->mtype.pbFormat) if (This->mtype.pbFormat)
CoTaskMemFree(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 */ /* Common helper AddRef called from all interfaces */
...@@ -475,11 +482,31 @@ static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject) ...@@ -475,11 +482,31 @@ static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
return E_NOINTERFACE; 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) static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
{ {
double time = 0.0; double time = 0.0;
REFERENCE_TIME tStart, tEnd; 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))) if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd)))
time = 1e-7 * tStart; time = 1e-7 * tStart;
switch (This->grabberMethod) { switch (This->grabberMethod) {
...@@ -781,11 +808,16 @@ SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MED ...@@ -781,11 +808,16 @@ SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MED
static HRESULT WINAPI static HRESULT WINAPI
SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm) 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) { if (bufferEm) {
FIXME("buffering not implemented\n"); if (This->bufferLen < 0)
return E_NOTIMPL; This->bufferLen = 0;
} }
else
This->bufferLen = -1;
LeaveCriticalSection(&This->critSect);
return S_OK; return S_OK;
} }
...@@ -793,10 +825,29 @@ SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL buffer ...@@ -793,10 +825,29 @@ SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL buffer
static HRESULT WINAPI static HRESULT WINAPI
SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer) 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) if (!bufSize)
return E_POINTER; 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 */ /* ISampleGrabber */
...@@ -900,7 +951,6 @@ SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample) ...@@ -900,7 +951,6 @@ SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample)
return E_POINTER; return E_POINTER;
if ((This->state != State_Running) || (This->oneShot == OneShot_Past)) if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
return S_FALSE; return S_FALSE;
if (This->grabberIface)
SampleGrabber_callback(This, sample); SampleGrabber_callback(This, sample);
hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK; hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
if (This->oneShot == OneShot_Wait) { if (This->oneShot == OneShot_Wait) {
...@@ -917,16 +967,14 @@ static HRESULT WINAPI ...@@ -917,16 +967,14 @@ static HRESULT WINAPI
SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed) SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed)
{ {
SG_Impl *This = impl_from_IMemInputPin(iface); 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); TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface);
if (!samples || !nProcessed) if (!samples || !nProcessed)
return E_POINTER; return E_POINTER;
if ((This->state != State_Running) || (This->oneShot == OneShot_Past)) if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
return S_FALSE; return S_FALSE;
if (This->grabberIface) {
LONG idx;
for (idx = 0; idx < nSamples; idx++) for (idx = 0; idx < nSamples; idx++)
SampleGrabber_callback(This, samples[idx]); SampleGrabber_callback(This, samples[idx]);
}
return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK; return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK;
} }
...@@ -1405,6 +1453,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv) ...@@ -1405,6 +1453,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
obj->pin_out.name = pin_out_name; obj->pin_out.name = pin_out_name;
obj->pin_out.sg = obj; obj->pin_out.sg = obj;
obj->pin_out.pair = NULL; 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.achName[0] = 0;
obj->info.pGraph = NULL; obj->info.pGraph = NULL;
obj->state = State_Stopped; obj->state = State_Stopped;
...@@ -1417,6 +1467,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv) ...@@ -1417,6 +1467,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
obj->grabberIface = NULL; obj->grabberIface = NULL;
obj->grabberMethod = -1; obj->grabberMethod = -1;
obj->oneShot = OneShot_None; obj->oneShot = OneShot_None;
obj->bufferLen = -1;
obj->bufferData = NULL;
*ppv = obj; *ppv = obj;
return S_OK; return S_OK;
......
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