2 * Copyright 2022 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "mf_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
30 enum quality_manager_state
32 QUALITY_MANAGER_READY
= 0,
33 QUALITY_MANAGER_SHUT_DOWN
,
36 struct quality_manager
38 IMFQualityManager IMFQualityManager_iface
;
39 IMFClockStateSink IMFClockStateSink_iface
;
42 IMFTopology
*topology
;
43 IMFPresentationClock
*clock
;
48 static struct quality_manager
*impl_from_IMFQualityManager(IMFQualityManager
*iface
)
50 return CONTAINING_RECORD(iface
, struct quality_manager
, IMFQualityManager_iface
);
53 static struct quality_manager
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
55 return CONTAINING_RECORD(iface
, struct quality_manager
, IMFClockStateSink_iface
);
58 static HRESULT WINAPI
standard_quality_manager_QueryInterface(IMFQualityManager
*iface
, REFIID riid
, void **out
)
60 struct quality_manager
*manager
= impl_from_IMFQualityManager(iface
);
62 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
64 if (IsEqualIID(riid
, &IID_IMFQualityManager
) ||
65 IsEqualIID(riid
, &IID_IUnknown
))
69 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
71 *out
= &manager
->IMFClockStateSink_iface
;
75 WARN("Unsupported %s.\n", debugstr_guid(riid
));
80 IUnknown_AddRef((IUnknown
*)*out
);
84 static ULONG WINAPI
standard_quality_manager_AddRef(IMFQualityManager
*iface
)
86 struct quality_manager
*manager
= impl_from_IMFQualityManager(iface
);
87 ULONG refcount
= InterlockedIncrement(&manager
->refcount
);
89 TRACE("%p, refcount %lu.\n", iface
, refcount
);
94 static ULONG WINAPI
standard_quality_manager_Release(IMFQualityManager
*iface
)
96 struct quality_manager
*manager
= impl_from_IMFQualityManager(iface
);
97 ULONG refcount
= InterlockedDecrement(&manager
->refcount
);
99 TRACE("%p, refcount %lu.\n", iface
, refcount
);
104 IMFPresentationClock_Release(manager
->clock
);
105 if (manager
->topology
)
106 IMFTopology_Release(manager
->topology
);
107 DeleteCriticalSection(&manager
->cs
);
114 static void standard_quality_manager_set_topology(struct quality_manager
*manager
, IMFTopology
*topology
)
116 if (manager
->topology
)
117 IMFTopology_Release(manager
->topology
);
118 manager
->topology
= topology
;
119 if (manager
->topology
)
120 IMFTopology_AddRef(manager
->topology
);
123 static HRESULT WINAPI
standard_quality_manager_NotifyTopology(IMFQualityManager
*iface
, IMFTopology
*topology
)
125 struct quality_manager
*manager
= impl_from_IMFQualityManager(iface
);
128 TRACE("%p, %p.\n", iface
, topology
);
130 EnterCriticalSection(&manager
->cs
);
131 if (manager
->state
== QUALITY_MANAGER_SHUT_DOWN
)
135 standard_quality_manager_set_topology(manager
, topology
);
137 LeaveCriticalSection(&manager
->cs
);
142 static void standard_quality_manager_release_clock(struct quality_manager
*manager
)
146 IMFPresentationClock_RemoveClockStateSink(manager
->clock
, &manager
->IMFClockStateSink_iface
);
147 IMFPresentationClock_Release(manager
->clock
);
149 manager
->clock
= NULL
;
152 static HRESULT WINAPI
standard_quality_manager_NotifyPresentationClock(IMFQualityManager
*iface
,
153 IMFPresentationClock
*clock
)
155 struct quality_manager
*manager
= impl_from_IMFQualityManager(iface
);
158 TRACE("%p, %p.\n", iface
, clock
);
160 EnterCriticalSection(&manager
->cs
);
161 if (manager
->state
== QUALITY_MANAGER_SHUT_DOWN
)
167 standard_quality_manager_release_clock(manager
);
168 manager
->clock
= clock
;
169 IMFPresentationClock_AddRef(manager
->clock
);
170 if (FAILED(IMFPresentationClock_AddClockStateSink(manager
->clock
, &manager
->IMFClockStateSink_iface
)))
171 WARN("Failed to set state sink.\n");
173 LeaveCriticalSection(&manager
->cs
);
178 static HRESULT WINAPI
standard_quality_manager_NotifyProcessInput(IMFQualityManager
*iface
, IMFTopologyNode
*node
,
179 LONG input_index
, IMFSample
*sample
)
181 TRACE("%p, %p, %ld, %p stub.\n", iface
, node
, input_index
, sample
);
186 static HRESULT WINAPI
standard_quality_manager_NotifyProcessOutput(IMFQualityManager
*iface
, IMFTopologyNode
*node
,
187 LONG output_index
, IMFSample
*sample
)
189 TRACE("%p, %p, %ld, %p stub.\n", iface
, node
, output_index
, sample
);
194 static HRESULT WINAPI
standard_quality_manager_NotifyQualityEvent(IMFQualityManager
*iface
, IUnknown
*object
,
195 IMFMediaEvent
*event
)
197 FIXME("%p, %p, %p stub.\n", iface
, object
, event
);
202 static HRESULT WINAPI
standard_quality_manager_Shutdown(IMFQualityManager
*iface
)
204 struct quality_manager
*manager
= impl_from_IMFQualityManager(iface
);
206 TRACE("%p.\n", iface
);
208 EnterCriticalSection(&manager
->cs
);
209 if (manager
->state
!= QUALITY_MANAGER_SHUT_DOWN
)
211 standard_quality_manager_release_clock(manager
);
212 standard_quality_manager_set_topology(manager
, NULL
);
213 manager
->state
= QUALITY_MANAGER_SHUT_DOWN
;
215 LeaveCriticalSection(&manager
->cs
);
220 static const IMFQualityManagerVtbl standard_quality_manager_vtbl
=
222 standard_quality_manager_QueryInterface
,
223 standard_quality_manager_AddRef
,
224 standard_quality_manager_Release
,
225 standard_quality_manager_NotifyTopology
,
226 standard_quality_manager_NotifyPresentationClock
,
227 standard_quality_manager_NotifyProcessInput
,
228 standard_quality_manager_NotifyProcessOutput
,
229 standard_quality_manager_NotifyQualityEvent
,
230 standard_quality_manager_Shutdown
,
233 static HRESULT WINAPI
standard_quality_manager_sink_QueryInterface(IMFClockStateSink
*iface
,
234 REFIID riid
, void **obj
)
236 struct quality_manager
*manager
= impl_from_IMFClockStateSink(iface
);
237 return IMFQualityManager_QueryInterface(&manager
->IMFQualityManager_iface
, riid
, obj
);
240 static ULONG WINAPI
standard_quality_manager_sink_AddRef(IMFClockStateSink
*iface
)
242 struct quality_manager
*manager
= impl_from_IMFClockStateSink(iface
);
243 return IMFQualityManager_AddRef(&manager
->IMFQualityManager_iface
);
246 static ULONG WINAPI
standard_quality_manager_sink_Release(IMFClockStateSink
*iface
)
248 struct quality_manager
*manager
= impl_from_IMFClockStateSink(iface
);
249 return IMFQualityManager_Release(&manager
->IMFQualityManager_iface
);
252 static HRESULT WINAPI
standard_quality_manager_sink_OnClockStart(IMFClockStateSink
*iface
,
253 MFTIME systime
, LONGLONG offset
)
258 static HRESULT WINAPI
standard_quality_manager_sink_OnClockStop(IMFClockStateSink
*iface
,
264 static HRESULT WINAPI
standard_quality_manager_sink_OnClockPause(IMFClockStateSink
*iface
,
270 static HRESULT WINAPI
standard_quality_manager_sink_OnClockRestart(IMFClockStateSink
*iface
,
276 static HRESULT WINAPI
standard_quality_manager_sink_OnClockSetRate(IMFClockStateSink
*iface
,
277 MFTIME systime
, float rate
)
282 static const IMFClockStateSinkVtbl standard_quality_manager_sink_vtbl
=
284 standard_quality_manager_sink_QueryInterface
,
285 standard_quality_manager_sink_AddRef
,
286 standard_quality_manager_sink_Release
,
287 standard_quality_manager_sink_OnClockStart
,
288 standard_quality_manager_sink_OnClockStop
,
289 standard_quality_manager_sink_OnClockPause
,
290 standard_quality_manager_sink_OnClockRestart
,
291 standard_quality_manager_sink_OnClockSetRate
,
294 HRESULT WINAPI
MFCreateStandardQualityManager(IMFQualityManager
**manager
)
296 struct quality_manager
*object
;
298 TRACE("%p.\n", manager
);
300 if (!(object
= calloc(1, sizeof(*object
))))
301 return E_OUTOFMEMORY
;
303 object
->IMFQualityManager_iface
.lpVtbl
= &standard_quality_manager_vtbl
;
304 object
->IMFClockStateSink_iface
.lpVtbl
= &standard_quality_manager_sink_vtbl
;
305 object
->refcount
= 1;
306 InitializeCriticalSection(&object
->cs
);
308 *manager
= &object
->IMFQualityManager_iface
;