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 "wine/debug.h"
29 #include "wine/strmbase.h"
31 #include "amstream_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(amstream
);
37 typedef struct MediaStreamFilter_InputPin
40 } MediaStreamFilter_InputPin
;
42 static const IPinVtbl MediaStreamFilter_InputPin_Vtbl
=
44 BaseInputPinImpl_QueryInterface
,
46 BaseInputPinImpl_Release
,
47 BaseInputPinImpl_Connect
,
48 BaseInputPinImpl_ReceiveConnection
,
49 BasePinImpl_Disconnect
,
50 BasePinImpl_ConnectedTo
,
51 BasePinImpl_ConnectionMediaType
,
52 BasePinImpl_QueryPinInfo
,
53 BasePinImpl_QueryDirection
,
55 BasePinImpl_QueryAccept
,
56 BasePinImpl_EnumMediaTypes
,
57 BasePinImpl_QueryInternalConnections
,
58 BaseInputPinImpl_EndOfStream
,
59 BaseInputPinImpl_BeginFlush
,
60 BaseInputPinImpl_EndFlush
,
61 BasePinImpl_NewSegment
67 IMediaStream
** streams
;
69 } IMediaStreamFilterImpl
;
71 static inline IMediaStreamFilterImpl
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
73 return CONTAINING_RECORD(iface
, IMediaStreamFilterImpl
, filter
);
76 static HRESULT WINAPI
BasePinImpl_CheckMediaType(BasePin
*This
, const AM_MEDIA_TYPE
*pmt
)
78 IMediaStreamFilterImpl
*filter
= impl_from_IMediaStreamFilter((IMediaStreamFilter
*)This
->pinInfo
.pFilter
);
82 TRACE("Checking media type %s - %s\n", debugstr_guid(&pmt
->majortype
), debugstr_guid(&pmt
->subtype
));
84 /* Find which stream is associated with the pin */
85 for (i
= 0; i
< filter
->nb_streams
; i
++)
86 if (&This
->IPin_iface
== filter
->pins
[i
])
89 if (i
== filter
->nb_streams
)
92 if (FAILED(IMediaStream_GetInformation(filter
->streams
[i
], &purpose_id
, NULL
)))
95 TRACE("Checking stream with purpose id %s\n", debugstr_guid(&purpose_id
));
97 if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryVideo
) && IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
99 if (IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB1
) ||
100 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB4
) ||
101 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB8
) ||
102 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB565
) ||
103 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB555
) ||
104 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB24
) ||
105 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB32
))
107 TRACE("Video sub-type %s matches\n", debugstr_guid(&pmt
->subtype
));
111 else if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryAudio
) && IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Audio
))
113 if (IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
115 TRACE("Audio sub-type %s matches\n", debugstr_guid(&pmt
->subtype
));
123 static LONG WINAPI
BasePinImp_GetMediaTypeVersion(BasePin
*This
)
128 static HRESULT WINAPI
BasePinImp_GetMediaType(BasePin
*This
, int index
, AM_MEDIA_TYPE
*amt
)
130 IMediaStreamFilterImpl
*filter
= (IMediaStreamFilterImpl
*)This
->pinInfo
.pFilter
;
134 /* FIXME: Reset structure as we only fill majortype and minortype for now */
135 ZeroMemory(amt
, sizeof(*amt
));
137 /* Find which stream is associated with the pin */
138 for (i
= 0; i
< filter
->nb_streams
; i
++)
139 if (&This
->IPin_iface
== filter
->pins
[i
])
142 if (i
== filter
->nb_streams
)
145 if (FAILED(IMediaStream_GetInformation(filter
->streams
[i
], &purpose_id
, NULL
)))
148 TRACE("Processing stream with purpose id %s\n", debugstr_guid(&purpose_id
));
150 if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryVideo
))
152 amt
->majortype
= MEDIATYPE_Video
;
157 amt
->subtype
= MEDIASUBTYPE_RGB1
;
160 amt
->subtype
= MEDIASUBTYPE_RGB4
;
163 amt
->subtype
= MEDIASUBTYPE_RGB8
;
166 amt
->subtype
= MEDIASUBTYPE_RGB565
;
169 amt
->subtype
= MEDIASUBTYPE_RGB555
;
172 amt
->subtype
= MEDIASUBTYPE_RGB24
;
175 amt
->subtype
= MEDIASUBTYPE_RGB32
;
181 else if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryAudio
))
186 amt
->majortype
= MEDIATYPE_Audio
;
187 amt
->subtype
= MEDIASUBTYPE_PCM
;
193 static const BaseInputPinFuncTable input_BaseInputFuncTable
= {
195 BasePinImpl_CheckMediaType
,
197 BasePinImp_GetMediaTypeVersion
,
198 BasePinImp_GetMediaType
203 /*** IUnknown methods ***/
205 static HRESULT WINAPI
MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter
*iface
, REFIID riid
, void **ret_iface
)
207 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
211 if (IsEqualIID(riid
, &IID_IUnknown
) ||
212 IsEqualIID(riid
, &IID_IPersist
) ||
213 IsEqualIID(riid
, &IID_IMediaFilter
) ||
214 IsEqualIID(riid
, &IID_IBaseFilter
) ||
215 IsEqualIID(riid
, &IID_IMediaStreamFilter
))
220 IMediaStreamFilter_AddRef(*ret_iface
);
224 return E_NOINTERFACE
;
227 static ULONG WINAPI
MediaStreamFilterImpl_AddRef(IMediaStreamFilter
*iface
)
229 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
230 ULONG ref
= BaseFilterImpl_AddRef(&This
->filter
.IBaseFilter_iface
);
232 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
237 static ULONG WINAPI
MediaStreamFilterImpl_Release(IMediaStreamFilter
*iface
)
239 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
240 ULONG ref
= InterlockedDecrement(&This
->filter
.refCount
);
242 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
247 for (i
= 0; i
< This
->nb_streams
; i
++)
249 IMediaStream_Release(This
->streams
[i
]);
250 IPin_Release(This
->pins
[i
]);
252 CoTaskMemFree(This
->streams
);
253 CoTaskMemFree(This
->pins
);
254 BaseFilter_Destroy(&This
->filter
);
255 HeapFree(GetProcessHeap(), 0, This
);
261 /*** IPersist methods ***/
263 static HRESULT WINAPI
MediaStreamFilterImpl_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
265 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
266 return BaseFilterImpl_GetClassID(&This
->filter
.IBaseFilter_iface
, clsid
);
269 /*** IBaseFilter methods ***/
271 static HRESULT WINAPI
MediaStreamFilterImpl_Stop(IMediaStreamFilter
*iface
)
273 FIXME("(%p)->(): Stub!\n", iface
);
278 static HRESULT WINAPI
MediaStreamFilterImpl_Pause(IMediaStreamFilter
*iface
)
280 FIXME("(%p)->(): Stub!\n", iface
);
285 static HRESULT WINAPI
MediaStreamFilterImpl_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
287 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
292 static HRESULT WINAPI
MediaStreamFilterImpl_GetState(IMediaStreamFilter
*iface
, DWORD ms_timeout
, FILTER_STATE
*state
)
294 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
295 return BaseFilterImpl_GetState(&This
->filter
.IBaseFilter_iface
, ms_timeout
, state
);
298 static HRESULT WINAPI
MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
300 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
301 return BaseFilterImpl_SetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
304 static HRESULT WINAPI
MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
306 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
307 return BaseFilterImpl_GetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
310 static HRESULT WINAPI
MediaStreamFilterImpl_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
312 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
313 return BaseFilterImpl_EnumPins(&This
->filter
.IBaseFilter_iface
, enum_pins
);
316 static HRESULT WINAPI
MediaStreamFilterImpl_FindPin(IMediaStreamFilter
*iface
, LPCWSTR id
, IPin
**pin
)
318 FIXME("(%p)->(%s,%p): Stub!\n", iface
, debugstr_w(id
), pin
);
323 static HRESULT WINAPI
MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
325 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
326 return BaseFilterImpl_QueryFilterInfo(&This
->filter
.IBaseFilter_iface
, info
);
329 static HRESULT WINAPI
MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter
*iface
, IFilterGraph
*graph
, LPCWSTR name
)
331 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
332 return BaseFilterImpl_JoinFilterGraph(&This
->filter
.IBaseFilter_iface
, graph
, name
);
335 static HRESULT WINAPI
MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
337 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
338 return BaseFilterImpl_QueryVendorInfo(&This
->filter
.IBaseFilter_iface
, vendor_info
);
341 /*** IMediaStreamFilter methods ***/
343 static HRESULT WINAPI
MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter
* iface
, IAMMediaStream
*pAMMediaStream
)
345 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
346 IMediaStream
** streams
;
348 MediaStreamFilter_InputPin
* pin
;
353 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
355 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IMediaStream
*));
357 return E_OUTOFMEMORY
;
358 This
->streams
= streams
;
359 pins
= CoTaskMemRealloc(This
->pins
, (This
->nb_streams
+ 1) * sizeof(IPin
*));
361 return E_OUTOFMEMORY
;
363 info
.pFilter
= &This
->filter
.IBaseFilter_iface
;
364 info
.dir
= PINDIR_INPUT
;
365 hr
= IAMMediaStream_GetInformation(pAMMediaStream
, &purpose_id
, NULL
);
368 /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */
369 info
.achName
[0] = 'I';
370 StringFromGUID2(&purpose_id
, info
.achName
+ 1, 40);
371 hr
= BaseInputPin_Construct(&MediaStreamFilter_InputPin_Vtbl
, sizeof(BaseInputPin
), &info
,
372 &input_BaseInputFuncTable
, &This
->filter
.csFilter
, NULL
, &This
->pins
[This
->nb_streams
]);
376 pin
= (MediaStreamFilter_InputPin
*)This
->pins
[This
->nb_streams
];
377 pin
->pin
.pin
.pinInfo
.pFilter
= &This
->filter
.IBaseFilter_iface
;
378 This
->streams
[This
->nb_streams
] = (IMediaStream
*)pAMMediaStream
;
381 IAMMediaStream_AddRef(pAMMediaStream
);
386 static HRESULT WINAPI
MediaStreamFilterImpl_GetMediaStream(IMediaStreamFilter
* iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
388 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
392 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
394 for (i
= 0; i
< This
->nb_streams
; i
++)
396 IMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
397 if (IsEqualIID(&purpose_id
, idPurpose
))
399 *ppMediaStream
= This
->streams
[i
];
400 IMediaStream_AddRef(*ppMediaStream
);
405 return MS_E_NOSTREAM
;
408 static HRESULT WINAPI
MediaStreamFilterImpl_EnumMediaStreams(IMediaStreamFilter
* iface
, LONG Index
, IMediaStream
**ppMediaStream
)
410 FIXME("(%p)->(%d,%p): Stub!\n", iface
, Index
, ppMediaStream
);
415 static HRESULT WINAPI
MediaStreamFilterImpl_SupportSeeking(IMediaStreamFilter
* iface
, BOOL bRenderer
)
417 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
422 static HRESULT WINAPI
MediaStreamFilterImpl_ReferenceTimeToStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pTime
)
424 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
429 static HRESULT WINAPI
MediaStreamFilterImpl_GetCurrentStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pCurrentStreamTime
)
431 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
436 static HRESULT WINAPI
MediaStreamFilterImpl_WaitUntil(IMediaStreamFilter
* iface
, REFERENCE_TIME WaitStreamTime
)
438 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
443 static HRESULT WINAPI
MediaStreamFilterImpl_Flush(IMediaStreamFilter
* iface
, BOOL bCancelEOS
)
445 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
450 static HRESULT WINAPI
MediaStreamFilterImpl_EndOfStream(IMediaStreamFilter
* iface
)
452 FIXME("(%p)->(): Stub!\n", iface
);
457 static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl
=
459 MediaStreamFilterImpl_QueryInterface
,
460 MediaStreamFilterImpl_AddRef
,
461 MediaStreamFilterImpl_Release
,
462 MediaStreamFilterImpl_GetClassID
,
463 MediaStreamFilterImpl_Stop
,
464 MediaStreamFilterImpl_Pause
,
465 MediaStreamFilterImpl_Run
,
466 MediaStreamFilterImpl_GetState
,
467 MediaStreamFilterImpl_SetSyncSource
,
468 MediaStreamFilterImpl_GetSyncSource
,
469 MediaStreamFilterImpl_EnumPins
,
470 MediaStreamFilterImpl_FindPin
,
471 MediaStreamFilterImpl_QueryFilterInfo
,
472 MediaStreamFilterImpl_JoinFilterGraph
,
473 MediaStreamFilterImpl_QueryVendorInfo
,
474 MediaStreamFilterImpl_AddMediaStream
,
475 MediaStreamFilterImpl_GetMediaStream
,
476 MediaStreamFilterImpl_EnumMediaStreams
,
477 MediaStreamFilterImpl_SupportSeeking
,
478 MediaStreamFilterImpl_ReferenceTimeToStreamTime
,
479 MediaStreamFilterImpl_GetCurrentStreamTime
,
480 MediaStreamFilterImpl_WaitUntil
,
481 MediaStreamFilterImpl_Flush
,
482 MediaStreamFilterImpl_EndOfStream
485 static IPin
* WINAPI
MediaStreamFilterImpl_GetPin(BaseFilter
*iface
, int pos
)
487 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
489 if (pos
< This
->nb_streams
)
491 IPin_AddRef(This
->pins
[pos
]);
492 return This
->pins
[pos
];
498 static LONG WINAPI
MediaStreamFilterImpl_GetPinCount(BaseFilter
*iface
)
500 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
502 return This
->nb_streams
;
505 static const BaseFilterFuncTable BaseFuncTable
= {
506 MediaStreamFilterImpl_GetPin
,
507 MediaStreamFilterImpl_GetPinCount
510 HRESULT
MediaStreamFilter_create(IUnknown
*pUnkOuter
, void **ppObj
)
512 IMediaStreamFilterImpl
* object
;
514 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
517 return CLASS_E_NOAGGREGATION
;
519 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IMediaStreamFilterImpl
));
521 return E_OUTOFMEMORY
;
523 BaseFilter_Init(&object
->filter
, (IBaseFilterVtbl
*)&MediaStreamFilter_Vtbl
, &CLSID_MediaStreamFilter
, (DWORD_PTR
)(__FILE__
": MediaStreamFilterImpl.csFilter"), &BaseFuncTable
);
525 *ppObj
= &object
->filter
.IBaseFilter_iface
;