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
22 #include "amstream_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(amstream
);
29 IEnumPins IEnumPins_iface
;
33 unsigned int count
, index
;
36 static const IEnumPinsVtbl enum_pins_vtbl
;
38 static struct enum_pins
*impl_from_IEnumPins(IEnumPins
*iface
)
40 return CONTAINING_RECORD(iface
, struct enum_pins
, IEnumPins_iface
);
43 static HRESULT WINAPI
enum_pins_QueryInterface(IEnumPins
*iface
, REFIID iid
, void **out
)
45 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
47 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumPins
))
49 IEnumPins_AddRef(iface
);
54 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
59 static ULONG WINAPI
enum_pins_AddRef(IEnumPins
*iface
)
61 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
62 ULONG refcount
= InterlockedIncrement(&enum_pins
->refcount
);
63 TRACE("%p increasing refcount to %u.\n", enum_pins
, refcount
);
67 static ULONG WINAPI
enum_pins_Release(IEnumPins
*iface
)
69 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
70 ULONG refcount
= InterlockedDecrement(&enum_pins
->refcount
);
73 TRACE("%p decreasing refcount to %u.\n", enum_pins
, refcount
);
76 for (i
= 0; i
< enum_pins
->count
; ++i
)
77 IPin_Release(enum_pins
->pins
[i
]);
78 heap_free(enum_pins
->pins
);
84 static HRESULT WINAPI
enum_pins_Next(IEnumPins
*iface
, ULONG count
, IPin
**pins
, ULONG
*ret_count
)
86 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
89 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface
, count
, pins
, ret_count
);
91 if (!pins
|| (count
> 1 && !ret_count
))
94 for (i
= 0; i
< count
&& enum_pins
->index
< enum_pins
->count
; ++i
)
96 IPin_AddRef(pins
[i
] = enum_pins
->pins
[i
]);
100 if (ret_count
) *ret_count
= i
;
101 return i
== count
? S_OK
: S_FALSE
;
104 static HRESULT WINAPI
enum_pins_Skip(IEnumPins
*iface
, ULONG count
)
106 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
108 TRACE("iface %p, count %u.\n", iface
, count
);
110 enum_pins
->index
+= count
;
112 return enum_pins
->index
>= enum_pins
->count
? S_FALSE
: S_OK
;
115 static HRESULT WINAPI
enum_pins_Reset(IEnumPins
*iface
)
117 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
119 TRACE("iface %p.\n", iface
);
121 enum_pins
->index
= 0;
125 static HRESULT WINAPI
enum_pins_Clone(IEnumPins
*iface
, IEnumPins
**out
)
127 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
128 struct enum_pins
*object
;
131 TRACE("iface %p, out %p.\n", iface
, out
);
133 if (!(object
= heap_alloc(sizeof(*object
))))
134 return E_OUTOFMEMORY
;
136 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
137 object
->refcount
= 1;
138 object
->count
= enum_pins
->count
;
139 object
->index
= enum_pins
->index
;
140 if (!(object
->pins
= heap_alloc(enum_pins
->count
* sizeof(*object
->pins
))))
143 return E_OUTOFMEMORY
;
145 for (i
= 0; i
< enum_pins
->count
; ++i
)
146 IPin_AddRef(object
->pins
[i
] = enum_pins
->pins
[i
]);
148 *out
= &object
->IEnumPins_iface
;
152 static const IEnumPinsVtbl enum_pins_vtbl
=
154 enum_pins_QueryInterface
,
165 IMediaStreamFilter IMediaStreamFilter_iface
;
169 IReferenceClock
*clock
;
173 IAMMediaStream
**streams
;
176 static inline struct filter
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
178 return CONTAINING_RECORD(iface
, struct filter
, IMediaStreamFilter_iface
);
181 static HRESULT WINAPI
filter_QueryInterface(IMediaStreamFilter
*iface
, REFIID riid
, void **ret_iface
)
183 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
187 if (IsEqualIID(riid
, &IID_IUnknown
) ||
188 IsEqualIID(riid
, &IID_IPersist
) ||
189 IsEqualIID(riid
, &IID_IMediaFilter
) ||
190 IsEqualIID(riid
, &IID_IBaseFilter
) ||
191 IsEqualIID(riid
, &IID_IMediaStreamFilter
))
196 IMediaStreamFilter_AddRef(*ret_iface
);
200 return E_NOINTERFACE
;
203 static ULONG WINAPI
filter_AddRef(IMediaStreamFilter
*iface
)
205 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
206 ULONG refcount
= InterlockedIncrement(&filter
->refcount
);
208 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
213 static ULONG WINAPI
filter_Release(IMediaStreamFilter
*iface
)
215 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
216 ULONG refcount
= InterlockedDecrement(&filter
->refcount
);
219 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
223 for (i
= 0; i
< filter
->nb_streams
; ++i
)
225 IAMMediaStream_JoinFilter(filter
->streams
[i
], NULL
);
226 IAMMediaStream_Release(filter
->streams
[i
]);
228 heap_free(filter
->streams
);
230 IReferenceClock_Release(filter
->clock
);
231 DeleteCriticalSection(&filter
->cs
);
238 static HRESULT WINAPI
filter_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
240 *clsid
= CLSID_MediaStreamFilter
;
244 static HRESULT WINAPI
filter_Stop(IMediaStreamFilter
*iface
)
246 FIXME("(%p)->(): Stub!\n", iface
);
251 static HRESULT WINAPI
filter_Pause(IMediaStreamFilter
*iface
)
253 FIXME("(%p)->(): Stub!\n", iface
);
258 static HRESULT WINAPI
filter_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
260 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
265 static HRESULT WINAPI
filter_GetState(IMediaStreamFilter
*iface
, DWORD timeout
, FILTER_STATE
*state
)
267 FIXME("iface %p, timeout %u, state %p, stub!\n", iface
, timeout
, state
);
269 *state
= State_Stopped
;
273 static HRESULT WINAPI
filter_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
275 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
277 TRACE("iface %p, clock %p.\n", iface
, clock
);
279 EnterCriticalSection(&filter
->cs
);
282 IReferenceClock_AddRef(clock
);
284 IReferenceClock_Release(filter
->clock
);
285 filter
->clock
= clock
;
287 LeaveCriticalSection(&filter
->cs
);
292 static HRESULT WINAPI
filter_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
294 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
296 TRACE("iface %p, clock %p.\n", iface
, clock
);
298 EnterCriticalSection(&filter
->cs
);
301 IReferenceClock_AddRef(filter
->clock
);
302 *clock
= filter
->clock
;
304 LeaveCriticalSection(&filter
->cs
);
309 static HRESULT WINAPI
filter_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
311 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
312 struct enum_pins
*object
;
315 TRACE("iface %p, enum_pins %p.\n", iface
, enum_pins
);
317 EnterCriticalSection(&filter
->cs
);
322 if (!(object
= heap_alloc(sizeof(*object
))))
323 return E_OUTOFMEMORY
;
325 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
326 object
->refcount
= 1;
327 object
->count
= filter
->nb_streams
;
329 if (!(object
->pins
= heap_alloc(filter
->nb_streams
* sizeof(*object
->pins
))))
332 return E_OUTOFMEMORY
;
334 for (i
= 0; i
< filter
->nb_streams
; ++i
)
336 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&object
->pins
[i
])))
337 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
340 LeaveCriticalSection(&filter
->cs
);
342 *enum_pins
= &object
->IEnumPins_iface
;
346 static HRESULT WINAPI
filter_FindPin(IMediaStreamFilter
*iface
, const WCHAR
*id
, IPin
**out
)
348 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
353 TRACE("iface %p, id %s, out %p.\n", iface
, debugstr_w(id
), out
);
355 EnterCriticalSection(&filter
->cs
);
357 for (i
= 0; i
< filter
->nb_streams
; ++i
)
359 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&pin
)))
361 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
365 if (SUCCEEDED(IPin_QueryId(pin
, &ret_id
)))
367 if (!wcscmp(id
, ret_id
))
369 CoTaskMemFree(ret_id
);
371 LeaveCriticalSection(&filter
->cs
);
374 CoTaskMemFree(ret_id
);
379 LeaveCriticalSection(&filter
->cs
);
381 return VFW_E_NOT_FOUND
;
384 static HRESULT WINAPI
filter_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
386 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
388 TRACE("iface %p, info %p.\n", iface
, info
);
390 EnterCriticalSection(&filter
->cs
);
392 wcscpy(info
->achName
, filter
->name
);
394 IFilterGraph_AddRef(filter
->graph
);
395 info
->pGraph
= filter
->graph
;
397 LeaveCriticalSection(&filter
->cs
);
402 static HRESULT WINAPI
filter_JoinFilterGraph(IMediaStreamFilter
*iface
,
403 IFilterGraph
*graph
, const WCHAR
*name
)
405 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
407 TRACE("iface %p, graph %p, name.%s.\n", iface
, graph
, debugstr_w(name
));
409 EnterCriticalSection(&filter
->cs
);
412 wcsncpy(filter
->name
, name
, ARRAY_SIZE(filter
->name
));
415 filter
->graph
= graph
;
417 LeaveCriticalSection(&filter
->cs
);
422 static HRESULT WINAPI
filter_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
424 WARN("iface %p, vendor_info %p, stub!\n", iface
, vendor_info
);
428 /*** IMediaStreamFilter methods ***/
430 static HRESULT WINAPI
filter_AddMediaStream(IMediaStreamFilter
*iface
, IAMMediaStream
*pAMMediaStream
)
432 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
433 IAMMediaStream
** streams
;
436 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
438 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IAMMediaStream
*));
440 return E_OUTOFMEMORY
;
441 This
->streams
= streams
;
443 hr
= IAMMediaStream_JoinFilter(pAMMediaStream
, iface
);
447 This
->streams
[This
->nb_streams
] = pAMMediaStream
;
450 IAMMediaStream_AddRef(pAMMediaStream
);
455 static HRESULT WINAPI
filter_GetMediaStream(IMediaStreamFilter
*iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
457 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
461 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
463 for (i
= 0; i
< This
->nb_streams
; i
++)
465 IAMMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
466 if (IsEqualIID(&purpose_id
, idPurpose
))
468 *ppMediaStream
= (IMediaStream
*)This
->streams
[i
];
469 IMediaStream_AddRef(*ppMediaStream
);
474 return MS_E_NOSTREAM
;
477 static HRESULT WINAPI
filter_EnumMediaStreams(IMediaStreamFilter
*iface
, LONG Index
, IMediaStream
**ppMediaStream
)
479 FIXME("(%p)->(%d,%p): Stub!\n", iface
, Index
, ppMediaStream
);
484 static HRESULT WINAPI
filter_SupportSeeking(IMediaStreamFilter
*iface
, BOOL bRenderer
)
486 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
491 static HRESULT WINAPI
filter_ReferenceTimeToStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*pTime
)
493 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
498 static HRESULT WINAPI
filter_GetCurrentStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*pCurrentStreamTime
)
500 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
505 static HRESULT WINAPI
filter_WaitUntil(IMediaStreamFilter
*iface
, REFERENCE_TIME WaitStreamTime
)
507 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
512 static HRESULT WINAPI
filter_Flush(IMediaStreamFilter
*iface
, BOOL bCancelEOS
)
514 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
519 static HRESULT WINAPI
filter_EndOfStream(IMediaStreamFilter
*iface
)
521 FIXME("(%p)->(): Stub!\n", iface
);
526 static const IMediaStreamFilterVtbl filter_vtbl
=
528 filter_QueryInterface
,
536 filter_SetSyncSource
,
537 filter_GetSyncSource
,
540 filter_QueryFilterInfo
,
541 filter_JoinFilterGraph
,
542 filter_QueryVendorInfo
,
543 filter_AddMediaStream
,
544 filter_GetMediaStream
,
545 filter_EnumMediaStreams
,
546 filter_SupportSeeking
,
547 filter_ReferenceTimeToStreamTime
,
548 filter_GetCurrentStreamTime
,
554 HRESULT
filter_create(IUnknown
*outer
, void **out
)
556 struct filter
*object
;
558 TRACE("outer %p, out %p.\n", outer
, out
);
561 return CLASS_E_NOAGGREGATION
;
563 if (!(object
= heap_alloc_zero(sizeof(*object
))))
564 return E_OUTOFMEMORY
;
566 object
->IMediaStreamFilter_iface
.lpVtbl
= &filter_vtbl
;
567 object
->refcount
= 1;
568 InitializeCriticalSection(&object
->cs
);
569 object
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MediaStreamFilter.cs");
571 TRACE("Created media stream filter %p.\n", object
);
572 *out
= &object
->IMediaStreamFilter_iface
;