quartz: Use quality control in video renderer.
This commit is contained in:
parent
95897b6819
commit
7fbc8814d8
|
@ -91,7 +91,6 @@ typedef struct VideoRendererImpl
|
||||||
IUnknown * pUnkOuter;
|
IUnknown * pUnkOuter;
|
||||||
BOOL bUnkOuterValid;
|
BOOL bUnkOuterValid;
|
||||||
BOOL bAggregatable;
|
BOOL bAggregatable;
|
||||||
REFERENCE_TIME rtLastStop;
|
|
||||||
LONG WindowStyle;
|
LONG WindowStyle;
|
||||||
|
|
||||||
/* During pause we can hold a single sample, for use in GetCurrentImage */
|
/* During pause we can hold a single sample, for use in GetCurrentImage */
|
||||||
|
@ -383,27 +382,8 @@ static HRESULT WINAPI VideoRenderer_Receive(BaseInputPin* pin, IMediaSample * pS
|
||||||
if (IMediaSample_GetMediaTime(pSample, &tStart, &tStop) == S_OK)
|
if (IMediaSample_GetMediaTime(pSample, &tStart, &tStop) == S_OK)
|
||||||
MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, tStart);
|
MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, tStart);
|
||||||
|
|
||||||
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
|
|
||||||
if (FAILED(hr))
|
|
||||||
ERR("Cannot get sample time (%x)\n", hr);
|
|
||||||
|
|
||||||
if (This->rtLastStop != tStart && This->filter.state == State_Running)
|
|
||||||
{
|
|
||||||
LONG64 delta;
|
|
||||||
delta = tStart - This->rtLastStop;
|
|
||||||
if ((delta < -100000 || delta > 100000) &&
|
|
||||||
IMediaSample_IsDiscontinuity(pSample) == S_FALSE)
|
|
||||||
ERR("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n",
|
|
||||||
(DWORD)(This->rtLastStop / 10000000),
|
|
||||||
(DWORD)((This->rtLastStop / 10000)%1000),
|
|
||||||
(DWORD)(tStart / 10000000), (DWORD)((tStart / 10000)%1000));
|
|
||||||
This->rtLastStop = tStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Preroll means the sample isn't shown, this is used for key frames and things like that */
|
/* Preroll means the sample isn't shown, this is used for key frames and things like that */
|
||||||
if (IMediaSample_IsPreroll(pSample) == S_OK)
|
if (IMediaSample_IsPreroll(pSample) == S_OK) {
|
||||||
{
|
|
||||||
This->rtLastStop = tStop;
|
|
||||||
LeaveCriticalSection(&This->filter.csFilter);
|
LeaveCriticalSection(&This->filter.csFilter);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -436,6 +416,7 @@ static HRESULT WINAPI VideoRenderer_Receive(BaseInputPin* pin, IMediaSample * pS
|
||||||
SetEvent(This->hEvent);
|
SetEvent(This->hEvent);
|
||||||
if (This->filter.state == State_Paused)
|
if (This->filter.state == State_Paused)
|
||||||
{
|
{
|
||||||
|
VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
|
||||||
This->sample_held = pSample;
|
This->sample_held = pSample;
|
||||||
LeaveCriticalSection(&This->filter.csFilter);
|
LeaveCriticalSection(&This->filter.csFilter);
|
||||||
WaitForSingleObject(This->blocked, INFINITE);
|
WaitForSingleObject(This->blocked, INFINITE);
|
||||||
|
@ -452,44 +433,15 @@ static HRESULT WINAPI VideoRenderer_Receive(BaseInputPin* pin, IMediaSample * pS
|
||||||
LeaveCriticalSection(&This->filter.csFilter);
|
LeaveCriticalSection(&This->filter.csFilter);
|
||||||
return VFW_E_WRONG_STATE;
|
return VFW_E_WRONG_STATE;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
hr = QualityControlRender_WaitFor(&This->qcimpl, pSample, This->blocked);
|
||||||
if (This->filter.pClock && This->filter.state == State_Running)
|
if (hr == S_OK) {
|
||||||
{
|
QualityControlRender_BeginRender(&This->qcimpl);
|
||||||
REFERENCE_TIME time, trefstart, trefstop;
|
VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
|
||||||
LONG delta;
|
QualityControlRender_EndRender(&This->qcimpl);
|
||||||
|
|
||||||
/* Perhaps I <SHOULD> use the reference clock AdviseTime function here
|
|
||||||
* I'm not going to! When I tried, it seemed to generate lag and
|
|
||||||
* it caused instability.
|
|
||||||
*/
|
|
||||||
IReferenceClock_GetTime(This->filter.pClock, &time);
|
|
||||||
|
|
||||||
trefstart = This->filter.rtStreamStart;
|
|
||||||
trefstop = (REFERENCE_TIME)((double)(tStop - tStart) / This->pInputPin->pin.dRate) + This->filter.rtStreamStart;
|
|
||||||
delta = (LONG)((trefstart-time)/10000);
|
|
||||||
This->filter.rtStreamStart = trefstop;
|
|
||||||
This->rtLastStop = tStop;
|
|
||||||
|
|
||||||
if (delta > 0)
|
|
||||||
{
|
|
||||||
TRACE("Sleeping for %u ms\n", delta);
|
|
||||||
Sleep(delta);
|
|
||||||
}
|
|
||||||
else if (time > trefstop)
|
|
||||||
{
|
|
||||||
TRACE("Dropping sample: Time: %u.%03u ms trefstop: %u.%03u ms!\n",
|
|
||||||
(DWORD)(time / 10000000), (DWORD)((time / 10000)%1000),
|
|
||||||
(DWORD)(trefstop / 10000000), (DWORD)((trefstop / 10000)%1000) );
|
|
||||||
This->rtLastStop = tStop;
|
|
||||||
LeaveCriticalSection(&This->filter.csFilter);
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
QualityControlRender_DoQOS(&This->qcimpl);
|
||||||
}
|
}
|
||||||
This->rtLastStop = tStop;
|
|
||||||
|
|
||||||
VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
|
|
||||||
|
|
||||||
LeaveCriticalSection(&This->filter.csFilter);
|
LeaveCriticalSection(&This->filter.csFilter);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -601,7 +553,6 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
||||||
|
|
||||||
pVideoRenderer->init = 0;
|
pVideoRenderer->init = 0;
|
||||||
pVideoRenderer->AutoShow = 1;
|
pVideoRenderer->AutoShow = 1;
|
||||||
pVideoRenderer->rtLastStop = -1;
|
|
||||||
ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
|
ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
|
||||||
ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
|
ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
|
||||||
ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
|
ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
|
||||||
|
@ -846,6 +797,17 @@ static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock) {
|
||||||
|
VideoRendererImpl *This = (VideoRendererImpl *)iface;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
EnterCriticalSection(&This->filter.csFilter);
|
||||||
|
QualityControlRender_SetClock(&This->qcimpl, clock);
|
||||||
|
hr = BaseFilterImpl_SetSyncSource(iface, clock);
|
||||||
|
LeaveCriticalSection(&This->filter.csFilter);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
|
static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
@ -867,6 +829,7 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta
|
||||||
|
|
||||||
This->filter.rtStreamStart = tStart;
|
This->filter.rtStreamStart = tStart;
|
||||||
This->filter.state = State_Running;
|
This->filter.state = State_Running;
|
||||||
|
QualityControlRender_Start(&This->qcimpl, tStart);
|
||||||
} else if (This->filter.filterInfo.pGraph) {
|
} else if (This->filter.filterInfo.pGraph) {
|
||||||
IMediaEventSink *pEventSink;
|
IMediaEventSink *pEventSink;
|
||||||
hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
|
hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
|
||||||
|
@ -925,7 +888,7 @@ static const IBaseFilterVtbl VideoRenderer_Vtbl =
|
||||||
VideoRenderer_Pause,
|
VideoRenderer_Pause,
|
||||||
VideoRenderer_Run,
|
VideoRenderer_Run,
|
||||||
VideoRenderer_GetState,
|
VideoRenderer_GetState,
|
||||||
BaseFilterImpl_SetSyncSource,
|
VideoRenderer_SetSyncSource,
|
||||||
BaseFilterImpl_GetSyncSource,
|
BaseFilterImpl_GetSyncSource,
|
||||||
BaseFilterImpl_EnumPins,
|
BaseFilterImpl_EnumPins,
|
||||||
VideoRenderer_FindPin,
|
VideoRenderer_FindPin,
|
||||||
|
@ -984,6 +947,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
|
||||||
if (pVideoRenderer->filter.state == State_Paused)
|
if (pVideoRenderer->filter.state == State_Paused)
|
||||||
ResetEvent(pVideoRenderer->blocked);
|
ResetEvent(pVideoRenderer->blocked);
|
||||||
|
|
||||||
|
QualityControlRender_Start(&pVideoRenderer->qcimpl, pVideoRenderer->filter.rtStreamStart);
|
||||||
hr = BaseInputPinImpl_EndFlush(iface);
|
hr = BaseInputPinImpl_EndFlush(iface);
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk);
|
MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk);
|
||||||
|
|
Loading…
Reference in New Issue