9#include <private/qplatformvideosink_p.h>
10#include <private/qabstractvideobuffer_p.h>
11#include <private/qwindowsmfdefs_p.h>
23#define PAD_TO_DWORD(x) (((x) + 3) & ~3)
35 , m_bytesPerLine(bytesPerLine)
60 qWarning(
"Faild to lock mf buffer!");
80 IMFMediaBuffer *m_buffer;
86 static const GUID
IID_IMarker = {0xa3ff32de, 0x1031, 0x438a, {0x8b, 0x47, 0x82, 0xf8, 0xac, 0xda, 0x59, 0xb7}};
87 MIDL_INTERFACE(
"a3ff32de-1031-438a-8b47-82f8acda59b7")
88 IMarker : public IUnknown
90 virtual STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE *pType) = 0;
99 MFSTREAMSINK_MARKER_TYPE eMarkerType,
100 const PROPVARIANT* pvarMarkerValue,
101 const PROPVARIANT* pvarContextValue,
104 if (ppMarker == NULL)
113 if (SUCCEEDED(hr) && pvarMarkerValue)
116 if (SUCCEEDED(hr) && pvarContextValue)
121 (*ppMarker)->AddRef();
135 if (iid == IID_IUnknown) {
136 *
ppv =
static_cast<IUnknown*
>(
this);
138 *
ppv =
static_cast<IMarker*
>(
this);
141 return E_NOINTERFACE;
149 return InterlockedIncrement(&m_cRef);
154 LONG cRef = InterlockedDecrement(&m_cRef);
165 *pType = m_eMarkerType;
173 return PropVariantCopy(pvar, &m_varMarkerValue);
180 return PropVariantCopy(pvar, &m_varContextValue);
191 Marker(MFSTREAMSINK_MARKER_TYPE eMarkerType) : m_eMarkerType(eMarkerType)
193 PropVariantInit(&m_varMarkerValue);
194 PropVariantInit(&m_varContextValue);
199 PropVariantClear(&m_varMarkerValue);
200 PropVariantClear(&m_varContextValue);
209 static const DWORD DEFAULT_MEDIA_STREAM_ID = 0x0;
213 , m_rendererControl(rendererControl)
217 if (FAILED(MFCreateEventQueue(&m_eventQueue)))
218 qWarning(
"Failed to create mf event queue!");
219 if (FAILED(MFAllocateWorkQueue(&m_workQueueId)))
220 qWarning(
"Failed to allocated mf work queue!");
233 if (
riid == IID_IMFStreamSink) {
234 *ppvObject =
static_cast<IMFStreamSink*
>(
this);
235 }
else if (
riid == IID_IMFMediaEventGenerator) {
236 *ppvObject =
static_cast<IMFMediaEventGenerator*
>(
this);
237 }
else if (
riid == IID_IMFMediaTypeHandler) {
238 *ppvObject =
static_cast<IMFMediaTypeHandler*
>(
this);
239 }
else if (
riid == IID_IUnknown) {
240 *ppvObject =
static_cast<IUnknown*
>(
static_cast<IMFStreamSink*
>(
this));
243 return E_NOINTERFACE;
251 return InterlockedIncrement(&m_cRef);
256 LONG cRef = InterlockedDecrement(&m_cRef);
266 IMFMediaEvent **ppEvent)
override
271 IMFMediaEventQueue *
queue = NULL;
277 queue = m_eventQueue;
284 hr =
queue->GetEvent(dwFlags, ppEvent);
292 IMFAsyncCallback *pCallback,
293 IUnknown *punkState)
override
297 return MF_E_SHUTDOWN;
298 return m_eventQueue->BeginGetEvent(pCallback, punkState);
302 IMFAsyncResult *pResult,
303 IMFMediaEvent **ppEvent)
override
307 return MF_E_SHUTDOWN;
308 return m_eventQueue->EndGetEvent(pResult, ppEvent);
313 REFGUID guidExtendedType,
315 const PROPVARIANT *pvValue)
override
317#ifdef DEBUG_MEDIAFOUNDATION
318 qDebug() <<
"MediaStream::QueueEvent" << met;
322 return MF_E_SHUTDOWN;
323 return m_eventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue);
328 IMFMediaSink **ppMediaSink)
override
332 return MF_E_SHUTDOWN;
333 else if (!ppMediaSink)
337 *ppMediaSink = m_sink;
342 DWORD *pdwIdentifier)
override
344 *pdwIdentifier = MediaStream::DEFAULT_MEDIA_STREAM_ID;
349 IMFMediaTypeHandler **ppHandler)
override
351 LPVOID handler = NULL;
352 HRESULT hr = QueryInterface(IID_IMFMediaTypeHandler, &handler);
353 *ppHandler = (IMFMediaTypeHandler*)(handler);
358 IMFSample *pSample)
override
365 return MF_E_SHUTDOWN;
368 hr = validateOperation(OpProcessSample);
374 m_sampleQueue.push_back(pSample);
377 if (m_state != State_Paused)
378 hr = queueAsyncOperation(OpProcessSample);
384 MFSTREAMSINK_MARKER_TYPE eMarkerType,
385 const PROPVARIANT *pvarMarkerValue,
386 const PROPVARIANT *pvarContextValue)
override
390 IMarker *pMarker = NULL;
392 return MF_E_SHUTDOWN;
394 hr = validateOperation(OpPlaceMarker);
399 hr = Marker::Create(eMarkerType, pvarMarkerValue, pvarContextValue, &pMarker);
403 m_sampleQueue.push_back(pMarker);
406 if (m_state != State_Paused)
407 hr = queueAsyncOperation(OpPlaceMarker);
413#ifdef DEBUG_MEDIAFOUNDATION
414 qDebug() <<
"MediaStream::Flush";
418 return MF_E_SHUTDOWN;
422 return processSamplesFromQueue(DropSamples);
427 IMFMediaType *pMediaType,
428 IMFMediaType **ppMediaType)
override
434 return MF_E_SHUTDOWN;
436 int index = getMediaTypeIndex(pMediaType);
438 if (ppMediaType && m_mediaTypes.size() > 0) {
439 *ppMediaType = m_mediaTypes[0];
440 (*ppMediaType)->AddRef();
442 return MF_E_INVALIDMEDIATYPE;
448 if (ppMediaType && (SUCCEEDED(MFCreateMediaType(ppMediaType)))) {
449 (*ppMediaType)->CopyAllItems(pMediaType);
450 (*ppMediaType)->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
451 (*ppMediaType)->SetUINT32(MF_MT_COMPRESSED, FALSE);
452 (*ppMediaType)->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
454 return MF_E_INVALIDMEDIATYPE;
461 DWORD *pdwTypeCount)
override
463 if (pdwTypeCount == NULL)
466 *pdwTypeCount = DWORD(m_mediaTypes.size());
472 IMFMediaType **ppType)
override
482 if (dwIndex >= DWORD(m_mediaTypes.size()))
483 hr = MF_E_NO_MORE_TYPES;
487 *ppType = m_mediaTypes[dwIndex];
494 IMFMediaType *pMediaType)
override
499 return MF_E_SHUTDOWN;
501 DWORD flag = MF_MEDIATYPE_EQUAL_MAJOR_TYPES |
502 MF_MEDIATYPE_EQUAL_FORMAT_TYPES |
503 MF_MEDIATYPE_EQUAL_FORMAT_DATA;
505 if (m_currentMediaType && (m_currentMediaType->IsEqual(pMediaType, &flag) == S_OK))
508 hr = validateOperation(OpSetMediaType);
511 int index = getMediaTypeIndex(pMediaType);
514 hr = pMediaType->GetUINT64(MF_MT_FRAME_SIZE, &
size);
516 m_currentFormatIndex =
index;
523 if (SUCCEEDED(pMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE,
524 reinterpret_cast<UINT8*
>(&
viewport),
534 if (FAILED(pMediaType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&m_bytesPerLine))) {
535 m_bytesPerLine = getBytesPerLine(
format);
538 m_state = State_Ready;
539 if (m_currentMediaType)
540 m_currentMediaType->Release();
541 m_currentMediaType = pMediaType;
542 pMediaType->AddRef();
545 hr = MF_E_INVALIDREQUEST;
552 IMFMediaType **ppMediaType)
override
554 if (ppMediaType == NULL)
558 return MF_E_SHUTDOWN;
559 if (m_currentFormatIndex < 0)
560 return MF_E_NOT_INITIALIZED;
561 *ppMediaType = m_currentMediaType;
562 (*ppMediaType)->AddRef();
567 GUID *pguidMajorType)
override
569 if (pguidMajorType == NULL)
571 *pguidMajorType = MFMediaType_Video;
581 supportedFormatsChanged();
584 void setClock(IMFPresentationClock *presentationClock)
588 if (m_presentationClock)
589 m_presentationClock->Release();
590 m_presentationClock = presentationClock;
591 if (m_presentationClock)
592 m_presentationClock->AddRef();
601 if (m_currentMediaType) {
602 m_currentMediaType->Release();
603 m_currentMediaType = NULL;
604 m_currentFormatIndex = -1;
608 m_eventQueue->Shutdown();
610 MFUnlockWorkQueue(m_workQueueId);
612 if (m_presentationClock) {
613 m_presentationClock->Release();
614 m_presentationClock = NULL;
622 m_eventQueue->Release();
632 HRESULT hr = validateOperation(OpPreroll);
634 m_state = State_Prerolling;
635 m_prerollTargetTime = hnsUpcomingStartTime;
636 hr = queueAsyncOperation(OpPreroll);
645 hr = validateOperation(OpFinalize);
646 if (SUCCEEDED(hr) && m_finalizeResult != NULL)
647 hr = MF_E_INVALIDREQUEST;
651 hr = MFCreateAsyncResult(NULL, pCallback, punkState, &m_finalizeResult);
654 m_state = State_Finalized;
655 hr = queueAsyncOperation(OpFinalize);
662#ifdef DEBUG_MEDIAFOUNDATION
668 hr = validateOperation(OpStart);
675 m_presentationClock->GetCorrelatedTime(0, &m_startTime, &sysTime);
676 m_state = State_Started;
677 hr = queueAsyncOperation(OpStart);
684#ifdef DEBUG_MEDIAFOUNDATION
685 qDebug() <<
"MediaStream::restart";
688 HRESULT hr = validateOperation(OpRestart);
690 m_state = State_Started;
691 hr = queueAsyncOperation(OpRestart);
698#ifdef DEBUG_MEDIAFOUNDATION
699 qDebug() <<
"MediaStream::stop";
702 HRESULT hr = validateOperation(OpStop);
704 m_state = State_Stopped;
705 hr = queueAsyncOperation(OpStop);
712#ifdef DEBUG_MEDIAFOUNDATION
713 qDebug() <<
"MediaStream::pause";
716 HRESULT hr = validateOperation(OpPause);
718 m_state = State_Paused;
719 hr = queueAsyncOperation(OpPause);
726#ifdef DEBUG_MEDIAFOUNDATION
730 HRESULT hr = validateOperation(OpSetRate);
733 hr = queueAsyncOperation(OpSetRate);
741 m_pixelFormats.clear();
747 IMFMediaType *mediaType;
748 if (FAILED(MFCreateMediaType(&mediaType))) {
749 qWarning(
"Failed to create mf media type!");
752 mediaType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
753 mediaType->SetUINT32(MF_MT_COMPRESSED, FALSE);
754 mediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
755 mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
759 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_ARGB32);
762 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
766 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV);
769 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_I420);
772 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY);
775 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YV12);
778 mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12);
781 mediaType->Release();
787 m_pixelFormats.prepend(
format);
788 m_mediaTypes.prepend(mediaType);
795 if (!m_scheduledBuffer)
799 frame.setStartTime(m_bufferStartTime * 0.1);
800 frame.setEndTime((m_bufferStartTime + m_bufferDuration) * 0.1);
801 m_videoSink->platformVideoSink()->setVideoFrame(
frame);
802 m_scheduledBuffer->Release();
803 m_scheduledBuffer = NULL;
805 schedulePresentation(
true);
811 if (m_scheduledBuffer) {
812 m_scheduledBuffer->Release();
813 m_scheduledBuffer = NULL;
814 schedulePresentation(
true);
854 State_TypeNotSet = 0,
860 State_WaitForSurfaceStart,
862 State_Count = State_Finalized + 1
879 Op_Count = OpFinalize + 1
886 class AsyncOperation :
public IUnknown
889 AsyncOperation(StreamOperation op)
894 StreamOperation m_op;
897 STDMETHODIMP QueryInterface(REFIID iid,
void**
ppv)
override
901 if (iid == IID_IUnknown) {
902 *
ppv =
static_cast<IUnknown*
>(
this);
905 return E_NOINTERFACE;
912 return InterlockedIncrement(&m_cRef);
916 ULONG uCount = InterlockedDecrement(&m_cRef);
925 virtual ~AsyncOperation()
933 static BOOL ValidStateMatrix[State_Count][Op_Count];
938 IMFMediaType *m_currentMediaType =
nullptr;
939 State m_state = State_TypeNotSet;
940 IMFMediaSink *m_sink =
nullptr;
941 IMFMediaEventQueue *m_eventQueue =
nullptr;
942 DWORD m_workQueueId = 0;
945 IMFAsyncResult *m_finalizeResult =
nullptr;
946 MFTIME m_startTime = 0;
948 bool m_shutdown =
false;
951 int m_currentFormatIndex = -1;
952 int m_bytesPerLine = 0;
957 void clearMediaTypes()
959 for (IMFMediaType* mediaType :
std::as_const(m_mediaTypes))
961 m_mediaTypes.
clear();
964 int getMediaTypeIndex(IMFMediaType *mt)
967 if (FAILED(mt->GetMajorType(&majorType)))
969 if (majorType != MFMediaType_Video)
973 if (FAILED(mt->GetGUID(MF_MT_SUBTYPE, &subType)))
978 m_mediaTypes[
index]->GetGUID(MF_MT_SUBTYPE, &st);
987 switch (
format.pixelFormat()) {
994 return format.frameWidth() * 4;
1014 HRESULT onDispatchWorkItem(IMFAsyncResult* pAsyncResult)
1018 return MF_E_SHUTDOWN;
1021 IUnknown *pState = NULL;
1022 hr = pAsyncResult->GetState(&pState);
1023 if (SUCCEEDED(hr)) {
1025 AsyncOperation *pOp = (AsyncOperation*)pState;
1026 StreamOperation op = pOp->m_op;
1029 endPreroll(S_FALSE);
1030 schedulePresentation(
true);
1033 endPreroll(S_FALSE);
1034 if (SUCCEEDED(hr)) {
1036 hr = queueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL);
1038 schedulePresentation(
true);
1041 hr = processSamplesFromQueue(WriteSamples);
1049 hr = processSamplesFromQueue(DropSamples);
1052 hr = queueEvent(MEStreamSinkStopped, GUID_NULL, hr, NULL);
1055 hr = queueEvent(MEStreamSinkPaused, GUID_NULL, hr, NULL);
1058 hr = queueEvent(MEStreamSinkRateChanged, GUID_NULL, S_OK, NULL);
1060 case OpProcessSample:
1062 hr = dispatchProcessSample(pOp);
1065 endPreroll(S_FALSE);
1066 hr = dispatchFinalize(pOp);
1079 HRESULT queueEvent(MediaEventType met, REFGUID guidExtendedType,
HRESULT hrStatus,
const PROPVARIANT* pvValue)
1085 hr = m_eventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue);
1089 HRESULT validateOperation(StreamOperation op)
1092 if (ValidStateMatrix[m_state][op])
1095 return MF_E_INVALIDREQUEST;
1098 HRESULT queueAsyncOperation(StreamOperation op)
1101 AsyncOperation *asyncOp =
new AsyncOperation(op);
1102 if (asyncOp == NULL)
1106 hr = MFPutWorkItem(m_workQueueId, &m_workQueueCB, asyncOp);
1114 HRESULT processSamplesFromQueue(FlushState bFlushData)
1119 while (
pos != m_sampleQueue.
end()) {
1120 IUnknown *pUnk = NULL;
1121 IMarker *pMarker = NULL;
1122 IMFSample *pSample = NULL;
1125 if (SUCCEEDED(hr)) {
1126 hr = pUnk->QueryInterface(IID_IMarker, (
void**)&pMarker);
1127 if (hr == E_NOINTERFACE)
1128 hr = pUnk->QueryInterface(IID_IMFSample, (
void**)&pSample);
1132 if (SUCCEEDED(hr)) {
1134 hr = sendMarkerEvent(pMarker, bFlushData);
1137 if (bFlushData == WriteSamples)
1138 hr = processSampleData(pSample);
1160 m_prerolling =
true;
1163 queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL);
1166 void endPreroll(
HRESULT hrStatus)
1170 m_prerolling =
false;
1171 queueEvent(MEStreamSinkPrerolled, GUID_NULL, hrStatus, NULL);
1173 MFTIME m_prerollTargetTime = 0;
1174 bool m_prerolling =
false;
1176 void clearSampleQueue() {
1177 for (IUnknown* sample :
std::as_const(m_sampleQueue))
1179 m_sampleQueue.
clear();
1182 HRESULT sendMarkerEvent(IMarker *pMarker, FlushState FlushState)
1186 if (FlushState == DropSamples)
1190 PropVariantInit(&
var);
1193 hr = pMarker->GetContext(&
var);
1196 hr = queueEvent(MEStreamSinkMarker, GUID_NULL, hrStatus, &
var);
1198 PropVariantClear(&
var);
1202 HRESULT dispatchProcessSample(AsyncOperation* pOp)
1207 hr = processSamplesFromQueue(WriteSamples);
1210 hr = queueEvent(MEError, GUID_NULL, hr, NULL);
1215 HRESULT dispatchFinalize(AsyncOperation*)
1219 hr = processSamplesFromQueue(WriteSamples);
1222 m_finalizeResult->SetStatus(hr);
1223 hr = MFInvokeCallback(m_finalizeResult);
1227 HRESULT processSampleData(IMFSample *pSample)
1229 m_sampleRequested =
false;
1231 LONGLONG
time, duration = -1;
1234 pSample->GetSampleDuration(&duration);
1237 if (SUCCEEDED(hr) && ((
time - m_prerollTargetTime) * m_rate) >= 0) {
1238 IMFMediaBuffer *pBuffer = NULL;
1239 hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1240 if (SUCCEEDED(hr)) {
1242 sb.m_buffer = pBuffer;
1244 sb.m_duration = duration;
1245 m_bufferCache.push_back(sb);
1249 queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL);
1252 bool requestSample =
true;
1254 if (SUCCEEDED(hr) && ((
time - m_startTime) * m_rate) >= 0) {
1255 IMFMediaBuffer *pBuffer = NULL;
1256 hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1257 if (SUCCEEDED(hr)) {
1259 sb.m_buffer = pBuffer;
1261 sb.m_duration = duration;
1262 m_bufferCache.push_back(sb);
1265 requestSample =
false;
1267 schedulePresentation(requestSample);
1275 IMFMediaBuffer *m_buffer;
1277 LONGLONG m_duration;
1280 static const int BUFFER_CACHE_SIZE = 2;
1282 void clearBufferCache()
1284 for (SampleBuffer sb :
std::as_const(m_bufferCache))
1286 m_bufferCache.
clear();
1288 if (m_scheduledBuffer) {
1289 m_scheduledBuffer->Release();
1290 m_scheduledBuffer = NULL;
1294 void schedulePresentation(
bool requestSample)
1296 if (m_state == State_Paused || m_state == State_Prerolling)
1298 if (!m_scheduledBuffer) {
1303 if (FAILED(m_presentationClock->GetCorrelatedTime(0, &
currentTime, &sysTime)))
1306 while (!m_bufferCache.
isEmpty()) {
1307 SampleBuffer sb = m_bufferCache.
takeFirst();
1308 if (timeOK && ((sb.m_time -
currentTime) * m_rate) < 0) {
1309 sb.m_buffer->Release();
1310#ifdef DEBUG_MEDIAFOUNDATION
1311 qDebug() <<
"currentPresentTime =" << float(
currentTime / 10000) * 0.001f <<
" and sampleTime is" << float(sb.m_time / 10000) * 0.001f;
1315 m_scheduledBuffer = sb.m_buffer;
1316 m_bufferStartTime = sb.m_time;
1317 m_bufferDuration = sb.m_duration;
1320 queueEvent(MEStreamSinkScrubSampleComplete, GUID_NULL, S_OK, NULL);
1324 if (requestSample && !m_sampleRequested && m_bufferCache.
size() < BUFFER_CACHE_SIZE) {
1325 m_sampleRequested =
true;
1326 queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL);
1329 IMFMediaBuffer *m_scheduledBuffer =
nullptr;
1330 MFTIME m_bufferStartTime = -1;
1331 MFTIME m_bufferDuration = -1;
1332 IMFPresentationClock *m_presentationClock =
nullptr;
1333 bool m_sampleRequested =
false;
1337 BOOL MediaStream::ValidStateMatrix[MediaStream::State_Count][MediaStream::Op_Count] =
1341 TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1343 TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
1345 TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1347 FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1349 FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1351 FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE,
1353 FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE,
1355 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
1363 public IMFClockStateSink,
1364 public IMFMediaSinkPreroll,
1365 public IMFGetService,
1366 public IMFRateSupport
1371 m_stream =
new MediaStream(
this, rendererControl);
1384 m_stream->setSink(surface);
1392 m_stream->present();
1400 m_stream->clearScheduledFrame();
1406 if (!m_presentationClock)
1408 MFTIME
time, sysTime;
1409 m_presentationClock->GetCorrelatedTime(0, &
time, &sysTime);
1424 if (
riid == IID_IMFMediaSink) {
1425 *ppvObject =
static_cast<IMFMediaSink*
>(
this);
1426 }
else if (
riid == IID_IMFGetService) {
1427 *ppvObject =
static_cast<IMFGetService*
>(
this);
1428 }
else if (
riid == IID_IMFMediaSinkPreroll) {
1429 *ppvObject =
static_cast<IMFMediaSinkPreroll*
>(
this);
1430 }
else if (
riid == IID_IMFClockStateSink) {
1431 *ppvObject =
static_cast<IMFClockStateSink*
>(
this);
1432 }
else if (
riid == IID_IMFRateSupport) {
1433 *ppvObject =
static_cast<IMFRateSupport*
>(
this);
1434 }
else if (
riid == IID_IUnknown) {
1435 *ppvObject =
static_cast<IUnknown*
>(
static_cast<IMFFinalizableMediaSink*
>(
this));
1438 return E_NOINTERFACE;
1446 return InterlockedIncrement(&m_cRef);
1451 LONG cRef = InterlockedDecrement(&m_cRef);
1461 LPVOID *ppvObject)
override
1466 if (guidService != MF_RATE_CONTROL_SERVICE)
1467 return MF_E_UNSUPPORTED_SERVICE;
1469 return QueryInterface(
riid, ppvObject);
1477 return MF_E_SHUTDOWN;
1478 return m_stream->startPreroll(hnsUpcomingStartTime);
1482 STDMETHODIMP
BeginFinalize(IMFAsyncCallback *pCallback, IUnknown *punkState)
override
1486 return MF_E_SHUTDOWN;
1487 return m_stream->finalize(pCallback, punkState);
1494 if (pResult == NULL)
1497 hr = pResult->GetStatus();
1503 DWORD *pdwCharacteristics)
override
1507 return MF_E_SHUTDOWN;
1508 *pdwCharacteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL;
1515 IMFStreamSink **)
override
1518 return m_shutdown ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED;
1525 return m_shutdown ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED;
1529 DWORD *pcStreamSinkCount)
override
1533 return MF_E_SHUTDOWN;
1534 *pcStreamSinkCount = 1;
1540 IMFStreamSink **ppStreamSink)
override
1544 return MF_E_SHUTDOWN;
1547 return MF_E_INVALIDINDEX;
1549 *ppStreamSink = m_stream;
1555 DWORD dwStreamSinkIdentifier,
1556 IMFStreamSink **ppStreamSink)
override
1558 if (ppStreamSink == NULL)
1559 return E_INVALIDARG;
1560 if (dwStreamSinkIdentifier != MediaStream::DEFAULT_MEDIA_STREAM_ID)
1561 return MF_E_INVALIDSTREAMNUMBER;
1565 return MF_E_SHUTDOWN;
1567 *ppStreamSink = m_stream;
1573 IMFPresentationClock *pPresentationClock)
override
1577 return MF_E_SHUTDOWN;
1579 if (m_presentationClock) {
1580 m_presentationClock->RemoveClockStateSink(
this);
1581 m_presentationClock->Release();
1583 m_presentationClock = pPresentationClock;
1584 if (m_presentationClock) {
1585 m_presentationClock->AddRef();
1586 m_presentationClock->AddClockStateSink(
this);
1588 m_stream->setClock(m_presentationClock);
1593 IMFPresentationClock **ppPresentationClock)
override
1597 return MF_E_SHUTDOWN;
1598 *ppPresentationClock = m_presentationClock;
1599 if (m_presentationClock) {
1600 m_presentationClock->AddRef();
1603 return MF_E_NO_CLOCK;
1610 return MF_E_SHUTDOWN;
1612 m_stream->shutdown();
1613 if (m_presentationClock) {
1614 m_presentationClock->Release();
1615 m_presentationClock = NULL;
1617 m_stream->Release();
1628 return MF_E_SHUTDOWN;
1629 return m_stream->start(llClockStartOffset);
1636 return MF_E_SHUTDOWN;
1637 return m_stream->stop();
1644 return MF_E_SHUTDOWN;
1645 return m_stream->pause();
1652 return MF_E_SHUTDOWN;
1653 return m_stream->restart();
1660 return MF_E_SHUTDOWN;
1661 m_playRate = flRate;
1662 return m_stream->setRate(flRate);
1668 float *pflRate)
override
1673 *pflRate = (fThin ? 8.f : 2.0f) * (eDirection == MFRATE_FORWARD ? 1 : -1) ;
1680 float *pflRate)
override
1696 float *pflNearestSupportedRate)
override
1701 MFRATE_DIRECTION
direction = flRate > 0.f ? MFRATE_FORWARD
1704 float fastestRate = 0.f;
1705 float slowestRate = 0.f;
1706 GetFastestRate(
direction, fThin, &fastestRate);
1707 GetSlowestRate(
direction, fThin, &slowestRate);
1710 qSwap(fastestRate, slowestRate);
1712 if (flRate < slowestRate || flRate > fastestRate) {
1713 hr = MF_E_UNSUPPORTED_RATE;
1714 if (pflNearestSupportedRate) {
1715 *pflNearestSupportedRate =
qBound(slowestRate,
1720 }
else if (pflNearestSupportedRate) {
1721 *pflNearestSupportedRate = flRate;
1730 bool m_shutdown =
false;
1731 IMFPresentationClock *m_presentationClock =
nullptr;
1733 float m_playRate = 1;
1742 , m_rendererControl(rendererControl)
1746 MFCreateAttributes(&m_attributes, 0);
1747 m_sink =
new MediaSink(rendererControl);
1752 m_attributes->Release();
1760 if (
riid == IID_IMFActivate) {
1761 *ppvObject =
static_cast<IMFActivate*
>(
this);
1762 }
else if (
riid == IID_IMFAttributes) {
1763 *ppvObject =
static_cast<IMFAttributes*
>(
this);
1764 }
else if (
riid == IID_IUnknown) {
1765 *ppvObject =
static_cast<IUnknown*
>(
static_cast<IMFActivate*
>(
this));
1768 return E_NOINTERFACE;
1776 return InterlockedIncrement(&m_cRef);
1781 LONG cRef = InterlockedDecrement(&m_cRef);
1792 return E_INVALIDARG;
1795 m_sink =
new MediaSink(m_rendererControl);
1797 m_sink->setSurface(m_videoSink);
1799 return m_sink->QueryInterface(
riid,
ppv);
1807 hr = m_sink->Shutdown();
1827 PROPVARIANT *pValue)
override
1829 return m_attributes->GetItem(guidKey, pValue);
1834 MF_ATTRIBUTE_TYPE *pType)
override
1836 return m_attributes->GetItemType(guidKey, pType);
1841 REFPROPVARIANT Value,
1842 BOOL *pbResult)
override
1844 return m_attributes->CompareItem(guidKey, Value, pbResult);
1848 IMFAttributes *pTheirs,
1849 MF_ATTRIBUTES_MATCH_TYPE MatchType,
1850 BOOL *pbResult)
override
1852 return m_attributes->Compare(pTheirs, MatchType, pbResult);
1857 UINT32 *punValue)
override
1859 return m_attributes->GetUINT32(guidKey, punValue);
1864 UINT64 *punValue)
override
1866 return m_attributes->GetUINT64(guidKey, punValue);
1871 double *pfValue)
override
1873 return m_attributes->GetDouble(guidKey, pfValue);
1878 GUID *pguidValue)
override
1880 return m_attributes->GetGUID(guidKey, pguidValue);
1885 UINT32 *pcchLength)
override
1887 return m_attributes->GetStringLength(guidKey, pcchLength);
1894 UINT32 *pcchLength)
override
1896 return m_attributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength);
1902 UINT32 *pcchLength)
override
1904 return m_attributes->GetAllocatedString(guidKey, ppwszValue, pcchLength);
1909 UINT32 *pcbBlobSize)
override
1911 return m_attributes->GetBlobSize(guidKey, pcbBlobSize);
1918 UINT32 *pcbBlobSize)
override
1920 return m_attributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize);
1926 UINT32 *pcbSize)
override
1928 return m_attributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize);
1934 LPVOID *
ppv)
override
1936 return m_attributes->GetUnknown(guidKey,
riid,
ppv);
1941 REFPROPVARIANT Value)
override
1943 return m_attributes->SetItem(guidKey, Value);
1947 REFGUID guidKey)
override
1949 return m_attributes->DeleteItem(guidKey);
1954 return m_attributes->DeleteAllItems();
1959 UINT32 unValue)
override
1961 return m_attributes->SetUINT32(guidKey, unValue);
1966 UINT64 unValue)
override
1968 return m_attributes->SetUINT64(guidKey, unValue);
1973 double fValue)
override
1975 return m_attributes->SetDouble(guidKey, fValue);
1980 REFGUID guidValue)
override
1982 return m_attributes->SetGUID(guidKey, guidValue);
1987 LPCWSTR wszValue)
override
1989 return m_attributes->SetString(guidKey, wszValue);
1995 UINT32 cbBufSize)
override
1997 return m_attributes->SetBlob(guidKey, pBuf, cbBufSize);
2002 IUnknown *pUnknown)
override
2004 return m_attributes->SetUnknown(guidKey, pUnknown);
2009 return m_attributes->LockStore();
2014 return m_attributes->UnlockStore();
2018 UINT32 *pcItems)
override
2020 return m_attributes->GetCount(pcItems);
2026 PROPVARIANT *pValue)
override
2028 return m_attributes->GetItemByIndex(unIndex, pguidKey, pValue);
2032 IMFAttributes *pDest)
override
2034 return m_attributes->CopyAllItems(pDest);
2041 if (m_videoSink ==
sink)
2048 m_sink->setSurface(m_videoSink);
2064 m_sink->clearScheduledFrame();
2070 return m_sink->getTime();
2077 return m_sink->getPlayRate();
2085 IMFAttributes *m_attributes;
2124void MFVideoRendererControl::clear()
2127 m_sink->platformVideoSink()->setVideoFrame(
QVideoFrame());
2129 if (m_presenterActivate) {
2131 m_presenterActivate->Release();
2132 m_presenterActivate = NULL;
2135 if (m_currentActivate) {
2136 m_currentActivate->ShutdownObject();
2137 m_currentActivate->Release();
2139 m_currentActivate = NULL;
2156 if (m_presenterActivate)
2157 m_presenterActivate->
setSink(m_sink);
2158 else if (m_currentActivate)
2159 static_cast<VideoRendererActivate*
>(m_currentActivate)->
setSink(m_sink);
2164 if (m_presenterActivate)
2170 if (m_presenterActivate)
2173 if (!m_currentActivate)
2177 MFTIME targetTime =
static_cast<MediaStream::PresentEvent*
>(
event)->targetTime();
2178 MFTIME
currentTime =
static_cast<VideoRendererActivate*
>(m_currentActivate)->getTime();
2179 float playRate =
static_cast<VideoRendererActivate*
>(m_currentActivate)->getPlayRate();
2182 const int interval = ((targetTime -
currentTime) / 10000) / playRate;
2184 static_cast<VideoRendererActivate*
>(m_currentActivate)->clearScheduledFrame();
2195void MFVideoRendererControl::present()
2197 if (m_presenterActivate)
2200 if (m_currentActivate)
2201 static_cast<VideoRendererActivate*
>(m_currentActivate)->present();
2210 if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) {
2212 m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate);
2214 m_currentActivate =
new VideoRendererActivate(
this);
2220 return m_currentActivate;
2233 return E_INVALIDARG;
2253 m_presenter->Release();
2262 if (m_videoSink ==
sink)
2274 if (m_cropRect == cropRect)
2277 m_cropRect = cropRect;
2285#include "moc_mfvideorenderercontrol_p.cpp"
2286#include "mfvideorenderercontrol.moc"
void setCropRect(QRect cropRect)
void setSink(QVideoSink *sink)
STDMETHODIMP ActivateObject(REFIID riid, void **ppv) override
STDMETHODIMP ShutdownObject() override
~EVRCustomPresenterActivate()
STDMETHODIMP DetachObject() override
EVRCustomPresenterActivate(QVideoSink *sink)
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override
void setCropRect(QRect cropRect)
void setSink(QVideoSink *sink)
void setCropRect(QRect cropRect)
void setSink(QVideoSink *surface)
~MFVideoRendererControl()
QVideoSink * sink() const
MFVideoRendererControl(QObject *parent=0)
void customEvent(QEvent *event) override
This event handler can be reimplemented in a subclass to receive custom events.
IMFActivate * createActivate()
The QAbstractVideoBuffer class is an abstraction for video data. \inmodule QtMultimedia.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
Type
This enum type defines the valid event types in Qt.
qsizetype size() const noexcept
bool isEmpty() const noexcept
virtual void customEvent(QEvent *event)
This event handler can be reimplemented in a subclass to receive custom events.
\inmodule QtCore\reentrant
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP QueryInterface(REFIID iid, void **ppv) override
STDMETHODIMP_(ULONG) AddRef() override
PROPVARIANT m_varContextValue
PROPVARIANT m_varMarkerValue
MFSTREAMSINK_MARKER_TYPE m_eMarkerType
STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE *pType) override
STDMETHODIMP GetMarkerValue(PROPVARIANT *pvar) override
static HRESULT Create(MFSTREAMSINK_MARKER_TYPE eMarkerType, const PROPVARIANT *pvarMarkerValue, const PROPVARIANT *pvarContextValue, IMarker **ppMarker)
STDMETHODIMP GetContext(PROPVARIANT *pvar) override
STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8 *pBuf, UINT32 cbBufSize) override
STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32 *pcchLength) override
void clearScheduledFrame()
STDMETHODIMP DetachObject(void) override
STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32 *punValue) override
STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32 *pcchLength) override
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
STDMETHODIMP_(ULONG) Release(void) override
STDMETHODIMP ShutdownObject(void) override
STDMETHODIMP LockStore(void) override
STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown *pUnknown) override
STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID *ppv) override
void setSink(QVideoSink *sink)
STDMETHODIMP_(ULONG) AddRef(void) override
VideoRendererActivate(MFVideoRendererControl *rendererControl)
STDMETHODIMP GetDouble(REFGUID guidKey, double *pfValue) override
STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue) override
STDMETHODIMP GetBlob(REFGUID guidKey, UINT8 *pBuf, UINT32 cbBufSize, UINT32 *pcbBlobSize) override
STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT *pValue) override
STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL *pbResult) override
STDMETHODIMP SetDouble(REFGUID guidKey, double fValue) override
STDMETHODIMP UnlockStore(void) override
STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value) override
STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE *pType) override
virtual ~VideoRendererActivate()
STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64 *punValue) override
STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue) override
STDMETHODIMP DeleteAllItems(void) override
STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID *pguidKey, PROPVARIANT *pValue) override
STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8 **ppBuf, UINT32 *pcbSize) override
STDMETHODIMP CopyAllItems(IMFAttributes *pDest) override
STDMETHODIMP DeleteItem(REFGUID guidKey) override
STDMETHODIMP GetGUID(REFGUID guidKey, GUID *pguidValue) override
STDMETHODIMP Compare(IMFAttributes *pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL *pbResult) override
STDMETHODIMP SetUINT64(REFGUID guidKey, UINT64 unValue) override
STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength) override
STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue) override
STDMETHODIMP ActivateObject(REFIID riid, void **ppv) override
STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32 *pcbBlobSize) override
STDMETHODIMP GetCount(UINT32 *pcItems) override
bool singleShot
whether the timer is a single-shot timer
The QVideoFrame class represents a frame of video data.
MapMode
Enumerates how a video buffer's data is mapped to system memory.
The QVideoSink class represents a generic sink for video data.
STDMETHODIMP_(ULONG) MFDecoderSourceReader
Combined button and popup list for selecting options.
static const GUID IID_IMarker
virtual STDMETHODIMP GetMarkerValue(PROPVARIANT *pvar)=0
virtual STDMETHODIMP GetContext(PROPVARIANT *pvar)=0
bool qFuzzyIsNull(qfloat16 f) noexcept
constexpr const T & qBound(const T &min, const T &val, const T &max)
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum format
GLsizei GLenum GLboolean sink
static QAbstractVideoBuffer::MapData mapData(const camera_frame_nv12_t &frame, unsigned char *baseAddress)
static double currentTime()
IUIViewSettingsInterop __RPC__in REFIID riid
IUIViewSettingsInterop __RPC__in REFIID __RPC__deref_out_opt void ** ppv
#define QMM_PRESENTATION_CURRENT_POSITION
view viewport() -> scroll(dx, dy, deviceRect)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent