Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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#include <private/qcomptr_p.h>
27#include "evrhelpers_p.h"
28
29#include <d3d9.h>
30#include <dxva2api.h>
31#include <evr9.h>
32#include <evr.h>
33#include <mfidl.h>
34#include <mfapi.h>
35#include <mferror.h>
36
38
41
42template<class T>
43class AsyncCallback : public IMFAsyncCallback
44{
45 Q_DISABLE_COPY(AsyncCallback)
46public:
47 typedef HRESULT (T::*InvokeFn)(IMFAsyncResult *asyncResult);
48
49 AsyncCallback(T *parent, InvokeFn fn) : m_parent(parent), m_invokeFn(fn)
50 {
51 }
52
53 // IUnknown
54 STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override
55 {
56 if (!ppv)
57 return E_POINTER;
58
59 if (iid == __uuidof(IUnknown)) {
60 *ppv = static_cast<IUnknown*>(static_cast<IMFAsyncCallback*>(this));
61 } else if (iid == __uuidof(IMFAsyncCallback)) {
62 *ppv = static_cast<IMFAsyncCallback*>(this);
63 } else {
64 *ppv = NULL;
65 return E_NOINTERFACE;
66 }
67 AddRef();
68 return S_OK;
69 }
70
71 STDMETHODIMP_(ULONG) AddRef() override {
72 // Delegate to parent class.
73 return m_parent->AddRef();
74 }
75 STDMETHODIMP_(ULONG) Release() override {
76 // Delegate to parent class.
77 return m_parent->Release();
78 }
79
80 // IMFAsyncCallback methods
81 STDMETHODIMP GetParameters(DWORD*, DWORD*) override
82 {
83 // Implementation of this method is optional.
84 return E_NOTIMPL;
85 }
86
87 STDMETHODIMP Invoke(IMFAsyncResult* asyncResult) override
88 {
89 return (m_parent->*m_invokeFn)(asyncResult);
90 }
91
94};
95
97{
98 Q_DISABLE_COPY(Scheduler)
99public:
101 {
102 Terminate = WM_USER,
103 Schedule = WM_USER + 1,
104 Flush = WM_USER + 2
105 };
106
107 Scheduler(EVRCustomPresenter *presenter);
108 ~Scheduler();
109
110 void setFrameRate(const MFRatio &fps);
111 void setClockRate(float rate) { m_playbackRate = rate; }
112
113 HRESULT startScheduler(ComPtr<IMFClock> clock);
115
116 HRESULT scheduleSample(const ComPtr<IMFSample> &sample, bool presentNow);
117 HRESULT processSamplesInQueue(LONG *nextSleep);
118 HRESULT flush();
119
120 bool areSamplesScheduled();
121
122 // ThreadProc for the scheduler thread.
123 static DWORD WINAPI schedulerThreadProc(LPVOID parameter);
124
125private:
126 DWORD schedulerThreadProcPrivate();
127 bool isSampleReadyToPresent(IMFSample *sample, LONG *pNextSleep) const;
128
129 EVRCustomPresenter *m_presenter;
130
131 QQueue<ComPtr<IMFSample>> m_scheduledSamples; // Samples waiting to be presented.
132
133 ComPtr<IMFClock> m_clock; // Presentation clock. Can be NULL.
134
135 DWORD m_threadID;
136 ThreadHandle m_schedulerThread;
137 EventHandle m_threadReadyEvent;
138 EventHandle m_flushEvent;
139
140 float m_playbackRate;
141 MFTIME m_perFrame_1_4th; // 1/4th of the frame duration.
142
143 QMutex m_mutex;
144};
145
147{
148 Q_DISABLE_COPY(SamplePool)
149public:
150 SamplePool();
151 ~SamplePool();
152
153 HRESULT initialize(QList<ComPtr<IMFSample>> &&samples);
154 HRESULT clear();
155
156 ComPtr<IMFSample> takeSample();
157 void returnSample(const ComPtr<IMFSample> &sample);
158
159private:
160 QMutex m_mutex;
161 QList<ComPtr<IMFSample>> m_videoSampleQueue;
162 bool m_initialized;
163};
164
166 : public QObject
167 , public IMFVideoDeviceID
168 , public IMFVideoPresenter // Inherits IMFClockStateSink
169 , public IMFRateSupport
170 , public IMFGetService
171 , public IMFTopologyServiceLookupClient
172{
173 Q_DISABLE_COPY(EVRCustomPresenter)
174public:
175 // Defines the state of the presenter.
183
184 // Defines the presenter's state with respect to frame-stepping.
186 {
187 FrameStepNone, // Not frame stepping.
188 FrameStepWaitingStart, // Frame stepping, but the clock is not started.
189 FrameStepPending, // Clock is started. Waiting for samples.
190 FrameStepScheduled, // Submitted a sample for rendering.
191 FrameStepComplete // Sample was rendered.
192 };
193
200
202 ~EVRCustomPresenter() override;
203
204 bool isValid() const;
205
206 // IUnknown methods
207 STDMETHODIMP QueryInterface(REFIID riid, void ** ppv) override;
208 STDMETHODIMP_(ULONG) AddRef() override;
209 STDMETHODIMP_(ULONG) Release() override;
210
211 // IMFGetService methods
212 STDMETHODIMP GetService(REFGUID guidService, REFIID riid, LPVOID *ppvObject) override;
213
214 // IMFVideoPresenter methods
215 STDMETHODIMP ProcessMessage(MFVP_MESSAGE_TYPE message, ULONG_PTR param) override;
216 STDMETHODIMP GetCurrentMediaType(IMFVideoMediaType** mediaType) override;
217
218 // IMFClockStateSink methods
219 STDMETHODIMP OnClockStart(MFTIME systemTime, LONGLONG clockStartOffset) override;
220 STDMETHODIMP OnClockStop(MFTIME systemTime) override;
221 STDMETHODIMP OnClockPause(MFTIME systemTime) override;
222 STDMETHODIMP OnClockRestart(MFTIME systemTime) override;
223 STDMETHODIMP OnClockSetRate(MFTIME systemTime, float rate) override;
224
225 // IMFRateSupport methods
226 STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION direction, BOOL thin, float *rate) override;
227 STDMETHODIMP GetFastestRate(MFRATE_DIRECTION direction, BOOL thin, float *rate) override;
228 STDMETHODIMP IsRateSupported(BOOL thin, float rate, float *nearestSupportedRate) override;
229
230 // IMFVideoDeviceID methods
231 STDMETHODIMP GetDeviceID(IID* deviceID) override;
232
233 // IMFTopologyServiceLookupClient methods
234 STDMETHODIMP InitServicePointers(IMFTopologyServiceLookup *lookup) override;
235 STDMETHODIMP ReleaseServicePointers() override;
236
238 void setSink(QVideoSink *sink);
239 void setCropRect(QRect cropRect);
240
241 void startSurface();
242 void stopSurface();
243 void presentSample(const ComPtr<IMFSample> &sample);
244
245 bool event(QEvent *) override;
246
247public Q_SLOTS:
249
250private:
251 HRESULT checkShutdown() const
252 {
253 if (m_renderState == RenderShutdown)
254 return MF_E_SHUTDOWN;
255 else
256 return S_OK;
257 }
258
259 // The "active" state is started or paused.
260 inline bool isActive() const
261 {
262 return ((m_renderState == RenderStarted) || (m_renderState == RenderPaused));
263 }
264
265 // Scrubbing occurs when the frame rate is 0.
266 inline bool isScrubbing() const { return m_playbackRate == 0.0f; }
267
268 // Send an event to the EVR through its IMediaEventSink interface.
269 void notifyEvent(long eventCode, LONG_PTR param1, LONG_PTR param2)
270 {
271 if (m_mediaEventSink)
272 m_mediaEventSink->Notify(eventCode, param1, param2);
273 }
274
275 float getMaxRate(bool thin);
276
277 // Mixer operations
278 HRESULT configureMixer(IMFTransform *mixer);
279
280 // Formats
281 HRESULT createOptimalVideoType(IMFMediaType* proposed, IMFMediaType **optimal);
282 HRESULT setMediaType(IMFMediaType *mediaType);
283 HRESULT isMediaTypeSupported(IMFMediaType *mediaType);
284
285 // Message handlers
286 HRESULT flush();
287 HRESULT renegotiateMediaType();
288 HRESULT processInputNotify();
289 HRESULT beginStreaming();
290 HRESULT endStreaming();
291 HRESULT checkEndOfStream();
292
293 // Managing samples
294 void processOutputLoop();
295 HRESULT processOutput();
296 HRESULT deliverSample(const ComPtr<IMFSample> &sample);
297 HRESULT trackSample(const ComPtr<IMFSample> &sample);
298 void releaseResources();
299
300 // Frame-stepping
301 HRESULT prepareFrameStep(DWORD steps);
302 HRESULT startFrameStep();
303 HRESULT deliverFrameStepSample(const ComPtr<IMFSample> &sample);
304 HRESULT completeFrameStep(const ComPtr<IMFSample> &sample);
305 HRESULT cancelFrameStep();
306
307 // Callback when a video sample is released.
308 HRESULT onSampleFree(IMFAsyncResult *result);
309 AsyncCallback<EVRCustomPresenter> m_sampleFreeCB;
310
311 // Holds information related to frame-stepping.
312 struct FrameStep
313 {
315 QList<ComPtr<IMFSample>> samples;
316 DWORD steps = 0;
317 DWORD_PTR sampleNoRef = 0;
318 };
319
320 long m_refCount;
321
322 RenderState m_renderState;
323 FrameStep m_frameStep;
324
325 QRecursiveMutex m_mutex;
326
327 // Samples and scheduling
328 Scheduler m_scheduler; // Manages scheduling of samples.
329 SamplePool m_samplePool; // Pool of allocated samples.
330 DWORD m_tokenCounter; // Counter. Incremented whenever we create new samples.
331
332 // Rendering state
333 bool m_sampleNotify; // Did the mixer signal it has an input sample?
334 bool m_prerolled; // Have we presented at least one sample?
335 bool m_endStreaming; // Did we reach the end of the stream (EOS)?
336
337 MFVideoNormalizedRect m_sourceRect;
338 float m_playbackRate;
339
340 D3DPresentEngine *m_presentEngine; // Rendering engine. (Never null if the constructor succeeds.)
341
342 ComPtr<IMFClock> m_clock; // The EVR's clock.
343 ComPtr<IMFTransform> m_mixer; // The EVR's mixer.
344 ComPtr<IMediaEventSink> m_mediaEventSink; // The EVR's event-sink interface.
345 ComPtr<IMFMediaType> m_mediaType; // Output media type
346
347 QPointer<QVideoSink> m_videoSink;
348 bool m_canRenderToSurface;
349 qint64 m_positionOffset; // Seek position in microseconds.
350 QRect m_cropRect; // Video crop rectangle
351};
352
353bool qt_evr_setCustomPresenter(IUnknown *evr, EVRCustomPresenter *presenter);
354
356
357#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
void presentSample(const ComPtr< IMFSample > &sample)
STDMETHODIMP OnClockStart(MFTIME systemTime, LONGLONG clockStartOffset) override
STDMETHODIMP OnClockPause(MFTIME systemTime) override
STDMETHODIMP ProcessMessage(MFVP_MESSAGE_TYPE message, ULONG_PTR param) override
EVRCustomPresenter(QVideoSink *sink=0)
\inmodule QtCore
Definition qcoreevent.h:45
Definition qlist.h:75
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qmutex.h:309
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
ComPtr< IMFSample > takeSample()
void returnSample(const ComPtr< IMFSample > &sample)
HRESULT stopScheduler()
Scheduler(EVRCustomPresenter *presenter)
HRESULT startScheduler(ComPtr< IMFClock > clock)
void setFrameRate(const MFRatio &fps)
void setClockRate(float rate)
HRESULT processSamplesInQueue(LONG *nextSleep)
HRESULT scheduleSample(const ComPtr< IMFSample > &sample, bool presentNow)
static DWORD WINAPI schedulerThreadProc(LPVOID parameter)
direction
bool qt_evr_setCustomPresenter(IUnknown *evr, EVRCustomPresenter *presenter)
Combined button and popup list for selecting options.
static bool initialize()
Definition qctf.cpp:94
#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:60
IUIViewSettingsInterop __RPC__in REFIID riid
IUIViewSettingsInterop __RPC__in REFIID __RPC__deref_out_opt void ** ppv
long HRESULT