Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
mftvideo.cpp
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#include "mftvideo_p.h"
5#include <private/qmemoryvideobuffer_p.h>
6#include <private/qwindowsmultimediautils_p.h>
7#include <mferror.h>
8#include <strmif.h>
9#include <uuids.h>
10#include <initguid.h>
11#include <d3d9.h>
12#include <qdebug.h>
13
14// This MFT sends all samples it processes to connected video probes.
15// Sample is sent to probes in ProcessInput.
16// In ProcessOutput this MFT simply returns the original sample.
17
18// The implementation is based on a boilerplate from the MF SDK example.
19
21 m_cRef(1),
22 m_inputType(0),
23 m_outputType(0),
24 m_sample(0),
25 m_videoSinkTypeHandler(0),
26 m_bytesPerLine(0)
27{
28}
29
31{
32 if (m_inputType)
33 m_inputType->Release();
34
35 if (m_outputType)
36 m_outputType->Release();
37
38 if (m_videoSinkTypeHandler)
39 m_videoSinkTypeHandler->Release();
40}
41
42//void MFTransform::addProbe(MFVideoProbeControl *probe)
43//{
44// QMutexLocker locker(&m_videoProbeMutex);
45
46// if (m_videoProbes.contains(probe))
47// return;
48
49// m_videoProbes.append(probe);
50//}
51
52//void MFTransform::removeProbe(MFVideoProbeControl *probe)
53//{
54// QMutexLocker locker(&m_videoProbeMutex);
55// m_videoProbes.removeOne(probe);
56//}
57
58void MFTransform::setVideoSink(IUnknown *videoSink)
59{
60 // This transform supports the same input types as the video sink.
61 // Store its type handler interface in order to report the correct supported types.
62
63 if (m_videoSinkTypeHandler) {
64 m_videoSinkTypeHandler->Release();
65 m_videoSinkTypeHandler = NULL;
66 }
67
68 if (videoSink)
69 videoSink->QueryInterface(IID_PPV_ARGS(&m_videoSinkTypeHandler));
70}
71
72STDMETHODIMP MFTransform::QueryInterface(REFIID riid, void** ppv)
73{
74 if (!ppv)
75 return E_POINTER;
76 if (riid == IID_IMFTransform) {
77 *ppv = static_cast<IMFTransform*>(this);
78 } else if (riid == IID_IUnknown) {
79 *ppv = static_cast<IUnknown*>(this);
80 } else {
81 *ppv = NULL;
82 return E_NOINTERFACE;
83 }
84 AddRef();
85 return S_OK;
86}
87
88STDMETHODIMP_(ULONG) MFTransform::AddRef()
89{
90 return InterlockedIncrement(&m_cRef);
91}
92
93STDMETHODIMP_(ULONG) MFTransform::Release()
94{
95 ULONG cRef = InterlockedDecrement(&m_cRef);
96 if (cRef == 0) {
97 delete this;
98 }
99 return cRef;
100}
101
102STDMETHODIMP MFTransform::GetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
103{
104 if (!pdwInputMinimum || !pdwInputMaximum || !pdwOutputMinimum || !pdwOutputMaximum)
105 return E_POINTER;
106 *pdwInputMinimum = 1;
107 *pdwInputMaximum = 1;
108 *pdwOutputMinimum = 1;
109 *pdwOutputMaximum = 1;
110 return S_OK;
111}
112
113STDMETHODIMP MFTransform::GetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
114{
115 if (!pcInputStreams || !pcOutputStreams)
116 return E_POINTER;
117
118 *pcInputStreams = 1;
119 *pcOutputStreams = 1;
120 return S_OK;
121}
122
123STDMETHODIMP MFTransform::GetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
124{
125 // streams are numbered consecutively
126 Q_UNUSED(dwInputIDArraySize);
127 Q_UNUSED(pdwInputIDs);
128 Q_UNUSED(dwOutputIDArraySize);
129 Q_UNUSED(pdwOutputIDs);
130 return E_NOTIMPL;
131}
132
133STDMETHODIMP MFTransform::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
134{
135 QMutexLocker locker(&m_mutex);
136
137 if (dwInputStreamID > 0)
138 return MF_E_INVALIDSTREAMNUMBER;
139
140 if (!pStreamInfo)
141 return E_POINTER;
142
143 pStreamInfo->cbSize = 0;
144 pStreamInfo->hnsMaxLatency = 0;
145 pStreamInfo->cbMaxLookahead = 0;
146 pStreamInfo->cbAlignment = 0;
147 pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES
148 | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
149 | MFT_INPUT_STREAM_PROCESSES_IN_PLACE;
150
151 return S_OK;
152}
153
154STDMETHODIMP MFTransform::GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
155{
156 QMutexLocker locker(&m_mutex);
157
158 if (dwOutputStreamID > 0)
159 return MF_E_INVALIDSTREAMNUMBER;
160
161 if (!pStreamInfo)
162 return E_POINTER;
163
164 pStreamInfo->cbSize = 0;
165 pStreamInfo->cbAlignment = 0;
166 pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES
167 | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
168 | MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
169 | MFT_OUTPUT_STREAM_DISCARDABLE;
170
171 return S_OK;
172}
173
174STDMETHODIMP MFTransform::GetAttributes(IMFAttributes **pAttributes)
175{
176 // This MFT does not support attributes.
177 Q_UNUSED(pAttributes);
178 return E_NOTIMPL;
179}
180
181STDMETHODIMP MFTransform::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **pAttributes)
182{
183 // This MFT does not support input stream attributes.
184 Q_UNUSED(dwInputStreamID);
185 Q_UNUSED(pAttributes);
186 return E_NOTIMPL;
187}
188
189STDMETHODIMP MFTransform::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **pAttributes)
190{
191 // This MFT does not support output stream attributes.
192 Q_UNUSED(dwOutputStreamID);
193 Q_UNUSED(pAttributes);
194 return E_NOTIMPL;
195}
196
197STDMETHODIMP MFTransform::DeleteInputStream(DWORD dwStreamID)
198{
199 // This MFT has a fixed number of input streams.
200 Q_UNUSED(dwStreamID);
201 return E_NOTIMPL;
202}
203
204STDMETHODIMP MFTransform::AddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
205{
206 // This MFT has a fixed number of input streams.
207 Q_UNUSED(cStreams);
208 Q_UNUSED(adwStreamIDs);
209 return E_NOTIMPL;
210}
211
212STDMETHODIMP MFTransform::GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
213{
214 // We support the same input types as the video sink
215 if (!m_videoSinkTypeHandler)
216 return E_NOTIMPL;
217
218 if (dwInputStreamID > 0)
219 return MF_E_INVALIDSTREAMNUMBER;
220
221 if (!ppType)
222 return E_POINTER;
223
224 return m_videoSinkTypeHandler->GetMediaTypeByIndex(dwTypeIndex, ppType);
225}
226
227STDMETHODIMP MFTransform::GetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
228{
229 // Since we don't modify the samples, the output type must be the same as the input type.
230 // Report our input type as the only available output type.
231
232 if (dwOutputStreamID > 0)
233 return MF_E_INVALIDSTREAMNUMBER;
234
235 if (!ppType)
236 return E_POINTER;
237
238 // Input type must be set first
239 if (!m_inputType)
240 return MF_E_TRANSFORM_TYPE_NOT_SET;
241
242 if (dwTypeIndex > 0)
243 return MF_E_NO_MORE_TYPES;
244
245 // Return a copy to make sure our type is not modified
246 if (FAILED(MFCreateMediaType(ppType)))
247 return E_OUTOFMEMORY;
248
249 return m_inputType->CopyAllItems(*ppType);
250}
251
252STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
253{
254 if (dwInputStreamID > 0)
255 return MF_E_INVALIDSTREAMNUMBER;
256
257 QMutexLocker locker(&m_mutex);
258
259 if (m_sample)
260 return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
261
262 if (!isMediaTypeSupported(pType))
263 return MF_E_INVALIDMEDIATYPE;
264
265 if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
266 return pType ? S_OK : E_POINTER;
267
268 if (m_inputType) {
269 m_inputType->Release();
270 // Input type has changed, discard output type (if it's set) so it's reset later on
271 DWORD flags = 0;
272 if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) {
273 m_outputType->Release();
274 m_outputType = 0;
275 }
276 }
277
278 m_inputType = pType;
279
280 if (m_inputType)
281 m_inputType->AddRef();
282
283 return S_OK;
284}
285
286STDMETHODIMP MFTransform::SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
287{
288 if (dwOutputStreamID > 0)
289 return MF_E_INVALIDSTREAMNUMBER;
290
291 if (dwFlags == MFT_SET_TYPE_TEST_ONLY && !pType)
292 return E_POINTER;
293
294 QMutexLocker locker(&m_mutex);
295
296 // Input type must be set first
297 if (!m_inputType)
298 return MF_E_TRANSFORM_TYPE_NOT_SET;
299
300 if (m_sample)
301 return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
302
303 DWORD flags = 0;
304 if (pType && m_inputType->IsEqual(pType, &flags) != S_OK)
305 return MF_E_INVALIDMEDIATYPE;
306
307 if (dwFlags == MFT_SET_TYPE_TEST_ONLY)
308 return pType ? S_OK : E_POINTER;
309
310 if (m_outputType)
311 m_outputType->Release();
312
313 m_outputType = pType;
314
315 if (m_outputType) {
316 m_outputType->AddRef();
317 m_format = videoFormatForMFMediaType(m_outputType, &m_bytesPerLine);
318 }
319
320 return S_OK;
321}
322
323STDMETHODIMP MFTransform::GetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
324{
325 if (dwInputStreamID > 0)
326 return MF_E_INVALIDSTREAMNUMBER;
327
328 if (ppType == NULL)
329 return E_POINTER;
330
331 QMutexLocker locker(&m_mutex);
332
333 if (!m_inputType)
334 return MF_E_TRANSFORM_TYPE_NOT_SET;
335
336 // Return a copy to make sure our type is not modified
337 if (FAILED(MFCreateMediaType(ppType)))
338 return E_OUTOFMEMORY;
339
340 return m_inputType->CopyAllItems(*ppType);
341}
342
343STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
344{
345 if (dwOutputStreamID > 0)
346 return MF_E_INVALIDSTREAMNUMBER;
347
348 if (ppType == NULL)
349 return E_POINTER;
350
351 QMutexLocker locker(&m_mutex);
352
353 if (!m_outputType)
354 return MF_E_TRANSFORM_TYPE_NOT_SET;
355
356 // Return a copy to make sure our type is not modified
357 if (FAILED(MFCreateMediaType(ppType)))
358 return E_OUTOFMEMORY;
359
360 return m_outputType->CopyAllItems(*ppType);
361}
362
363STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
364{
365 if (dwInputStreamID > 0)
366 return MF_E_INVALIDSTREAMNUMBER;
367
368 if (!pdwFlags)
369 return E_POINTER;
370
371 QMutexLocker locker(&m_mutex);
372
373 if (!m_inputType || !m_outputType)
374 return MF_E_TRANSFORM_TYPE_NOT_SET;
375
376 if (m_sample)
377 *pdwFlags = 0;
378 else
379 *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
380
381 return S_OK;
382}
383
384STDMETHODIMP MFTransform::GetOutputStatus(DWORD *pdwFlags)
385{
386 if (!pdwFlags)
387 return E_POINTER;
388
389 QMutexLocker locker(&m_mutex);
390
391 if (!m_inputType || !m_outputType)
392 return MF_E_TRANSFORM_TYPE_NOT_SET;
393
394 if (m_sample)
395 *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
396 else
397 *pdwFlags = 0;
398
399 return S_OK;
400}
401
402STDMETHODIMP MFTransform::SetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
403{
404 Q_UNUSED(hnsLowerBound);
405 Q_UNUSED(hnsUpperBound);
406 return E_NOTIMPL;
407}
408
409STDMETHODIMP MFTransform::ProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
410{
411 // This MFT ignores all events, and the pipeline should send all events downstream.
412 Q_UNUSED(dwInputStreamID);
413 Q_UNUSED(pEvent);
414 return E_NOTIMPL;
415}
416
417STDMETHODIMP MFTransform::ProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
418{
419 Q_UNUSED(ulParam);
420
421 HRESULT hr = S_OK;
422
423 switch (eMessage)
424 {
425 case MFT_MESSAGE_COMMAND_FLUSH:
426 hr = OnFlush();
427 break;
428
429 case MFT_MESSAGE_COMMAND_DRAIN:
430 // Drain: Tells the MFT not to accept any more input until
431 // all of the pending output has been processed. That is our
432 // default behevior already, so there is nothing to do.
433 break;
434
435 case MFT_MESSAGE_SET_D3D_MANAGER:
436 // The pipeline should never send this message unless the MFT
437 // has the MF_SA_D3D_AWARE attribute set to TRUE. However, if we
438 // do get this message, it's invalid and we don't implement it.
439 hr = E_NOTIMPL;
440 break;
441
442 // The remaining messages do not require any action from this MFT.
443 case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
444 case MFT_MESSAGE_NOTIFY_END_STREAMING:
445 case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
446 case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
447 break;
448
449 default:
450 break;
451 }
452
453 return hr;
454}
455
456STDMETHODIMP MFTransform::ProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
457{
458 if (dwInputStreamID > 0)
459 return MF_E_INVALIDSTREAMNUMBER;
460
461 if (dwFlags != 0)
462 return E_INVALIDARG; // dwFlags is reserved and must be zero.
463
464 QMutexLocker locker(&m_mutex);
465
466 if (!m_inputType)
467 return MF_E_TRANSFORM_TYPE_NOT_SET;
468
469 if (m_sample)
470 return MF_E_NOTACCEPTING;
471
472 // Validate the number of buffers. There should only be a single buffer to hold the video frame.
473 DWORD dwBufferCount = 0;
474 HRESULT hr = pSample->GetBufferCount(&dwBufferCount);
475 if (FAILED(hr))
476 return hr;
477
478 if (dwBufferCount == 0)
479 return E_FAIL;
480
481 if (dwBufferCount > 1)
482 return MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS;
483
484 m_sample = pSample;
485 m_sample->AddRef();
486
487 QMutexLocker lockerProbe(&m_videoProbeMutex);
488
489// if (!m_videoProbes.isEmpty()) {
490// QVideoFrame frame = makeVideoFrame();
491
492// for (MFVideoProbeControl* probe : std::as_const(m_videoProbes))
493// probe->bufferProbed(frame);
494// }
495
496 return S_OK;
497}
498
499STDMETHODIMP MFTransform::ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
500{
501 if (pOutputSamples == NULL || pdwStatus == NULL)
502 return E_POINTER;
503
504 if (cOutputBufferCount != 1)
505 return E_INVALIDARG;
506
507 QMutexLocker locker(&m_mutex);
508
509 if (!m_inputType)
510 return MF_E_TRANSFORM_TYPE_NOT_SET;
511
512 if (!m_outputType) {
513 pOutputSamples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
514 return MF_E_TRANSFORM_STREAM_CHANGE;
515 }
516
517 if (dwFlags == MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER)
518 goto done;
519 else if (dwFlags != 0)
520 return E_INVALIDARG;
521
522 if (!m_sample)
523 return MF_E_TRANSFORM_NEED_MORE_INPUT;
524
525 // Since the MFT_OUTPUT_STREAM_PROVIDES_SAMPLES flag is set, the client
526 // should not be providing samples here
527 if (pOutputSamples[0].pSample != NULL)
528 return E_INVALIDARG;
529
530 pOutputSamples[0].pSample = m_sample;
531 pOutputSamples[0].pSample->AddRef();
532
533 // Send video frame to probes
534 // We do it here (instead of inside ProcessInput) to make sure samples discarded by the renderer
535 // are not sent.
536 m_videoProbeMutex.lock();
537// if (!m_videoProbes.isEmpty()) {
538// QVideoFrame frame = makeVideoFrame();
539
540// for (MFVideoProbeControl* probe : std::as_const(m_videoProbes))
541// probe->bufferProbed(frame);
542// }
543 m_videoProbeMutex.unlock();
544
545done:
546 pOutputSamples[0].dwStatus = 0;
547 *pdwStatus = 0;
548
549 m_sample->Release();
550 m_sample = 0;
551
552 return S_OK;
553}
554
555HRESULT MFTransform::OnFlush()
556{
557 QMutexLocker locker(&m_mutex);
558
559 if (m_sample) {
560 m_sample->Release();
561 m_sample = 0;
562 }
563 return S_OK;
564}
565
566QVideoFrameFormat MFTransform::videoFormatForMFMediaType(IMFMediaType *mediaType, int *bytesPerLine)
567{
568 UINT32 stride;
569 if (FAILED(mediaType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride))) {
570 *bytesPerLine = 0;
571 return QVideoFrameFormat();
572 }
573
574 *bytesPerLine = (int)stride;
575
576 QSize size;
577 UINT32 width, height;
578 if (FAILED(MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height)))
579 return QVideoFrameFormat();
580
581 size.setWidth(width);
582 size.setHeight(height);
583
584 GUID subtype = GUID_NULL;
585 if (FAILED(mediaType->GetGUID(MF_MT_SUBTYPE, &subtype)))
586 return QVideoFrameFormat();
587
590 QVideoFrameFormat format(size, pixelFormat);
591
592 quint32 num, den;
593 if (SUCCEEDED(MFGetAttributeRatio(mediaType, MF_MT_FRAME_RATE, &num, &den))) {
594 format.setFrameRate(qreal(num)/den);
595 }
596
597 return format;
598}
599
600QVideoFrame MFTransform::makeVideoFrame()
601{
603
604 if (!m_format.isValid())
605 return frame;
606
607 IMFMediaBuffer *buffer = 0;
608
609 do {
610 if (FAILED(m_sample->ConvertToContiguousBuffer(&buffer)))
611 break;
612
613 QByteArray array = dataFromBuffer(buffer, m_format.frameHeight(), &m_bytesPerLine);
614 if (array.isEmpty())
615 break;
616
617 // Wrapping IMFSample or IMFMediaBuffer in a QVideoFrame is not possible because we cannot hold
618 // IMFSample for a "long" time without affecting the rest of the topology.
619 // If IMFSample is held for more than 5 frames decoder starts to reuse it even though it hasn't been released it yet.
620 // That is why we copy data from IMFMediaBuffer here.
621 frame = QVideoFrame(new QMemoryVideoBuffer(array, m_bytesPerLine), m_format);
622
623 // WMF uses 100-nanosecond units, Qt uses microseconds
624 LONGLONG startTime = -1;
625 if (SUCCEEDED(m_sample->GetSampleTime(&startTime))) {
626 frame.setStartTime(startTime * 0.1);
627
628 LONGLONG duration = -1;
629 if (SUCCEEDED(m_sample->GetSampleDuration(&duration)))
630 frame.setEndTime((startTime + duration) * 0.1);
631 }
632 } while (false);
633
634 if (buffer)
635 buffer->Release();
636
637 return frame;
638}
639
640QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine)
641{
643 BYTE *bytes;
644 DWORD length;
645 HRESULT hr = buffer->Lock(&bytes, NULL, &length);
646 if (SUCCEEDED(hr)) {
647 array = QByteArray((const char *)bytes, (int)length);
648 buffer->Unlock();
649 } else {
650 // try to lock as Direct3DSurface
651 IDirect3DSurface9 *surface = 0;
652 do {
653 if (FAILED(MFGetService(buffer, MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void**)&surface)))
654 break;
655
656 D3DLOCKED_RECT rect;
657 if (FAILED(surface->LockRect(&rect, NULL, D3DLOCK_READONLY)))
658 break;
659
660 if (bytesPerLine)
661 *bytesPerLine = (int)rect.Pitch;
662
663 array = QByteArray((const char *)rect.pBits, rect.Pitch * height);
664 surface->UnlockRect();
665 } while (false);
666
667 if (surface) {
668 surface->Release();
669 surface = 0;
670 }
671 }
672
673 return array;
674}
675
676bool MFTransform::isMediaTypeSupported(IMFMediaType *type)
677{
678 // If we don't have the video sink's type handler,
679 // assume it supports anything...
680 if (!m_videoSinkTypeHandler || !type)
681 return true;
682
683 return m_videoSinkTypeHandler->IsMediaTypeSupported(type, NULL) == S_OK;
684}
STDMETHODIMP ProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam) override
Definition mftvideo.cpp:417
STDMETHODIMP AddInputStreams(DWORD cStreams, DWORD *adwStreamIDs) override
Definition mftvideo.cpp:204
STDMETHODIMP ProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent) override
Definition mftvideo.cpp:409
STDMETHODIMP SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags) override
Definition mftvideo.cpp:286
void setVideoSink(IUnknown *videoSink)
Definition mftvideo.cpp:58
virtual ~MFTransform()
Definition mftvideo.cpp:30
STDMETHODIMP GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo) override
Definition mftvideo.cpp:133
STDMETHODIMP GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **pAttributes) override
Definition mftvideo.cpp:189
STDMETHODIMP GetAttributes(IMFAttributes **pAttributes) override
Definition mftvideo.cpp:174
STDMETHODIMP DeleteInputStream(DWORD dwStreamID) override
Definition mftvideo.cpp:197
STDMETHODIMP QueryInterface(REFIID iid, void **ppv) override
Definition mftvideo.cpp:72
STDMETHODIMP GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType) override
Definition mftvideo.cpp:343
STDMETHODIMP GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo) override
Definition mftvideo.cpp:154
STDMETHODIMP SetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound) override
Definition mftvideo.cpp:402
STDMETHODIMP GetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum) override
Definition mftvideo.cpp:102
STDMETHODIMP GetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams) override
Definition mftvideo.cpp:113
STDMETHODIMP GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **pAttributes) override
Definition mftvideo.cpp:181
STDMETHODIMP GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType) override
Definition mftvideo.cpp:212
STDMETHODIMP GetOutputStatus(DWORD *pdwFlags) override
Definition mftvideo.cpp:384
STDMETHODIMP SetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags) override
Definition mftvideo.cpp:252
STDMETHODIMP ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus) override
Definition mftvideo.cpp:499
STDMETHODIMP GetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType) override
Definition mftvideo.cpp:323
STDMETHODIMP GetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType) override
Definition mftvideo.cpp:227
STDMETHODIMP GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags) override
Definition mftvideo.cpp:363
STDMETHODIMP ProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags) override
Definition mftvideo.cpp:456
STDMETHODIMP GetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs) override
Definition mftvideo.cpp:123
\inmodule QtCore
Definition qbytearray.h:57
The QMemoryVideoBuffer class provides a system memory allocated video data buffer.
\inmodule QtCore
Definition qmutex.h:317
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:293
void lock() noexcept
Locks the mutex.
Definition qmutex.h:290
\inmodule QtCore
Definition qsize.h:25
The QVideoFrameFormat class specifies the stream format of a video presentation surface.
bool isValid() const
Identifies if a video surface format has a valid pixel format and frame size.
PixelFormat
Enumerates video data types.
int frameHeight() const
Returns the height of frame in a video stream.
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:26
rect
[4]
STDMETHODIMP_(ULONG) MFTransform
Definition mftvideo.cpp:88
Q_MULTIMEDIA_EXPORT QVideoFrameFormat::PixelFormat pixelFormatFromMediaSubtype(const GUID &subtype)
qint64 startTime
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
const void GLsizei GLsizei stride
GLenum GLuint buffer
GLint GLsizei width
GLenum type
GLbitfield flags
GLint GLsizei GLsizei GLenum format
GLenum array
GLuint num
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
double qreal
Definition qtypes.h:92
IUIViewSettingsInterop __RPC__in REFIID riid
IUIViewSettingsInterop __RPC__in REFIID __RPC__deref_out_opt void ** ppv
long HRESULT
QFrame frame
[0]