2 * Video Mixing Renderer for dx9
4 * Copyright 2004 Christian Costa
5 * Copyright 2008 Maarten Lankhorst
6 * Copyright 2012 Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "quartz_private.h"
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
50 BaseRenderer renderer;
51 IUnknown IUnknown_inner;
53 BITMAPINFOHEADER bmiheader;
59 static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface)
61 return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner);
64 static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
66 VMR9Impl *This = (VMR9Impl *)iface;
67 LPBYTE pbSrcStream = NULL;
68 REFERENCE_TIME tStart, tStop;
69 VMR9PresentationInfo info;
72 TRACE("%p %p\n", iface, pSample);
74 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
76 info.dwFlags = VMR9Sample_SrcDstRectsValid;
78 info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
80 if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
81 info.dwFlags |= VMR9Sample_Discontinuity;
83 if (IMediaSample_IsPreroll(pSample) == S_OK)
84 info.dwFlags |= VMR9Sample_Preroll;
86 if (IMediaSample_IsSyncPoint(pSample) == S_OK)
87 info.dwFlags |= VMR9Sample_SyncPoint;
89 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
92 ERR("Cannot get pointer to sample data (%x)\n", hr);
96 info.rtStart = tStart;
98 info.szAspectRatio.cx = This->bmiheader.biWidth;
99 info.szAspectRatio.cy = This->bmiheader.biHeight;
104 static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
106 VMR9Impl *This = (VMR9Impl*)iface;
108 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
111 /* Ignore subtype, test for bicompression instead */
112 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
114 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
116 This->bmiheader = format->bmiHeader;
117 TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
119 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
121 VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
123 This->bmiheader = format->bmiHeader;
125 TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
129 ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
132 if (This->bmiheader.biCompression)
137 HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
139 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
140 if (IMediaSample_IsPreroll(pSample) == S_OK)
145 static const BaseRendererFuncTable BaseFuncTable = {
157 VMR9_ShouldDrawSampleNow,
167 static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
169 VMR9Impl *This = impl_from_inner_IUnknown(iface);
170 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
172 if (This->bAggregatable)
173 This->bUnkOuterValid = TRUE;
177 if (IsEqualIID(riid, &IID_IUnknown))
178 *ppv = &This->IUnknown_inner;
182 hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
189 IUnknown_AddRef((IUnknown *)(*ppv));
193 else if (IsEqualIID(riid, &IID_IBasicVideo))
194 FIXME("No interface for IID_IBasicVideo\n");
195 else if (IsEqualIID(riid, &IID_IBasicVideo2))
196 FIXME("No interface for IID_IBasicVideo2\n");
197 else if (IsEqualIID(riid, &IID_IVideoWindow))
198 FIXME("No interface for IID_IVideoWindow\n");
199 else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
201 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
203 else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
204 FIXME("No interface for IID_IAMFilterMiscFlags\n");
205 else if (IsEqualIID(riid, &IID_IMediaPosition))
206 FIXME("No interface for IID_IMediaPosition\n");
207 else if (IsEqualIID(riid, &IID_IQualProp))
208 FIXME("No interface for IID_IQualProp\n");
209 else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
210 FIXME("No interface for IID_IVMRAspectRatioControl9\n");
211 else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
212 FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
213 else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
214 FIXME("No interface for IID_IVMRMixerBitmap9\n");
215 else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
216 FIXME("No interface for IID_IVMRMonitorConfig9\n");
217 else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
218 FIXME("No interface for IID_IVMRMixerControl9\n");
220 FIXME("No interface for %s\n", debugstr_guid(riid));
222 return E_NOINTERFACE;
225 static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
227 VMR9Impl *This = impl_from_inner_IUnknown(iface);
228 ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
230 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
235 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
237 VMR9Impl *This = impl_from_inner_IUnknown(iface);
238 ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
240 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
244 TRACE("Destroying\n");
251 static const IUnknownVtbl IInner_VTable =
253 VMR9Inner_QueryInterface,
258 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
260 VMR9Impl *This = (VMR9Impl *)iface;
262 if (This->bAggregatable)
263 This->bUnkOuterValid = TRUE;
267 if (This->bAggregatable)
268 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
270 if (IsEqualIID(riid, &IID_IUnknown))
274 IUnknown_AddRef(&This->IUnknown_inner);
275 hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
276 IUnknown_Release(&This->IUnknown_inner);
277 This->bAggregatable = TRUE;
282 return E_NOINTERFACE;
285 return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
288 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
290 VMR9Impl *This = (VMR9Impl *)iface;
293 if (This->outer_unk && This->bUnkOuterValid)
294 ret = IUnknown_AddRef(This->outer_unk);
296 ret = IUnknown_AddRef(&This->IUnknown_inner);
298 TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
303 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
305 VMR9Impl *This = (VMR9Impl *)iface;
308 if (This->outer_unk && This->bUnkOuterValid)
309 ret = IUnknown_Release(This->outer_unk);
311 ret = IUnknown_Release(&This->IUnknown_inner);
313 TRACE("(%p)->Release from %d\n", iface, ret + 1);
320 static const IBaseFilterVtbl VMR9_Vtbl =
325 BaseFilterImpl_GetClassID,
326 BaseRendererImpl_Stop,
327 BaseRendererImpl_Pause,
328 BaseRendererImpl_Run,
329 BaseRendererImpl_GetState,
330 BaseRendererImpl_SetSyncSource,
331 BaseFilterImpl_GetSyncSource,
332 BaseFilterImpl_EnumPins,
333 BaseRendererImpl_FindPin,
334 BaseFilterImpl_QueryFilterInfo,
335 BaseFilterImpl_JoinFilterGraph,
336 BaseFilterImpl_QueryVendorInfo
339 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
344 TRACE("(%p, %p)\n", outer_unk, ppv);
348 pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
350 pVMR9->outer_unk = outer_unk;
351 pVMR9->bUnkOuterValid = FALSE;
352 pVMR9->bAggregatable = FALSE;
353 pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
355 hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
359 *ppv = (LPVOID)pVMR9;
360 TRACE("Created at %p\n", pVMR9);
364 BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
365 CoTaskMemFree(pVMR9);