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
= BaseFilterImpl_Release(&This
->filter
.IBaseFilter_iface
);
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 HeapFree(GetProcessHeap(), 0, This
);
259 /*** IPersist methods ***/
261 static HRESULT WINAPI
MediaStreamFilterImpl_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
263 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
264 return BaseFilterImpl_GetClassID(&This
->filter
.IBaseFilter_iface
, clsid
);
267 /*** IBaseFilter methods ***/
269 static HRESULT WINAPI
MediaStreamFilterImpl_Stop(IMediaStreamFilter
*iface
)
271 FIXME("(%p)->(): Stub!\n", iface
);
276 static HRESULT WINAPI
MediaStreamFilterImpl_Pause(IMediaStreamFilter
*iface
)
278 FIXME("(%p)->(): Stub!\n", iface
);
283 static HRESULT WINAPI
MediaStreamFilterImpl_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
285 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
290 static HRESULT WINAPI
MediaStreamFilterImpl_GetState(IMediaStreamFilter
*iface
, DWORD ms_timeout
, FILTER_STATE
*state
)
292 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
293 return BaseFilterImpl_GetState(&This
->filter
.IBaseFilter_iface
, ms_timeout
, state
);
296 static HRESULT WINAPI
MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
298 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
299 return BaseFilterImpl_SetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
302 static HRESULT WINAPI
MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
304 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
305 return BaseFilterImpl_GetSyncSource(&This
->filter
.IBaseFilter_iface
, clock
);
308 static HRESULT WINAPI
MediaStreamFilterImpl_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
310 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
311 return BaseFilterImpl_EnumPins(&This
->filter
.IBaseFilter_iface
, enum_pins
);
314 static HRESULT WINAPI
MediaStreamFilterImpl_FindPin(IMediaStreamFilter
*iface
, LPCWSTR id
, IPin
**pin
)
316 FIXME("(%p)->(%s,%p): Stub!\n", iface
, debugstr_w(id
), pin
);
321 static HRESULT WINAPI
MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
323 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
324 return BaseFilterImpl_QueryFilterInfo(&This
->filter
.IBaseFilter_iface
, info
);
327 static HRESULT WINAPI
MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter
*iface
, IFilterGraph
*graph
, LPCWSTR name
)
329 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
330 return BaseFilterImpl_JoinFilterGraph(&This
->filter
.IBaseFilter_iface
, graph
, name
);
333 static HRESULT WINAPI
MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
335 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
336 return BaseFilterImpl_QueryVendorInfo(&This
->filter
.IBaseFilter_iface
, vendor_info
);
339 /*** IMediaStreamFilter methods ***/
341 static HRESULT WINAPI
MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter
* iface
, IAMMediaStream
*pAMMediaStream
)
343 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
344 IMediaStream
** streams
;
346 MediaStreamFilter_InputPin
* pin
;
351 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
353 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IMediaStream
*));
355 return E_OUTOFMEMORY
;
356 This
->streams
= streams
;
357 pins
= CoTaskMemRealloc(This
->pins
, (This
->nb_streams
+ 1) * sizeof(IPin
*));
359 return E_OUTOFMEMORY
;
361 info
.pFilter
= (IBaseFilter
*)&This
->filter
;
362 info
.dir
= PINDIR_INPUT
;
363 hr
= IAMMediaStream_GetInformation(pAMMediaStream
, &purpose_id
, NULL
);
366 /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */
367 info
.achName
[0] = 'I';
368 StringFromGUID2(&purpose_id
, info
.achName
+ 1, 40);
369 hr
= BaseInputPin_Construct(&MediaStreamFilter_InputPin_Vtbl
, sizeof(BaseInputPin
), &info
,
370 &input_BaseInputFuncTable
, &This
->filter
.csFilter
, NULL
, &This
->pins
[This
->nb_streams
]);
374 pin
= (MediaStreamFilter_InputPin
*)This
->pins
[This
->nb_streams
];
375 pin
->pin
.pin
.pinInfo
.pFilter
= (LPVOID
)This
;
376 This
->streams
[This
->nb_streams
] = (IMediaStream
*)pAMMediaStream
;
379 IMediaStream_AddRef((IMediaStream
*)pAMMediaStream
);
384 static HRESULT WINAPI
MediaStreamFilterImpl_GetMediaStream(IMediaStreamFilter
* iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
386 IMediaStreamFilterImpl
*This
= impl_from_IMediaStreamFilter(iface
);
390 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
392 for (i
= 0; i
< This
->nb_streams
; i
++)
394 IMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
395 if (IsEqualIID(&purpose_id
, idPurpose
))
397 *ppMediaStream
= This
->streams
[i
];
398 IMediaStream_AddRef(*ppMediaStream
);
403 return MS_E_NOSTREAM
;
406 static HRESULT WINAPI
MediaStreamFilterImpl_EnumMediaStreams(IMediaStreamFilter
* iface
, LONG Index
, IMediaStream
**ppMediaStream
)
408 FIXME("(%p)->(%d,%p): Stub!\n", iface
, Index
, ppMediaStream
);
413 static HRESULT WINAPI
MediaStreamFilterImpl_SupportSeeking(IMediaStreamFilter
* iface
, BOOL bRenderer
)
415 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
420 static HRESULT WINAPI
MediaStreamFilterImpl_ReferenceTimeToStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pTime
)
422 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
427 static HRESULT WINAPI
MediaStreamFilterImpl_GetCurrentStreamTime(IMediaStreamFilter
* iface
, REFERENCE_TIME
*pCurrentStreamTime
)
429 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
434 static HRESULT WINAPI
MediaStreamFilterImpl_WaitUntil(IMediaStreamFilter
* iface
, REFERENCE_TIME WaitStreamTime
)
436 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
441 static HRESULT WINAPI
MediaStreamFilterImpl_Flush(IMediaStreamFilter
* iface
, BOOL bCancelEOS
)
443 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
448 static HRESULT WINAPI
MediaStreamFilterImpl_EndOfStream(IMediaStreamFilter
* iface
)
450 FIXME("(%p)->(): Stub!\n", iface
);
455 static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl
=
457 MediaStreamFilterImpl_QueryInterface
,
458 MediaStreamFilterImpl_AddRef
,
459 MediaStreamFilterImpl_Release
,
460 MediaStreamFilterImpl_GetClassID
,
461 MediaStreamFilterImpl_Stop
,
462 MediaStreamFilterImpl_Pause
,
463 MediaStreamFilterImpl_Run
,
464 MediaStreamFilterImpl_GetState
,
465 MediaStreamFilterImpl_SetSyncSource
,
466 MediaStreamFilterImpl_GetSyncSource
,
467 MediaStreamFilterImpl_EnumPins
,
468 MediaStreamFilterImpl_FindPin
,
469 MediaStreamFilterImpl_QueryFilterInfo
,
470 MediaStreamFilterImpl_JoinFilterGraph
,
471 MediaStreamFilterImpl_QueryVendorInfo
,
472 MediaStreamFilterImpl_AddMediaStream
,
473 MediaStreamFilterImpl_GetMediaStream
,
474 MediaStreamFilterImpl_EnumMediaStreams
,
475 MediaStreamFilterImpl_SupportSeeking
,
476 MediaStreamFilterImpl_ReferenceTimeToStreamTime
,
477 MediaStreamFilterImpl_GetCurrentStreamTime
,
478 MediaStreamFilterImpl_WaitUntil
,
479 MediaStreamFilterImpl_Flush
,
480 MediaStreamFilterImpl_EndOfStream
483 static IPin
* WINAPI
MediaStreamFilterImpl_GetPin(BaseFilter
*iface
, int pos
)
485 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
487 if (pos
< This
->nb_streams
)
489 IPin_AddRef(This
->pins
[pos
]);
490 return This
->pins
[pos
];
496 static LONG WINAPI
MediaStreamFilterImpl_GetPinCount(BaseFilter
*iface
)
498 IMediaStreamFilterImpl
* This
= (IMediaStreamFilterImpl
*)iface
;
500 return This
->nb_streams
;
503 static const BaseFilterFuncTable BaseFuncTable
= {
504 MediaStreamFilterImpl_GetPin
,
505 MediaStreamFilterImpl_GetPinCount
508 HRESULT
MediaStreamFilter_create(IUnknown
*pUnkOuter
, void **ppObj
)
510 IMediaStreamFilterImpl
* object
;
512 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
515 return CLASS_E_NOAGGREGATION
;
517 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IMediaStreamFilterImpl
));
519 return E_OUTOFMEMORY
;
521 BaseFilter_Init(&object
->filter
, (IBaseFilterVtbl
*)&MediaStreamFilter_Vtbl
, &CLSID_MediaStreamFilter
, (DWORD_PTR
)(__FILE__
": MediaStreamFilterImpl.csFilter"), &BaseFuncTable
);