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"
36 WINE_DEFAULT_DEBUG_CHANNEL(amstream
);
38 typedef struct MediaStreamFilter_InputPin
41 } MediaStreamFilter_InputPin
;
43 static const IPinVtbl MediaStreamFilter_InputPin_Vtbl
=
45 BaseInputPinImpl_QueryInterface
,
47 BaseInputPinImpl_Release
,
48 BaseInputPinImpl_Connect
,
49 BaseInputPinImpl_ReceiveConnection
,
50 BasePinImpl_Disconnect
,
51 BasePinImpl_ConnectedTo
,
52 BasePinImpl_ConnectionMediaType
,
53 BasePinImpl_QueryPinInfo
,
54 BasePinImpl_QueryDirection
,
56 BasePinImpl_QueryAccept
,
57 BasePinImpl_EnumMediaTypes
,
58 BasePinImpl_QueryInternalConnections
,
59 BaseInputPinImpl_EndOfStream
,
60 BaseInputPinImpl_BeginFlush
,
61 BaseInputPinImpl_EndFlush
,
62 BasePinImpl_NewSegment
68 IMediaStream
** streams
;
70 } IMediaStreamFilterImpl
;
72 static inline IMediaStreamFilterImpl
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
74 return CONTAINING_RECORD(iface
, IMediaStreamFilterImpl
, filter
);
77 static HRESULT WINAPI
BasePinImpl_CheckMediaType(BasePin
*This
, const AM_MEDIA_TYPE
*pmt
)
79 IMediaStreamFilterImpl
*filter
= impl_from_IMediaStreamFilter((IMediaStreamFilter
*)This
->pinInfo
.pFilter
);
83 TRACE("Checking media type %s - %s\n", debugstr_guid(&pmt
->majortype
), debugstr_guid(&pmt
->subtype
));
85 /* Find which stream is associated with the pin */
86 for (i
= 0; i
< filter
->nb_streams
; i
++)
87 if (&This
->IPin_iface
== filter
->pins
[i
])
90 if (i
== filter
->nb_streams
)
93 if (FAILED(IMediaStream_GetInformation(filter
->streams
[i
], &purpose_id
, NULL
)))
96 TRACE("Checking stream with purpose id %s\n", debugstr_guid(&purpose_id
));
98 if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryVideo
) && IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
100 if (IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB1
) ||
101 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB4
) ||
102 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB8
) ||
103 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB565
) ||
104 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB555
) ||
105 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB24
) ||
106 IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_RGB32
))
108 TRACE("Video sub-type %s matches\n", debugstr_guid(&pmt
->subtype
));
112 else if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryAudio
) && IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Audio
))
114 if (IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_PCM
))
116 TRACE("Audio sub-type %s matches\n", debugstr_guid(&pmt
->subtype
));
124 static LONG WINAPI
BasePinImp_GetMediaTypeVersion(BasePin
*This
)
129 static HRESULT WINAPI
BasePinImp_GetMediaType(BasePin
*This
, int index
, AM_MEDIA_TYPE
*amt
)
131 IMediaStreamFilterImpl
*filter
= (IMediaStreamFilterImpl
*)This
->pinInfo
.pFilter
;
135 /* FIXME: Reset structure as we only fill majortype and minortype for now */
136 ZeroMemory(amt
, sizeof(*amt
));
138 /* Find which stream is associated with the pin */
139 for (i
= 0; i
< filter
->nb_streams
; i
++)
140 if (&This
->IPin_iface
== filter
->pins
[i
])
143 if (i
== filter
->nb_streams
)
146 if (FAILED(IMediaStream_GetInformation(filter
->streams
[i
], &purpose_id
, NULL
)))
149 TRACE("Processing stream with purpose id %s\n", debugstr_guid(&purpose_id
));
151 if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryVideo
))
153 amt
->majortype
= MEDIATYPE_Video
;
158 amt
->subtype
= MEDIASUBTYPE_RGB1
;
161 amt
->subtype
= MEDIASUBTYPE_RGB4
;
164 amt
->subtype
= MEDIASUBTYPE_RGB8
;
167 amt
->subtype
= MEDIASUBTYPE_RGB565
;
170 amt
->subtype
= MEDIASUBTYPE_RGB555
;
173 amt
->subtype
= MEDIASUBTYPE_RGB24
;
176 amt
->subtype
= MEDIASUBTYPE_RGB32
;
182 else if (IsEqualGUID(&purpose_id
, &MSPID_PrimaryAudio
))
187 amt
->majortype
= MEDIATYPE_Audio
;
188 amt
->subtype
= MEDIASUBTYPE_PCM
;
194 static const BaseInputPinFuncTable input_BaseInputFuncTable
= {
196 BasePinImpl_CheckMediaType
,
198 BasePinImp_GetMediaTypeVersion
,
199 BasePinImp_GetMediaType
204 /*** IUnknown methods ***/
206 static HRESULT WINAPI
MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter
*iface
, REFIID riid
, void **ret_iface
)
208 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
212 if (IsEqualIID(riid
, &IID_IUnknown
) ||
213 IsEqualIID(riid
, &IID_IPersist
) ||
214 IsEqualIID(riid
, &IID_IMediaFilter
) ||
215 IsEqualIID(riid
, &IID_IBaseFilter
) ||
216 IsEqualIID(riid
, &IID_IMediaStreamFilter
))
221 IMediaStreamFilter_AddRef(*ret_iface
);
225 return E_NOINTERFACE
;
228 static ULONG WINAPI
MediaStreamFilterImpl_AddRef(IMediaStreamFilter
*iface
)
230 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
231 ULONG ref
= BaseFilterImpl_AddRef(&This
->filter
.IBaseFilter_iface
);
233 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
238 static ULONG WINAPI
MediaStreamFilterImpl_Release(IMediaStreamFilter
*iface
)
240 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
241 ULONG ref
= InterlockedDecrement(&This
->filter
.refCount
);
243 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
248 for (i
= 0; i
< This
->nb_streams
; i
++)
250 IMediaStream_Release(This
->streams
[i
]);
251 IPin_Release(This
->pins
[i
]);
253 BaseFilter_Destroy(&This
->filter
);
254 HeapFree(GetProcessHeap(), 0, This
);
260 /*** IPersist methods ***/
262 static HRESULT WINAPI
MediaStreamFilterImpl_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
264 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
265 return BaseFilterImpl_GetClassID(&This
->filter
.IBaseFilter_iface
, clsid
);
268 /*** IBaseFilter methods ***/
270 static HRESULT WINAPI
MediaStreamFilterImpl_Stop(IMediaStreamFilter
*iface
)
272 FIXME("(%p)->(): Stub!\n", iface
);
277 static HRESULT WINAPI
MediaStreamFilterImpl_Pause(IMediaStreamFilter
*iface
)
279 FIXME("(%p)->(): Stub!\n", iface
);
284 static HRESULT WINAPI
MediaStreamFilterImpl_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
286 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
291 static HRESULT WINAPI
MediaStreamFilterImpl_GetState(IMediaStreamFilter
*iface
, DWORD ms_timeout
, FILTER_STATE
*state
)
293 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
294 return BaseFilterImpl_GetState(&This
->filter
.IBaseFilter_iface
, ms_timeout
, state
);
297 static HRESULT WINAPI
MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
299 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
300 return BaseFilterImpl_SetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
303 static HRESULT WINAPI
MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
305 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
306 return BaseFilterImpl_GetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
309 static HRESULT WINAPI
MediaStreamFilterImpl_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
311 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
312 return BaseFilterImpl_EnumPins(&This
->filter
.IBaseFilter_iface
, enum_pins
);
315 static HRESULT WINAPI
MediaStreamFilterImpl_FindPin(IMediaStreamFilter
*iface
, LPCWSTR id
, IPin
**pin
)
317 FIXME("(%p)->(%s,%p): Stub!\n", iface
, debugstr_w(id
), pin
);
322 static HRESULT WINAPI
MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
324 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
325 return BaseFilterImpl_QueryFilterInfo(&This
->filter
.IBaseFilter_iface
, info
);
328 static HRESULT WINAPI
MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter
*iface
, IFilterGraph
*graph
, LPCWSTR name
)
330 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
331 return BaseFilterImpl_JoinFilterGraph(&This
->filter
.IBaseFilter_iface
, graph
, name
);
334 static HRESULT WINAPI
MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
336 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
337 return BaseFilterImpl_QueryVendorInfo(&This
->filter
.IBaseFilter_iface
, vendor_info
);
340 /*** IMediaStreamFilter methods ***/
342 static HRESULT WINAPI
MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter
* iface
, IAMMediaStream
*pAMMediaStream
)
344 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
345 IMediaStream
** streams
;
347 MediaStreamFilter_InputPin
* pin
;
352 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
354 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IMediaStream
*));
356 return E_OUTOFMEMORY
;
357 This
->streams
= streams
;
358 pins
= CoTaskMemRealloc(This
->pins
, (This
->nb_streams
+ 1) * sizeof(IPin
*));
360 return E_OUTOFMEMORY
;
362 info
.pFilter
= (IBaseFilter
*)&This
->filter
;
363 info
.dir
= PINDIR_INPUT
;
364 hr
= IAMMediaStream_GetInformation(pAMMediaStream
, &purpose_id
, NULL
);
367 /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */
368 info
.achName
[0] = 'I';
369 StringFromGUID2(&purpose_id
, info
.achName
+ 1, 40);
370 hr
= BaseInputPin_Construct(&MediaStreamFilter_InputPin_Vtbl
, sizeof(BaseInputPin
), &info
,
371 &input_BaseInputFuncTable
, &This
->filter
.csFilter
, NULL
, &This
->pins
[This
->nb_streams
]);
375 pin
= (MediaStreamFilter_InputPin
*)This
->pins
[This
->nb_streams
];
376 pin
->pin
.pin
.pinInfo
.pFilter
= (LPVOID
)This
;
377 This
->streams
[This
->nb_streams
] = (IMediaStream
*)pAMMediaStream
;
380 IMediaStream_AddRef((IMediaStream
*)pAMMediaStream
);
385 static HRESULT WINAPI
MediaStreamFilterImpl_GetMediaStream(IMediaStreamFilter
* iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
387 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
391 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
393 for (i
= 0; i
< This
->nb_streams
; i
++)
395 IMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
396 if (IsEqualIID(&purpose_id
, idPurpose
))
398 *ppMediaStream
= This
->streams
[i
];
399 IMediaStream_AddRef(*ppMediaStream
);
404 return MS_E_NOSTREAM
;
407 static HRESULT WINAPI
MediaStreamFilterImpl_EnumMediaStreams(IMediaStreamFilter
* iface
, LONG Index
, IMediaStream
**ppMediaStream
)
409 FIXME("(%p)->(%d,%p): Stub!\n", iface
, Index
, ppMediaStream
);
414 static HRESULT WINAPI
MediaStreamFilterImpl_SupportSeeking(IMediaStreamFilter
* iface
, BOOL bRenderer
)
416 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
421 static HRESULT WINAPI
MediaStreamFilterImpl_ReferenceTimeToStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pTime
)
423 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
428 static HRESULT WINAPI
MediaStreamFilterImpl_GetCurrentStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pCurrentStreamTime
)
430 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
435 static HRESULT WINAPI
MediaStreamFilterImpl_WaitUntil(IMediaStreamFilter
* iface
, REFERENCE_TIME WaitStreamTime
)
437 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
442 static HRESULT WINAPI
MediaStreamFilterImpl_Flush(IMediaStreamFilter
* iface
, BOOL bCancelEOS
)
444 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
449 static HRESULT WINAPI
MediaStreamFilterImpl_EndOfStream(IMediaStreamFilter
* iface
)
451 FIXME("(%p)->(): Stub!\n", iface
);
456 static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl
=
458 MediaStreamFilterImpl_QueryInterface
,
459 MediaStreamFilterImpl_AddRef
,
460 MediaStreamFilterImpl_Release
,
461 MediaStreamFilterImpl_GetClassID
,
462 MediaStreamFilterImpl_Stop
,
463 MediaStreamFilterImpl_Pause
,
464 MediaStreamFilterImpl_Run
,
465 MediaStreamFilterImpl_GetState
,
466 MediaStreamFilterImpl_SetSyncSource
,
467 MediaStreamFilterImpl_GetSyncSource
,
468 MediaStreamFilterImpl_EnumPins
,
469 MediaStreamFilterImpl_FindPin
,
470 MediaStreamFilterImpl_QueryFilterInfo
,
471 MediaStreamFilterImpl_JoinFilterGraph
,
472 MediaStreamFilterImpl_QueryVendorInfo
,
473 MediaStreamFilterImpl_AddMediaStream
,
474 MediaStreamFilterImpl_GetMediaStream
,
475 MediaStreamFilterImpl_EnumMediaStreams
,
476 MediaStreamFilterImpl_SupportSeeking
,
477 MediaStreamFilterImpl_ReferenceTimeToStreamTime
,
478 MediaStreamFilterImpl_GetCurrentStreamTime
,
479 MediaStreamFilterImpl_WaitUntil
,
480 MediaStreamFilterImpl_Flush
,
481 MediaStreamFilterImpl_EndOfStream
484 static IPin
* WINAPI
MediaStreamFilterImpl_GetPin(BaseFilter
*iface
, int pos
)
486 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
488 if (pos
< This
->nb_streams
)
490 IPin_AddRef(This
->pins
[pos
]);
491 return This
->pins
[pos
];
497 static LONG WINAPI
MediaStreamFilterImpl_GetPinCount(BaseFilter
*iface
)
499 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
501 return This
->nb_streams
;
504 static const BaseFilterFuncTable BaseFuncTable
= {
505 MediaStreamFilterImpl_GetPin
,
506 MediaStreamFilterImpl_GetPinCount
509 HRESULT
MediaStreamFilter_create(IUnknown
*pUnkOuter
, void **ppObj
)
511 IMediaStreamFilterImpl
* object
;
513 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
516 return CLASS_E_NOAGGREGATION
;
518 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IMediaStreamFilterImpl
));
520 return E_OUTOFMEMORY
;
522 BaseFilter_Init(&object
->filter
, (IBaseFilterVtbl
*)&MediaStreamFilter_Vtbl
, &CLSID_MediaStreamFilter
, (DWORD_PTR
)(__FILE__
": MediaStreamFilterImpl.csFilter"), &BaseFuncTable
);