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((IBaseFilter
*)iface
, IMediaStreamFilterImpl
, filter
.IBaseFilter_iface
);
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 CoTaskMemFree(This
->streams
);
241 CoTaskMemFree(This
->pins
);
242 BaseFilter_Destroy(&This
->filter
);
243 HeapFree(GetProcessHeap(), 0, This
);
249 /*** IPersist methods ***/
251 static HRESULT WINAPI
MediaStreamFilterImpl_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
253 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
254 return BaseFilterImpl_GetClassID(&This
->filter
.IBaseFilter_iface
, clsid
);
257 /*** IBaseFilter methods ***/
259 static HRESULT WINAPI
MediaStreamFilterImpl_Stop(IMediaStreamFilter
*iface
)
261 FIXME("(%p)->(): Stub!\n", iface
);
266 static HRESULT WINAPI
MediaStreamFilterImpl_Pause(IMediaStreamFilter
*iface
)
268 FIXME("(%p)->(): Stub!\n", iface
);
273 static HRESULT WINAPI
MediaStreamFilterImpl_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
275 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
280 static HRESULT WINAPI
MediaStreamFilterImpl_GetState(IMediaStreamFilter
*iface
, DWORD ms_timeout
, FILTER_STATE
*state
)
282 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
283 return BaseFilterImpl_GetState(&This
->filter
.IBaseFilter_iface
, ms_timeout
, state
);
286 static HRESULT WINAPI
MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
288 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
289 return BaseFilterImpl_SetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
292 static HRESULT WINAPI
MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
294 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
295 return BaseFilterImpl_GetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
298 static HRESULT WINAPI
MediaStreamFilterImpl_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
300 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
301 return BaseFilterImpl_EnumPins(&This
->filter
.IBaseFilter_iface
, enum_pins
);
304 static HRESULT WINAPI
MediaStreamFilterImpl_FindPin(IMediaStreamFilter
*iface
, LPCWSTR id
, IPin
**pin
)
306 FIXME("(%p)->(%s,%p): Stub!\n", iface
, debugstr_w(id
), pin
);
311 static HRESULT WINAPI
MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
313 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
314 return BaseFilterImpl_QueryFilterInfo(&This
->filter
.IBaseFilter_iface
, info
);
317 static HRESULT WINAPI
MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter
*iface
, IFilterGraph
*graph
, LPCWSTR name
)
319 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
320 return BaseFilterImpl_JoinFilterGraph(&This
->filter
.IBaseFilter_iface
, graph
, name
);
323 static HRESULT WINAPI
MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
325 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
326 return BaseFilterImpl_QueryVendorInfo(&This
->filter
.IBaseFilter_iface
, vendor_info
);
329 /*** IMediaStreamFilter methods ***/
331 static HRESULT WINAPI
MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter
* iface
, IAMMediaStream
*pAMMediaStream
)
333 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
334 IMediaStream
** streams
;
336 MediaStreamFilter_InputPin
* pin
;
341 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
343 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IMediaStream
*));
345 return E_OUTOFMEMORY
;
346 This
->streams
= streams
;
347 pins
= CoTaskMemRealloc(This
->pins
, (This
->nb_streams
+ 1) * sizeof(IPin
*));
349 return E_OUTOFMEMORY
;
351 info
.pFilter
= (IBaseFilter
*)&This
->filter
;
352 info
.dir
= PINDIR_INPUT
;
353 hr
= IAMMediaStream_GetInformation(pAMMediaStream
, &purpose_id
, NULL
);
356 /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */
357 info
.achName
[0] = 'I';
358 StringFromGUID2(&purpose_id
, info
.achName
+ 1, 40);
359 hr
= BaseInputPin_Construct(&MediaStreamFilter_InputPin_Vtbl
, sizeof(BaseInputPin
), &info
,
360 &input_BaseInputFuncTable
, &This
->filter
.csFilter
, NULL
, &This
->pins
[This
->nb_streams
]);
364 pin
= (MediaStreamFilter_InputPin
*)This
->pins
[This
->nb_streams
];
365 pin
->pin
.pin
.pinInfo
.pFilter
= (LPVOID
)This
;
366 This
->streams
[This
->nb_streams
] = (IMediaStream
*)pAMMediaStream
;
369 IMediaStream_AddRef((IMediaStream
*)pAMMediaStream
);
374 static HRESULT WINAPI
MediaStreamFilterImpl_GetMediaStream(IMediaStreamFilter
* iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
376 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
380 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
382 for (i
= 0; i
< This
->nb_streams
; i
++)
384 IMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
385 if (IsEqualIID(&purpose_id
, idPurpose
))
387 *ppMediaStream
= This
->streams
[i
];
388 IMediaStream_AddRef(*ppMediaStream
);
393 return MS_E_NOSTREAM
;
396 static HRESULT WINAPI
MediaStreamFilterImpl_EnumMediaStreams(IMediaStreamFilter
* iface
, LONG Index
, IMediaStream
**ppMediaStream
)
398 FIXME("(%p)->(%d,%p): Stub!\n", iface
, Index
, ppMediaStream
);
403 static HRESULT WINAPI
MediaStreamFilterImpl_SupportSeeking(IMediaStreamFilter
* iface
, BOOL bRenderer
)
405 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
410 static HRESULT WINAPI
MediaStreamFilterImpl_ReferenceTimeToStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pTime
)
412 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
417 static HRESULT WINAPI
MediaStreamFilterImpl_GetCurrentStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pCurrentStreamTime
)
419 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
424 static HRESULT WINAPI
MediaStreamFilterImpl_WaitUntil(IMediaStreamFilter
* iface
, REFERENCE_TIME WaitStreamTime
)
426 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
431 static HRESULT WINAPI
MediaStreamFilterImpl_Flush(IMediaStreamFilter
* iface
, BOOL bCancelEOS
)
433 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
438 static HRESULT WINAPI
MediaStreamFilterImpl_EndOfStream(IMediaStreamFilter
* iface
)
440 FIXME("(%p)->(): Stub!\n", iface
);
445 static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl
=
447 MediaStreamFilterImpl_QueryInterface
,
448 MediaStreamFilterImpl_AddRef
,
449 MediaStreamFilterImpl_Release
,
450 MediaStreamFilterImpl_GetClassID
,
451 MediaStreamFilterImpl_Stop
,
452 MediaStreamFilterImpl_Pause
,
453 MediaStreamFilterImpl_Run
,
454 MediaStreamFilterImpl_GetState
,
455 MediaStreamFilterImpl_SetSyncSource
,
456 MediaStreamFilterImpl_GetSyncSource
,
457 MediaStreamFilterImpl_EnumPins
,
458 MediaStreamFilterImpl_FindPin
,
459 MediaStreamFilterImpl_QueryFilterInfo
,
460 MediaStreamFilterImpl_JoinFilterGraph
,
461 MediaStreamFilterImpl_QueryVendorInfo
,
462 MediaStreamFilterImpl_AddMediaStream
,
463 MediaStreamFilterImpl_GetMediaStream
,
464 MediaStreamFilterImpl_EnumMediaStreams
,
465 MediaStreamFilterImpl_SupportSeeking
,
466 MediaStreamFilterImpl_ReferenceTimeToStreamTime
,
467 MediaStreamFilterImpl_GetCurrentStreamTime
,
468 MediaStreamFilterImpl_WaitUntil
,
469 MediaStreamFilterImpl_Flush
,
470 MediaStreamFilterImpl_EndOfStream
473 static IPin
* WINAPI
MediaStreamFilterImpl_GetPin(BaseFilter
*iface
, int pos
)
475 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
477 if (pos
< This
->nb_streams
)
479 IPin_AddRef(This
->pins
[pos
]);
480 return This
->pins
[pos
];
486 static LONG WINAPI
MediaStreamFilterImpl_GetPinCount(BaseFilter
*iface
)
488 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
490 return This
->nb_streams
;
493 static const BaseFilterFuncTable BaseFuncTable
= {
494 MediaStreamFilterImpl_GetPin
,
495 MediaStreamFilterImpl_GetPinCount
498 HRESULT
MediaStreamFilter_create(IUnknown
*pUnkOuter
, void **ppObj
)
500 IMediaStreamFilterImpl
* object
;
502 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
505 return CLASS_E_NOAGGREGATION
;
507 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IMediaStreamFilterImpl
));
509 return E_OUTOFMEMORY
;
511 BaseFilter_Init(&object
->filter
, (IBaseFilterVtbl
*)&MediaStreamFilter_Vtbl
, &CLSID_MediaStreamFilter
, (DWORD_PTR
)(__FILE__
": MediaStreamFilterImpl.csFilter"), &BaseFuncTable
);