Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
evrcustompresenter_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef EVRCUSTOMPRESENTER_H
5#define EVRCUSTOMPRESENTER_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QObject>
19#include <qmutex.h>
20#include <qqueue.h>
21#include <qevent.h>
22#include <qrect.h>
23#include <qvideoframeformat.h>
24#include <qvideosink.h>
25#include <qpointer.h>
26
27#include <d3d9.h>
28#include <dxva2api.h>
29#include <evr9.h>
30#include <evr.h>
31#include <mfidl.h>
32#include <mfapi.h>
33#include <mferror.h>
34
36
39
40template<class T>
41class AsyncCallback : public IMFAsyncCallback
42{
43 Q_DISABLE_COPY(AsyncCallback)
44public:
45 typedef HRESULT (T::*InvokeFn)(IMFAsyncResult *asyncResult);
46
48 {
49 }
50
51 // IUnknown
52 STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override
53 {
54 if (!ppv)
55 return E_POINTER;
56
57 if (iid == __uuidof(IUnknown)) {
58 *ppv = static_cast<IUnknown*>(static_cast<IMFAsyncCallback*>(this));
59 } else if (iid == __uuidof(IMFAsyncCallback)) {
60 *ppv = static_cast<IMFAsyncCallback*>(this);
61 } else {
62 *ppv = NULL;
63 return E_NOINTERFACE;
64 }
65 AddRef();
66 return S_OK;
67 }
68
69 STDMETHODIMP_(ULONG) AddRef() override {
70 // Delegate to parent class.
71 return m_parent->AddRef();
72 }
73 STDMETHODIMP_(ULONG) Release() override {
74 // Delegate to parent class.
75 return m_parent->Release();
76 }
77
78 // IMFAsyncCallback methods
79 STDMETHODIMP GetParameters(DWORD*, DWORD*) override
80 {
81 // Implementation of this method is optional.
82 return E_NOTIMPL;
83 }
84
85 STDMETHODIMP Invoke(IMFAsyncResult* asyncResult) override
86 {
87 return (m_parent->*m_invokeFn)(asyncResult);
88 }
89
92};
93
95{
96 Q_DISABLE_COPY(Scheduler)
97public:
99 {
100 Terminate = WM_USER,
101 Schedule = WM_USER + 1,
102 Flush = WM_USER + 2
103 };
104
105 Scheduler(EVRCustomPresenter *presenter);
106 ~Scheduler();
107
108 void setFrameRate(const MFRatio &fps);
109 void setClockRate(float rate) { m_playbackRate = rate; }
110
111 const LONGLONG &lastSampleTime() const { return m_lastSampleTime; }
112 const LONGLONG &frameDuration() const { return m_perFrameInterval; }
113
114 HRESULT startScheduler(IMFClock *clock);
116
117 HRESULT scheduleSample(IMFSample *sample, bool presentNow);
118 HRESULT processSamplesInQueue(LONG *nextSleep);
119 HRESULT processSample(IMFSample *sample, LONG *nextSleep);
120 HRESULT flush();
121
122 bool areSamplesScheduled();
123
124 // ThreadProc for the scheduler thread.
125 static DWORD WINAPI schedulerThreadProc(LPVOID parameter);
126
127private:
128 DWORD schedulerThreadProcPrivate();
129
130 EVRCustomPresenter *m_presenter;
131
132 QQueue<IMFSample*> m_scheduledSamples; // Samples waiting to be presented.
133
134 IMFClock *m_clock; // Presentation clock. Can be NULL.
135
136 DWORD m_threadID;
137 HANDLE m_schedulerThread;
138 HANDLE m_threadReadyEvent;
139 HANDLE m_flushEvent;
140
141 float m_playbackRate;
142 MFTIME m_perFrameInterval; // Duration of each frame.
143 LONGLONG m_perFrame_1_4th; // 1/4th of the frame duration.
144 MFTIME m_lastSampleTime; // Most recent sample time.
145
146 QMutex m_mutex;
147};
148
150{
151 Q_DISABLE_COPY(SamplePool)
152public:
153 SamplePool();
154 ~SamplePool();
155
157 HRESULT clear();
158
159 HRESULT getSample(IMFSample **sample);
160 HRESULT returnSample(IMFSample *sample);
161
162private:
163 QMutex m_mutex;
164 QList<IMFSample*> m_videoSampleQueue;
165 bool m_initialized;
166};
167
169 : public QObject
170 , public IMFVideoDeviceID
171 , public IMFVideoPresenter // Inherits IMFClockStateSink
172 , public IMFRateSupport
173 , public IMFGetService
174 , public IMFTopologyServiceLookupClient
175{
176 Q_DISABLE_COPY(EVRCustomPresenter)
177public:
178 // Defines the state of the presenter.
180 {
184 RenderShutdown // Initial state.
185 };
186
187 // Defines the presenter's state with respect to frame-stepping.
189 {
190 FrameStepNone, // Not frame stepping.
191 FrameStepWaitingStart, // Frame stepping, but the clock is not started.
192 FrameStepPending, // Clock is started. Waiting for samples.
193 FrameStepScheduled, // Submitted a sample for rendering.
194 FrameStepComplete // Sample was rendered.
195 };
196
198 {
202 };
203
205 ~EVRCustomPresenter() override;
206
207 bool isValid() const;
208
209 // IUnknown methods
210 STDMETHODIMP QueryInterface(REFIID riid, void ** ppv) override;
211 STDMETHODIMP_(ULONG) AddRef() override;
212 STDMETHODIMP_(ULONG) Release() override;
213
214 // IMFGetService methods
215 STDMETHODIMP GetService(REFGUID guidService, REFIID riid, LPVOID *ppvObject) override;
216
217 // IMFVideoPresenter methods
218 STDMETHODIMP ProcessMessage(MFVP_MESSAGE_TYPE message, ULONG_PTR param) override;
219 STDMETHODIMP GetCurrentMediaType(IMFVideoMediaType** mediaType) override;
220
221 // IMFClockStateSink methods
222 STDMETHODIMP OnClockStart(MFTIME systemTime, LONGLONG clockStartOffset) override;
223 STDMETHODIMP OnClockStop(MFTIME systemTime) override;
224 STDMETHODIMP OnClockPause(MFTIME systemTime) override;
225 STDMETHODIMP OnClockRestart(MFTIME systemTime) override;
226 STDMETHODIMP OnClockSetRate(MFTIME systemTime, float rate) override;
227
228 // IMFRateSupport methods
229 STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION direction, BOOL thin, float *rate) override;
230 STDMETHODIMP GetFastestRate(MFRATE_DIRECTION direction, BOOL thin, float *rate) override;
231 STDMETHODIMP IsRateSupported(BOOL thin, float rate, float *nearestSupportedRate) override;
232
233 // IMFVideoDeviceID methods
234 STDMETHODIMP GetDeviceID(IID* deviceID) override;
235
236 // IMFTopologyServiceLookupClient methods
237 STDMETHODIMP InitServicePointers(IMFTopologyServiceLookup *lookup) override;
238 STDMETHODIMP ReleaseServicePointers() override;
239
241 void setSink(QVideoSink *sink);
242 void setCropRect(QRect cropRect);
243
244 void startSurface();
245 void stopSurface();
246 void presentSample(IMFSample *sample);
247
248 bool event(QEvent *) override;
249
250public Q_SLOTS:
252
253private:
254 HRESULT checkShutdown() const
255 {
256 if (m_renderState == RenderShutdown)
257 return MF_E_SHUTDOWN;
258 else
259 return S_OK;
260 }
261
262 // The "active" state is started or paused.
263 inline bool isActive() const
264 {
265 return ((m_renderState == RenderStarted) || (m_renderState == RenderPaused));
266 }
267
268 // Scrubbing occurs when the frame rate is 0.
269 inline bool isScrubbing() const { return m_playbackRate == 0.0f; }
270
271 // Send an event to the EVR through its IMediaEventSink interface.
272 void notifyEvent(long eventCode, LONG_PTR param1, LONG_PTR param2)
273 {
274 if (m_mediaEventSink)
275 m_mediaEventSink->Notify(eventCode, param1, param2);
276 }
277
278 float getMaxRate(bool thin);
279
280 // Mixer operations
281 HRESULT configureMixer(IMFTransform *mixer);
282
283 // Formats
284 HRESULT createOptimalVideoType(IMFMediaType* proposed, IMFMediaType **optimal);
285 HRESULT setMediaType(IMFMediaType *mediaType);
286 HRESULT isMediaTypeSupported(IMFMediaType *mediaType);
287
288 // Message handlers
289 HRESULT flush();
290 HRESULT renegotiateMediaType();
291 HRESULT processInputNotify();
292 HRESULT beginStreaming();
293 HRESULT endStreaming();
294 HRESULT checkEndOfStream();
295
296 // Managing samples
297 void processOutputLoop();
298 HRESULT processOutput();
299 HRESULT deliverSample(IMFSample *sample, bool repaint);
300 HRESULT trackSample(IMFSample *sample);
301 void releaseResources();
302
303 // Frame-stepping
304 HRESULT prepareFrameStep(DWORD steps);
305 HRESULT startFrameStep();
306 HRESULT deliverFrameStepSample(IMFSample *sample);
307 HRESULT completeFrameStep(IMFSample *sample);
308 HRESULT cancelFrameStep();
309
310 // Callback when a video sample is released.
311 HRESULT onSampleFree(IMFAsyncResult *result);
313
314 // Holds information related to frame-stepping.
315 struct FrameStep
316 {
319 DWORD steps = 0;
320 DWORD_PTR sampleNoRef = 0;
321 };
322
323 long m_refCount;
324
325 RenderState m_renderState;
326 FrameStep m_frameStep;
327
328 QRecursiveMutex m_mutex;
329
330 // Samples and scheduling
331 Scheduler m_scheduler; // Manages scheduling of samples.
332 SamplePool m_samplePool; // Pool of allocated samples.
333 DWORD m_tokenCounter; // Counter. Incremented whenever we create new samples.
334
335 // Rendering state
336 bool m_sampleNotify; // Did the mixer signal it has an input sample?
337 bool m_repaint; // Do we need to repaint the last sample?
338 bool m_prerolled; // Have we presented at least one sample?
339 bool m_endStreaming; // Did we reach the end of the stream (EOS)?
340
341 MFVideoNormalizedRect m_sourceRect;
342 float m_playbackRate;
343
344 D3DPresentEngine *m_presentEngine; // Rendering engine. (Never null if the constructor succeeds.)
345
346 IMFClock *m_clock; // The EVR's clock.
347 IMFTransform *m_mixer; // The EVR's mixer.
348 IMediaEventSink *m_mediaEventSink; // The EVR's event-sink interface.
349 IMFMediaType *m_mediaType; // Output media type
350
351 QPointer<QVideoSink> m_videoSink;
352 bool m_canRenderToSurface;
353 qint64 m_positionOffset; // Seek position in microseconds.
354 QRect m_cropRect; // Video crop rectangle
355};
356
357bool qt_evr_setCustomPresenter(IUnknown *evr, EVRCustomPresenter *presenter);
358
360
361#endif // EVRCUSTOMPRESENTER_H
STDMETHODIMP_(ULONG) AddRef() override
HRESULT(T::* InvokeFn)(IMFAsyncResult *asyncResult)
AsyncCallback(T *parent, InvokeFn fn)
STDMETHODIMP QueryInterface(REFIID iid, void **ppv) override
STDMETHODIMP Invoke(IMFAsyncResult *asyncResult) override
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP GetParameters(DWORD *, DWORD *) override
void positionChanged(qint64 position)
STDMETHODIMP GetDeviceID(IID *deviceID) override
STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION direction, BOOL thin, float *rate) override
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP OnClockStop(MFTIME systemTime) override
STDMETHODIMP ReleaseServicePointers() override
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override
STDMETHODIMP OnClockRestart(MFTIME systemTime) override
STDMETHODIMP InitServicePointers(IMFTopologyServiceLookup *lookup) override
STDMETHODIMP GetService(REFGUID guidService, REFIID riid, LPVOID *ppvObject) override
void setCropRect(QRect cropRect)
STDMETHODIMP_(ULONG) AddRef() override
STDMETHODIMP IsRateSupported(BOOL thin, float rate, float *nearestSupportedRate) override
STDMETHODIMP OnClockSetRate(MFTIME systemTime, float rate) override
STDMETHODIMP GetCurrentMediaType(IMFVideoMediaType **mediaType) override
void setSink(QVideoSink *sink)
STDMETHODIMP GetFastestRate(MFRATE_DIRECTION direction, BOOL thin, float *rate) override
STDMETHODIMP OnClockStart(MFTIME systemTime, LONGLONG clockStartOffset) override
STDMETHODIMP OnClockPause(MFTIME systemTime) override
STDMETHODIMP ProcessMessage(MFVP_MESSAGE_TYPE message, ULONG_PTR param) override
void presentSample(IMFSample *sample)
\inmodule QtCore
Definition qcoreevent.h:45
Definition qlist.h:74
\inmodule QtCore
Definition qmutex.h:285
\inmodule QtCore
Definition qobject.h:90
\inmodule QtCore
Definition qpointer.h:18
\inmodule QtCore
Definition qqueue.h:14
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qmutex.h:313
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
HRESULT getSample(IMFSample **sample)
HRESULT returnSample(IMFSample *sample)
HRESULT stopScheduler()
HRESULT scheduleSample(IMFSample *sample, bool presentNow)
const LONGLONG & frameDuration() const
void setFrameRate(const MFRatio &fps)
const LONGLONG & lastSampleTime() const
void setClockRate(float rate)
HRESULT processSamplesInQueue(LONG *nextSleep)
static DWORD WINAPI schedulerThreadProc(LPVOID parameter)
HRESULT processSample(IMFSample *sample, LONG *nextSleep)
HRESULT startScheduler(IMFClock *clock)
direction
else opt state
[0]
bool qt_evr_setCustomPresenter(IUnknown *evr, EVRCustomPresenter *presenter)
Combined button and popup list for selecting options.
static bool initialize()
Definition qctf.cpp:67
#define DWORD_PTR
GLsizei samples
GLuint GLsizei const GLchar * message
GLenum const GLint * param
struct _cl_event * event
GLuint GLenum * rate
GLsizei GLenum GLboolean sink
GLuint64EXT * result
[6]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_SLOTS
long long qint64
Definition qtypes.h:55
IUIViewSettingsInterop __RPC__in REFIID riid
IUIViewSettingsInterop __RPC__in REFIID __RPC__deref_out_opt void ** ppv
long HRESULT
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent