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
;
177 static inline struct filter
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
179 return CONTAINING_RECORD(iface
, struct filter
, IMediaStreamFilter_iface
);
182 static HRESULT WINAPI
filter_QueryInterface(IMediaStreamFilter
*iface
, REFIID riid
, void **ret_iface
)
184 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
188 if (IsEqualIID(riid
, &IID_IUnknown
) ||
189 IsEqualIID(riid
, &IID_IPersist
) ||
190 IsEqualIID(riid
, &IID_IMediaFilter
) ||
191 IsEqualIID(riid
, &IID_IBaseFilter
) ||
192 IsEqualIID(riid
, &IID_IMediaStreamFilter
))
197 IMediaStreamFilter_AddRef(*ret_iface
);
201 return E_NOINTERFACE
;
204 static ULONG WINAPI
filter_AddRef(IMediaStreamFilter
*iface
)
206 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
207 ULONG refcount
= InterlockedIncrement(&filter
->refcount
);
209 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
214 static ULONG WINAPI
filter_Release(IMediaStreamFilter
*iface
)
216 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
217 ULONG refcount
= InterlockedDecrement(&filter
->refcount
);
220 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
224 for (i
= 0; i
< filter
->nb_streams
; ++i
)
226 IAMMediaStream_JoinFilter(filter
->streams
[i
], NULL
);
227 IAMMediaStream_Release(filter
->streams
[i
]);
229 heap_free(filter
->streams
);
231 IReferenceClock_Release(filter
->clock
);
232 DeleteCriticalSection(&filter
->cs
);
239 static HRESULT WINAPI
filter_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
241 *clsid
= CLSID_MediaStreamFilter
;
245 static HRESULT WINAPI
filter_Stop(IMediaStreamFilter
*iface
)
247 FIXME("(%p)->(): Stub!\n", iface
);
252 static HRESULT WINAPI
filter_Pause(IMediaStreamFilter
*iface
)
254 FIXME("(%p)->(): Stub!\n", iface
);
259 static HRESULT WINAPI
filter_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
261 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(start
));
266 static HRESULT WINAPI
filter_GetState(IMediaStreamFilter
*iface
, DWORD timeout
, FILTER_STATE
*state
)
268 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
270 TRACE("iface %p, timeout %u, state %p.\n", iface
, timeout
, state
);
275 EnterCriticalSection(&filter
->cs
);
277 *state
= filter
->state
;
279 LeaveCriticalSection(&filter
->cs
);
284 static HRESULT WINAPI
filter_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
286 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
288 TRACE("iface %p, clock %p.\n", iface
, clock
);
290 EnterCriticalSection(&filter
->cs
);
293 IReferenceClock_AddRef(clock
);
295 IReferenceClock_Release(filter
->clock
);
296 filter
->clock
= clock
;
298 LeaveCriticalSection(&filter
->cs
);
303 static HRESULT WINAPI
filter_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
305 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
307 TRACE("iface %p, clock %p.\n", iface
, clock
);
309 EnterCriticalSection(&filter
->cs
);
312 IReferenceClock_AddRef(filter
->clock
);
313 *clock
= filter
->clock
;
315 LeaveCriticalSection(&filter
->cs
);
320 static HRESULT WINAPI
filter_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
322 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
323 struct enum_pins
*object
;
326 TRACE("iface %p, enum_pins %p.\n", iface
, enum_pins
);
328 EnterCriticalSection(&filter
->cs
);
333 if (!(object
= heap_alloc(sizeof(*object
))))
334 return E_OUTOFMEMORY
;
336 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
337 object
->refcount
= 1;
338 object
->count
= filter
->nb_streams
;
340 if (!(object
->pins
= heap_alloc(filter
->nb_streams
* sizeof(*object
->pins
))))
343 return E_OUTOFMEMORY
;
345 for (i
= 0; i
< filter
->nb_streams
; ++i
)
347 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&object
->pins
[i
])))
348 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
351 LeaveCriticalSection(&filter
->cs
);
353 *enum_pins
= &object
->IEnumPins_iface
;
357 static HRESULT WINAPI
filter_FindPin(IMediaStreamFilter
*iface
, const WCHAR
*id
, IPin
**out
)
359 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
364 TRACE("iface %p, id %s, out %p.\n", iface
, debugstr_w(id
), out
);
366 EnterCriticalSection(&filter
->cs
);
368 for (i
= 0; i
< filter
->nb_streams
; ++i
)
370 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&pin
)))
372 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
376 if (SUCCEEDED(IPin_QueryId(pin
, &ret_id
)))
378 if (!wcscmp(id
, ret_id
))
380 CoTaskMemFree(ret_id
);
382 LeaveCriticalSection(&filter
->cs
);
385 CoTaskMemFree(ret_id
);
390 LeaveCriticalSection(&filter
->cs
);
392 return VFW_E_NOT_FOUND
;
395 static HRESULT WINAPI
filter_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
397 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
399 TRACE("iface %p, info %p.\n", iface
, info
);
401 EnterCriticalSection(&filter
->cs
);
403 wcscpy(info
->achName
, filter
->name
);
405 IFilterGraph_AddRef(filter
->graph
);
406 info
->pGraph
= filter
->graph
;
408 LeaveCriticalSection(&filter
->cs
);
413 static HRESULT WINAPI
filter_JoinFilterGraph(IMediaStreamFilter
*iface
,
414 IFilterGraph
*graph
, const WCHAR
*name
)
416 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
418 TRACE("iface %p, graph %p, name.%s.\n", iface
, graph
, debugstr_w(name
));
420 EnterCriticalSection(&filter
->cs
);
423 wcsncpy(filter
->name
, name
, ARRAY_SIZE(filter
->name
));
426 filter
->graph
= graph
;
428 LeaveCriticalSection(&filter
->cs
);
433 static HRESULT WINAPI
filter_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
435 WARN("iface %p, vendor_info %p, stub!\n", iface
, vendor_info
);
439 /*** IMediaStreamFilter methods ***/
441 static HRESULT WINAPI
filter_AddMediaStream(IMediaStreamFilter
*iface
, IAMMediaStream
*pAMMediaStream
)
443 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
444 IAMMediaStream
** streams
;
447 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
449 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IAMMediaStream
*));
451 return E_OUTOFMEMORY
;
452 This
->streams
= streams
;
454 hr
= IAMMediaStream_JoinFilter(pAMMediaStream
, iface
);
458 This
->streams
[This
->nb_streams
] = pAMMediaStream
;
461 IAMMediaStream_AddRef(pAMMediaStream
);
466 static HRESULT WINAPI
filter_GetMediaStream(IMediaStreamFilter
*iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
468 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
472 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
474 for (i
= 0; i
< This
->nb_streams
; i
++)
476 IAMMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
477 if (IsEqualIID(&purpose_id
, idPurpose
))
479 *ppMediaStream
= (IMediaStream
*)This
->streams
[i
];
480 IMediaStream_AddRef(*ppMediaStream
);
485 return MS_E_NOSTREAM
;
488 static HRESULT WINAPI
filter_EnumMediaStreams(IMediaStreamFilter
*iface
, LONG index
, IMediaStream
**stream
)
490 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
492 TRACE("filter %p, index %d, stream %p.\n", filter
, index
, stream
);
494 if (index
>= filter
->nb_streams
)
500 IMediaStream_AddRef(*stream
= (IMediaStream
*)filter
->streams
[index
]);
504 static HRESULT WINAPI
filter_SupportSeeking(IMediaStreamFilter
*iface
, BOOL bRenderer
)
506 FIXME("(%p)->(%d): Stub!\n", iface
, bRenderer
);
511 static HRESULT WINAPI
filter_ReferenceTimeToStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*pTime
)
513 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
518 static HRESULT WINAPI
filter_GetCurrentStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*pCurrentStreamTime
)
520 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
525 static HRESULT WINAPI
filter_WaitUntil(IMediaStreamFilter
*iface
, REFERENCE_TIME WaitStreamTime
)
527 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
532 static HRESULT WINAPI
filter_Flush(IMediaStreamFilter
*iface
, BOOL bCancelEOS
)
534 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
539 static HRESULT WINAPI
filter_EndOfStream(IMediaStreamFilter
*iface
)
541 FIXME("(%p)->(): Stub!\n", iface
);
546 static const IMediaStreamFilterVtbl filter_vtbl
=
548 filter_QueryInterface
,
556 filter_SetSyncSource
,
557 filter_GetSyncSource
,
560 filter_QueryFilterInfo
,
561 filter_JoinFilterGraph
,
562 filter_QueryVendorInfo
,
563 filter_AddMediaStream
,
564 filter_GetMediaStream
,
565 filter_EnumMediaStreams
,
566 filter_SupportSeeking
,
567 filter_ReferenceTimeToStreamTime
,
568 filter_GetCurrentStreamTime
,
574 HRESULT
filter_create(IUnknown
*outer
, void **out
)
576 struct filter
*object
;
578 TRACE("outer %p, out %p.\n", outer
, out
);
581 return CLASS_E_NOAGGREGATION
;
583 if (!(object
= heap_alloc_zero(sizeof(*object
))))
584 return E_OUTOFMEMORY
;
586 object
->IMediaStreamFilter_iface
.lpVtbl
= &filter_vtbl
;
587 object
->refcount
= 1;
588 InitializeCriticalSection(&object
->cs
);
589 object
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MediaStreamFilter.cs");
591 TRACE("Created media stream filter %p.\n", object
);
592 *out
= &object
->IMediaStreamFilter_iface
;