From 7c6f8ed4dbabfe7a7623ac11df92ea22d7735df7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 10 Jun 2008 18:45:25 +0200 Subject: [PATCH] quartz: Implement VideoRenderer_GetCurrentImage --- dlls/quartz/videorenderer.c | 80 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 78 insertions(+), 2 deletions(-) diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index fa3905e..bda9fdf 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -87,6 +87,9 @@ typedef struct VideoRendererImpl BOOL bAggregatable; REFERENCE_TIME rtLastStop; MediaSeekingImpl mediaSeeking; + + /* During pause we can hold a single sample, for use in GetCurrentImage */ + IMediaSample *sample_held; } VideoRendererImpl; static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -408,6 +411,15 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) } #endif + if (This->state == State_Paused) + { + if (This->sample_held) + IMediaSample_Release(This->sample_held); + + This->sample_held = pSample; + IMediaSample_AddRef(pSample); + } + if (This->pClock && This->state == State_Running) { REFERENCE_TIME time, trefstart, trefstop; @@ -585,6 +597,7 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) MediaSeekingImpl_Init((IBaseFilter*)pVideoRenderer, VideoRendererImpl_Change, VideoRendererImpl_Change, VideoRendererImpl_Change, &pVideoRenderer->mediaSeeking, &pVideoRenderer->csFilter); pVideoRenderer->mediaSeeking.lpVtbl = &VideoRendererImpl_Seeking_Vtbl; + pVideoRenderer->sample_held = NULL; *ppv = (LPVOID)pVideoRenderer; } else @@ -774,9 +787,15 @@ static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface) EnterCriticalSection(&This->csFilter); { This->state = State_Stopped; + + if (This->sample_held) + { + IMediaSample_Release(This->sample_held); + This->sample_held = NULL; + } } LeaveCriticalSection(&This->csFilter); - + return S_OK; } @@ -812,6 +831,12 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta This->rtStreamStart = tStart; This->state = State_Running; + + if (This->sample_held) + { + IMediaSample_Release(This->sample_held); + This->sample_held = NULL; + } } LeaveCriticalSection(&This->csFilter); @@ -1438,8 +1463,59 @@ static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface, long *pBufferSize, long *pDIBImage) { ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); + BITMAPINFOHEADER *bmiHeader; + LONG needed_size; + AM_MEDIA_TYPE *amt = &This->pInputPin->pin.mtCurrent; + char *ptr; + + EnterCriticalSection(&This->csFilter); + + if (!This->sample_held) + { + LeaveCriticalSection(&This->csFilter); + return (This->state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED); + } + + FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage); - FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage); + if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo)) + { + bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader; + } + else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2)) + { + bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader; + } + else + { + FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype)); + LeaveCriticalSection(&This->csFilter); + return VFW_E_RUNTIME_ERROR; + } + + needed_size = bmiHeader->biSize; + needed_size += IMediaSample_GetActualDataLength(This->sample_held); + + if (!pDIBImage) + { + *pBufferSize = needed_size; + LeaveCriticalSection(&This->csFilter); + return S_OK; + } + + if (needed_size < *pBufferSize) + { + ERR("Buffer too small %u/%lu\n", needed_size, *pBufferSize); + LeaveCriticalSection(&This->csFilter); + return E_FAIL; + } + *pBufferSize = needed_size; + + memcpy(pDIBImage, bmiHeader, bmiHeader->biSize); + IMediaSample_GetPointer(This->sample_held, (BYTE **)&ptr); + memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->sample_held)); + + LeaveCriticalSection(&This->csFilter); return S_OK; } -- 1.5.4.1