tests: Don't initialize static variables to 0.
[wine.git] / dlls / amstream / filter.c
blob4b0951cb6aed140dedc2ca1949c88d58f06f90a5
1 /*
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 #define COBJMACROS
22 #include "amstream_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
27 struct enum_pins
29 IEnumPins IEnumPins_iface;
30 LONG refcount;
32 IPin **pins;
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);
50 *out = iface;
51 return S_OK;
54 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
55 *out = NULL;
56 return E_NOINTERFACE;
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);
64 return 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);
71 unsigned int i;
73 TRACE("%p decreasing refcount to %u.\n", enum_pins, refcount);
74 if (!refcount)
76 for (i = 0; i < enum_pins->count; ++i)
77 IPin_Release(enum_pins->pins[i]);
78 heap_free(enum_pins->pins);
79 heap_free(enum_pins);
81 return refcount;
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);
87 unsigned int i;
89 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface, count, pins, ret_count);
91 if (!pins || (count > 1 && !ret_count))
92 return E_POINTER;
94 for (i = 0; i < count && enum_pins->index < enum_pins->count; ++i)
96 IPin_AddRef(pins[i] = enum_pins->pins[i]);
97 enum_pins->index++;
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;
122 return S_OK;
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;
129 unsigned int i;
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))))
142 heap_free(object);
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;
149 return S_OK;
152 static const IEnumPinsVtbl enum_pins_vtbl =
154 enum_pins_QueryInterface,
155 enum_pins_AddRef,
156 enum_pins_Release,
157 enum_pins_Next,
158 enum_pins_Skip,
159 enum_pins_Reset,
160 enum_pins_Clone,
163 struct filter
165 IMediaStreamFilter IMediaStreamFilter_iface;
166 LONG refcount;
167 CRITICAL_SECTION cs;
169 IReferenceClock *clock;
170 WCHAR name[128];
171 IFilterGraph *graph;
172 ULONG nb_streams;
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);
185 *ret_iface = NULL;
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))
192 *ret_iface = iface;
194 if (*ret_iface)
196 IMediaStreamFilter_AddRef(*ret_iface);
197 return S_OK;
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);
210 return refcount;
213 static ULONG WINAPI filter_Release(IMediaStreamFilter *iface)
215 struct filter *filter = impl_from_IMediaStreamFilter(iface);
216 ULONG refcount = InterlockedDecrement(&filter->refcount);
217 unsigned int i;
219 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
221 if (!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);
229 if (filter->clock)
230 IReferenceClock_Release(filter->clock);
231 DeleteCriticalSection(&filter->cs);
232 heap_free(filter);
235 return refcount;
238 static HRESULT WINAPI filter_GetClassID(IMediaStreamFilter *iface, CLSID *clsid)
240 *clsid = CLSID_MediaStreamFilter;
241 return S_OK;
244 static HRESULT WINAPI filter_Stop(IMediaStreamFilter *iface)
246 FIXME("(%p)->(): Stub!\n", iface);
248 return E_NOTIMPL;
251 static HRESULT WINAPI filter_Pause(IMediaStreamFilter *iface)
253 FIXME("(%p)->(): Stub!\n", iface);
255 return E_NOTIMPL;
258 static HRESULT WINAPI filter_Run(IMediaStreamFilter *iface, REFERENCE_TIME start)
260 FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(start));
262 return E_NOTIMPL;
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;
270 return S_OK;
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);
281 if (clock)
282 IReferenceClock_AddRef(clock);
283 if (filter->clock)
284 IReferenceClock_Release(filter->clock);
285 filter->clock = clock;
287 LeaveCriticalSection(&filter->cs);
289 return S_OK;
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);
300 if (filter->clock)
301 IReferenceClock_AddRef(filter->clock);
302 *clock = filter->clock;
304 LeaveCriticalSection(&filter->cs);
306 return S_OK;
309 static HRESULT WINAPI filter_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins)
311 struct filter *filter = impl_from_IMediaStreamFilter(iface);
312 struct enum_pins *object;
313 unsigned int i;
315 TRACE("iface %p, enum_pins %p.\n", iface, enum_pins);
317 EnterCriticalSection(&filter->cs);
319 if (!enum_pins)
320 return E_POINTER;
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;
328 object->index = 0;
329 if (!(object->pins = heap_alloc(filter->nb_streams * sizeof(*object->pins))))
331 heap_free(object);
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;
343 return S_OK;
346 static HRESULT WINAPI filter_FindPin(IMediaStreamFilter *iface, const WCHAR *id, IPin **out)
348 struct filter *filter = impl_from_IMediaStreamFilter(iface);
349 unsigned int i;
350 WCHAR *ret_id;
351 IPin *pin;
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]);
362 continue;
365 if (SUCCEEDED(IPin_QueryId(pin, &ret_id)))
367 if (!wcscmp(id, ret_id))
369 CoTaskMemFree(ret_id);
370 *out = pin;
371 LeaveCriticalSection(&filter->cs);
372 return S_OK;
374 CoTaskMemFree(ret_id);
376 IPin_Release(pin);
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);
393 if (filter->graph)
394 IFilterGraph_AddRef(filter->graph);
395 info->pGraph = filter->graph;
397 LeaveCriticalSection(&filter->cs);
399 return S_OK;
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);
411 if (name)
412 wcsncpy(filter->name, name, ARRAY_SIZE(filter->name));
413 else
414 filter->name[0] = 0;
415 filter->graph = graph;
417 LeaveCriticalSection(&filter->cs);
419 return S_OK;
422 static HRESULT WINAPI filter_QueryVendorInfo(IMediaStreamFilter *iface, LPWSTR *vendor_info)
424 WARN("iface %p, vendor_info %p, stub!\n", iface, vendor_info);
425 return E_NOTIMPL;
428 /*** IMediaStreamFilter methods ***/
430 static HRESULT WINAPI filter_AddMediaStream(IMediaStreamFilter *iface, IAMMediaStream *pAMMediaStream)
432 struct filter *This = impl_from_IMediaStreamFilter(iface);
433 IAMMediaStream** streams;
434 HRESULT hr;
436 TRACE("(%p)->(%p)\n", iface, pAMMediaStream);
438 streams = CoTaskMemRealloc(This->streams, (This->nb_streams + 1) * sizeof(IAMMediaStream*));
439 if (!streams)
440 return E_OUTOFMEMORY;
441 This->streams = streams;
443 hr = IAMMediaStream_JoinFilter(pAMMediaStream, iface);
444 if (FAILED(hr))
445 return hr;
447 This->streams[This->nb_streams] = pAMMediaStream;
448 This->nb_streams++;
450 IAMMediaStream_AddRef(pAMMediaStream);
452 return S_OK;
455 static HRESULT WINAPI filter_GetMediaStream(IMediaStreamFilter *iface, REFMSPID idPurpose, IMediaStream **ppMediaStream)
457 struct filter *This = impl_from_IMediaStreamFilter(iface);
458 MSPID purpose_id;
459 unsigned int i;
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);
470 return S_OK;
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);
481 return E_NOTIMPL;
484 static HRESULT WINAPI filter_SupportSeeking(IMediaStreamFilter *iface, BOOL bRenderer)
486 FIXME("(%p)->(%d): Stub!\n", iface, bRenderer);
488 return E_NOTIMPL;
491 static HRESULT WINAPI filter_ReferenceTimeToStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *pTime)
493 FIXME("(%p)->(%p): Stub!\n", iface, pTime);
495 return E_NOTIMPL;
498 static HRESULT WINAPI filter_GetCurrentStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *pCurrentStreamTime)
500 FIXME("(%p)->(%p): Stub!\n", iface, pCurrentStreamTime);
502 return E_NOTIMPL;
505 static HRESULT WINAPI filter_WaitUntil(IMediaStreamFilter *iface, REFERENCE_TIME WaitStreamTime)
507 FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(WaitStreamTime));
509 return E_NOTIMPL;
512 static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL bCancelEOS)
514 FIXME("(%p)->(%d): Stub!\n", iface, bCancelEOS);
516 return E_NOTIMPL;
519 static HRESULT WINAPI filter_EndOfStream(IMediaStreamFilter *iface)
521 FIXME("(%p)->(): Stub!\n", iface);
523 return E_NOTIMPL;
526 static const IMediaStreamFilterVtbl filter_vtbl =
528 filter_QueryInterface,
529 filter_AddRef,
530 filter_Release,
531 filter_GetClassID,
532 filter_Stop,
533 filter_Pause,
534 filter_Run,
535 filter_GetState,
536 filter_SetSyncSource,
537 filter_GetSyncSource,
538 filter_EnumPins,
539 filter_FindPin,
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,
549 filter_WaitUntil,
550 filter_Flush,
551 filter_EndOfStream
554 HRESULT filter_create(IUnknown *outer, void **out)
556 struct filter *object;
558 TRACE("outer %p, out %p.\n", outer, out);
560 if (outer)
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;
573 return S_OK;