2 * Implementation of MediaStream Filter
4 * Copyright 2008, 2012 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "amstream_private.h"
23 #include <wine/strmbase.h>
25 typedef struct MediaStreamFilter_InputPin
28 } MediaStreamFilter_InputPin
;
30 static const IPinVtbl MediaStreamFilter_InputPin_Vtbl
=
32 BaseInputPinImpl_QueryInterface
,
34 BaseInputPinImpl_Release
,
35 BaseInputPinImpl_Connect
,
36 BaseInputPinImpl_ReceiveConnection
,
37 BasePinImpl_Disconnect
,
38 BasePinImpl_ConnectedTo
,
39 BasePinImpl_ConnectionMediaType
,
40 BasePinImpl_QueryPinInfo
,
41 BasePinImpl_QueryDirection
,
43 BasePinImpl_QueryAccept
,
44 BasePinImpl_EnumMediaTypes
,
45 BasePinImpl_QueryInternalConnections
,
46 BaseInputPinImpl_EndOfStream
,
47 BaseInputPinImpl_BeginFlush
,
48 BaseInputPinImpl_EndFlush
,
49 BasePinImpl_NewSegment
55 IMediaStream
** streams
;
57 } IMediaStreamFilterImpl
;
59 static inline IMediaStreamFilterImpl
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
61 return CONTAINING_RECORD(iface
, IMediaStreamFilterImpl
, filter
);
64 static HRESULT WINAPI
BasePinImpl_CheckMediaType(BasePin
*This
, const AM_MEDIA_TYPE
*pmt
)
66 IMediaStreamFilterImpl
*filter
= impl_from_IMediaStreamFilter((IMediaStreamFilter
*)This
->pinInfo
.pFilter
);
70 TRACE("Checking media type %s - %s\n", debugstr_guid(&pmt
->majortype
), debugstr_guid(&pmt
->subtype
));
72 /* Find which stream is associated with the pin */
73 for (i
= 0; i
< filter
->nb_streams
; i
++)
74 if (&This
->IPin_iface
== filter
->pins
[i
])
77 if (i
== filter
->nb_streams
)
80 if (FAILED(IMediaStream_GetInformation(filter
->streams
[i
], &purpose_id
, NULL
)))
83 TRACE("Checking stream with purpose id %s\n", debugstr_guid(&purpose_id
));
85 if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryVideo
) && IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
87 if (IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB1
) ||
88 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB4
) ||
89 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB8
) ||
90 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB565
) ||
91 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB555
) ||
92 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB24
) ||
93 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB32
))
95 TRACE("Video sub-type %s matches\n", debugstr_guid(&pmt
->subtype
));
99 else if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryAudio
) && IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Audio
))
101 if (IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
103 TRACE("Audio sub-type %s matches\n", debugstr_guid(&pmt
->subtype
));
111 static LONG WINAPI
BasePinImp_GetMediaTypeVersion(BasePin
*This
)
116 static HRESULT WINAPI
BasePinImp_GetMediaType(BasePin
*This
, int index
, AM_MEDIA_TYPE
*amt
)
118 IMediaStreamFilterImpl
*filter
= (IMediaStreamFilterImpl
*)This
->pinInfo
.pFilter
;
122 /* FIXME: Reset structure as we only fill majortype and minortype for now */
123 ZeroMemory(amt
, sizeof(*amt
));
125 /* Find which stream is associated with the pin */
126 for (i
= 0; i
< filter
->nb_streams
; i
++)
127 if (&This
->IPin_iface
== filter
->pins
[i
])
130 if (i
== filter
->nb_streams
)
133 if (FAILED(IMediaStream_GetInformation(filter
->streams
[i
], &purpose_id
, NULL
)))
136 TRACE("Processing stream with purpose id %s\n", debugstr_guid(&purpose_id
));
138 if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryVideo
))
140 amt
->majortype
= MEDIATYPE_Video
;
145 amt
->subtype
= MEDIASUBTYPE_RGB1
;
148 amt
->subtype
= MEDIASUBTYPE_RGB4
;
151 amt
->subtype
= MEDIASUBTYPE_RGB8
;
154 amt
->subtype
= MEDIASUBTYPE_RGB565
;
157 amt
->subtype
= MEDIASUBTYPE_RGB555
;
160 amt
->subtype
= MEDIASUBTYPE_RGB24
;
163 amt
->subtype
= MEDIASUBTYPE_RGB32
;
169 else if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryAudio
))
174 amt
->majortype
= MEDIATYPE_Audio
;
175 amt
->subtype
= MEDIASUBTYPE_PCM
;
181 static const BaseInputPinFuncTable input_BaseInputFuncTable
= {
183 BasePinImpl_CheckMediaType
,
185 BasePinImp_GetMediaTypeVersion
,
186 BasePinImp_GetMediaType
191 /*** IUnknown methods ***/
193 static HRESULT WINAPI
MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter
*iface
, REFIID riid
, void **ret_iface
)
195 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
199 if (IsEqualIID(riid
, &IID_IUnknown
) ||
200 IsEqualIID(riid
, &IID_IPersist
) ||
201 IsEqualIID(riid
, &IID_IMediaFilter
) ||
202 IsEqualIID(riid
, &IID_IBaseFilter
) ||
203 IsEqualIID(riid
, &IID_IMediaStreamFilter
))
208 IMediaStreamFilter_AddRef(*ret_iface
);
212 return E_NOINTERFACE
;
215 static ULONG WINAPI
MediaStreamFilterImpl_AddRef(IMediaStreamFilter
*iface
)
217 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
218 ULONG ref
= BaseFilterImpl_AddRef(&This
->filter
.IBaseFilter_iface
);
220 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
225 static ULONG WINAPI
MediaStreamFilterImpl_Release(IMediaStreamFilter
*iface
)
227 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
228 ULONG ref
= InterlockedDecrement(&This
->filter
.refCount
);
230 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
235 for (i
= 0; i
< This
->nb_streams
; i
++)
237 IMediaStream_Release(This
->streams
[i
]);
238 IPin_Release(This
->pins
[i
]);
240 BaseFilter_Destroy(&This
->filter
);
241 HeapFree(GetProcessHeap(), 0, This
);
247 /*** IPersist methods ***/
249 static HRESULT WINAPI
MediaStreamFilterImpl_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
251 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
252 return BaseFilterImpl_GetClassID(&This
->filter
.IBaseFilter_iface
, clsid
);
255 /*** IBaseFilter methods ***/
257 static HRESULT WINAPI
MediaStreamFilterImpl_Stop(IMediaStreamFilter
*iface
)
259 FIXME("(%p)->(): Stub!\n", iface
);
264 static HRESULT WINAPI
MediaStreamFilterImpl_Pause(IMediaStreamFilter
*iface
)
266 FIXME("(%p)->(): Stub!\n", iface
);
271 static HRESULT WINAPI
MediaStreamFilterImpl_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
273 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
278 static HRESULT WINAPI
MediaStreamFilterImpl_GetState(IMediaStreamFilter
*iface
, DWORD ms_timeout
, FILTER_STATE
*state
)
280 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
281 return BaseFilterImpl_GetState(&This
->filter
.IBaseFilter_iface
, ms_timeout
, state
);
284 static HRESULT WINAPI
MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
286 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
287 return BaseFilterImpl_SetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
290 static HRESULT WINAPI
MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
292 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
293 return BaseFilterImpl_GetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
296 static HRESULT WINAPI
MediaStreamFilterImpl_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
298 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
299 return BaseFilterImpl_EnumPins(&This
->filter
.IBaseFilter_iface
, enum_pins
);
302 static HRESULT WINAPI
MediaStreamFilterImpl_FindPin(IMediaStreamFilter
*iface
, LPCWSTR id
, IPin
**pin
)
304 FIXME("(%p)->(%s,%p): Stub!\n", iface
, debugstr_w(id
), pin
);
309 static HRESULT WINAPI
MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
311 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
312 return BaseFilterImpl_QueryFilterInfo(&This
->filter
.IBaseFilter_iface
, info
);
315 static HRESULT WINAPI
MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter
*iface
, IFilterGraph
*graph
, LPCWSTR name
)
317 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
318 return BaseFilterImpl_JoinFilterGraph(&This
->filter
.IBaseFilter_iface
, graph
, name
);
321 static HRESULT WINAPI
MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
323 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
324 return BaseFilterImpl_QueryVendorInfo(&This
->filter
.IBaseFilter_iface
, vendor_info
);
327 /*** IMediaStreamFilter methods ***/
329 static HRESULT WINAPI
MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter
* iface
, IAMMediaStream
*pAMMediaStream
)
331 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
332 IMediaStream
** streams
;
334 MediaStreamFilter_InputPin
* pin
;
339 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
341 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IMediaStream
*));
343 return E_OUTOFMEMORY
;
344 This
->streams
= streams
;
345 pins
= CoTaskMemRealloc(This
->pins
, (This
->nb_streams
+ 1) * sizeof(IPin
*));
347 return E_OUTOFMEMORY
;
349 info
.pFilter
= (IBaseFilter
*)&This
->filter
;
350 info
.dir
= PINDIR_INPUT
;
351 hr
= IAMMediaStream_GetInformation(pAMMediaStream
, &purpose_id
, NULL
);
354 /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */
355 info
.achName
[0] = 'I';
356 StringFromGUID2(&purpose_id
, info
.achName
+ 1, 40);
357 hr
= BaseInputPin_Construct(&MediaStreamFilter_InputPin_Vtbl
, sizeof(BaseInputPin
), &info
,
358 &input_BaseInputFuncTable
, &This
->filter
.csFilter
, NULL
, &This
->pins
[This
->nb_streams
]);
362 pin
= (MediaStreamFilter_InputPin
*)This
->pins
[This
->nb_streams
];
363 pin
->pin
.pin
.pinInfo
.pFilter
= (LPVOID
)This
;
364 This
->streams
[This
->nb_streams
] = (IMediaStream
*)pAMMediaStream
;
367 IMediaStream_AddRef((IMediaStream
*)pAMMediaStream
);
372 static HRESULT WINAPI
MediaStreamFilterImpl_GetMediaStream(IMediaStreamFilter
* iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
374 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
378 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
380 for (i
= 0; i
< This
->nb_streams
; i
++)
382 IMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
383 if (IsEqualIID(&purpose_id
, idPurpose
))
385 *ppMediaStream
= This
->streams
[i
];
386 IMediaStream_AddRef(*ppMediaStream
);
391 return MS_E_NOSTREAM
;
394 static HRESULT WINAPI
MediaStreamFilterImpl_EnumMediaStreams(IMediaStreamFilter
* iface
, LONG Index
, IMediaStream
**ppMediaStream
)
396 FIXME("(%p)->(%d,%p): Stub!\n", iface
, Index
, ppMediaStream
);
401 static HRESULT WINAPI
MediaStreamFilterImpl_SupportSeeking(IMediaStreamFilter
* iface
, BOOL bRenderer
)
403 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
408 static HRESULT WINAPI
MediaStreamFilterImpl_ReferenceTimeToStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pTime
)
410 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
415 static HRESULT WINAPI
MediaStreamFilterImpl_GetCurrentStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pCurrentStreamTime
)
417 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
422 static HRESULT WINAPI
MediaStreamFilterImpl_WaitUntil(IMediaStreamFilter
* iface
, REFERENCE_TIME WaitStreamTime
)
424 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
429 static HRESULT WINAPI
MediaStreamFilterImpl_Flush(IMediaStreamFilter
* iface
, BOOL bCancelEOS
)
431 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
436 static HRESULT WINAPI
MediaStreamFilterImpl_EndOfStream(IMediaStreamFilter
* iface
)
438 FIXME("(%p)->(): Stub!\n", iface
);
443 static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl
=
445 MediaStreamFilterImpl_QueryInterface
,
446 MediaStreamFilterImpl_AddRef
,
447 MediaStreamFilterImpl_Release
,
448 MediaStreamFilterImpl_GetClassID
,
449 MediaStreamFilterImpl_Stop
,
450 MediaStreamFilterImpl_Pause
,
451 MediaStreamFilterImpl_Run
,
452 MediaStreamFilterImpl_GetState
,
453 MediaStreamFilterImpl_SetSyncSource
,
454 MediaStreamFilterImpl_GetSyncSource
,
455 MediaStreamFilterImpl_EnumPins
,
456 MediaStreamFilterImpl_FindPin
,
457 MediaStreamFilterImpl_QueryFilterInfo
,
458 MediaStreamFilterImpl_JoinFilterGraph
,
459 MediaStreamFilterImpl_QueryVendorInfo
,
460 MediaStreamFilterImpl_AddMediaStream
,
461 MediaStreamFilterImpl_GetMediaStream
,
462 MediaStreamFilterImpl_EnumMediaStreams
,
463 MediaStreamFilterImpl_SupportSeeking
,
464 MediaStreamFilterImpl_ReferenceTimeToStreamTime
,
465 MediaStreamFilterImpl_GetCurrentStreamTime
,
466 MediaStreamFilterImpl_WaitUntil
,
467 MediaStreamFilterImpl_Flush
,
468 MediaStreamFilterImpl_EndOfStream
471 static IPin
* WINAPI
MediaStreamFilterImpl_GetPin(BaseFilter
*iface
, int pos
)
473 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
475 if (pos
< This
->nb_streams
)
477 IPin_AddRef(This
->pins
[pos
]);
478 return This
->pins
[pos
];
484 static LONG WINAPI
MediaStreamFilterImpl_GetPinCount(BaseFilter
*iface
)
486 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
488 return This
->nb_streams
;
491 static const BaseFilterFuncTable BaseFuncTable
= {
492 MediaStreamFilterImpl_GetPin
,
493 MediaStreamFilterImpl_GetPinCount
496 HRESULT
MediaStreamFilter_create(IUnknown
*pUnkOuter
, void **ppObj
)
498 IMediaStreamFilterImpl
* object
;
500 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
503 return CLASS_E_NOAGGREGATION
;
505 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IMediaStreamFilterImpl
));
507 return E_OUTOFMEMORY
;
509 BaseFilter_Init(&object
->filter
, (IBaseFilterVtbl
*)&MediaStreamFilter_Vtbl
, &CLSID_MediaStreamFilter
, (DWORD_PTR
)(__FILE__
": MediaStreamFilterImpl.csFilter"), &BaseFuncTable
);