diff options
| author | jk <[email protected]> | 2023-08-25 15:16:49 -0700 |
|---|---|---|
| committer | Adonais Romero González <[email protected]> | 2023-08-25 15:28:29 -0700 |
| commit | 2639b5d65fa4777c669c45be8f1a13142b0e49a0 (patch) | |
| tree | 188b78a22b572b62729c68684662dcb7b65297f0 | |
| parent | e0c0afda943a63d5e6ce888e158096428c6654df (diff) | |
[avstream/sampledevicemft] Fix format change error for YUY2 (#984)
| -rw-r--r-- | avstream/sampledevicemft/basepin.cpp | 4 | ||||
| -rw-r--r-- | avstream/sampledevicemft/basepin.h | 12 | ||||
| -rw-r--r-- | avstream/sampledevicemft/multipinmfthelpers.cpp | 48 | ||||
| -rw-r--r-- | avstream/sampledevicemft/multipinmfthelpers.h | 5 | ||||
| -rw-r--r-- | avstream/sampledevicemft/multipinmftutils.cpp | 5 |
5 files changed, 56 insertions, 18 deletions
diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp index 471bbca7..5195acc5 100644 --- a/avstream/sampledevicemft/basepin.cpp +++ b/avstream/sampledevicemft/basepin.cpp @@ -30,7 +30,7 @@ CBasePin::CBasePin( _In_ ULONG id, _In_ CMultipinMft *parent) : , m_setMediaType(nullptr) , m_nRefCount(0) , m_state(DeviceStreamState_Stop) - , m_dwWorkQueueId(MFASYNC_CALLBACK_QUEUE_UNDEFINED) + , m_dwWorkQueueId(MFASYNC_CALLBACK_QUEUE_MULTITHREADED) { } @@ -505,7 +505,7 @@ STDMETHODIMP COutPin::AddPin( } #if defined MF_DEVICEMFT_ADD_GRAYSCALER_ // Take this out to remove the gray scaler - m_queue = new (std::nothrow) CPinQueueWithGrayScale(inputPinId); + m_queue = new (std::nothrow) CPinQueueWithGrayScale(inputPinId,Parent()); #else m_queue = new (std::nothrow) CPinQueue(inputPinId,Parent()); #endif diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h index d3e45c93..2feff7ae 100644 --- a/avstream/sampledevicemft/basepin.h +++ b/avstream/sampledevicemft/basepin.h @@ -638,7 +638,17 @@ class CTranslateOutPin : public COutPin { MFVideoFormat_H264, MFVideoFormat_MJPG }; - // @@@@README : This is what the compressed media types will be translated into + + // @@@@README + // If you translate to YUY2 in D3D mode it is a suboptimal path, because the + // pipeline i.e. Frameserver will lock the surface into a staging buffer and + // map it to the client process like Teams, Camera App etc. + // Ideally when translating to YUY2, don't pass the D3D Manager to the + // Decoder (CDecoderTee) or the Video Processor (CXVPTee). The pipeline will + // shove the system buffer back into the DX surface on the client side, if the App + // demands DX surfaces. NV12 is sharable from frameserver to clients and hence + // the preferred format to decode into. + // The below subtype is what the compressed media types will be translated into. const GUID translatedGUID = MFVideoFormat_NV12; // Translating to NV12 public: CTranslateOutPin(_In_ ULONG id = 0, diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp index 0d720c3d..79c029b8 100644 --- a/avstream/sampledevicemft/multipinmfthelpers.cpp +++ b/avstream/sampledevicemft/multipinmfthelpers.cpp @@ -224,7 +224,7 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp ||IsEqualCLSID(gInputSubType, MFVideoFormat_RGB32)) { CGrayTee *pTee = NULL; - pTee = new (std::nothrow) CGrayTee(m_spTeer); + pTee = new (std::nothrow) CGrayTee(m_spTeer.Get()); DMFTCHECKHR_GOTO(pTee->SetMediaTypes(inMediatype, outMediatype), done); m_spTeer = dynamic_cast< Ctee* >(pTee); } @@ -305,7 +305,7 @@ HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMe HRESULT hr = S_OK; ComPtr<IMFTransform> spTransform; DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done); - DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done); + DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.ReleaseAndGetAddressOf()), done); m_spVideoProcessor = spTransform; // // Start streaming @@ -610,12 +610,14 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType, m_pOutputMediaType.Get(), spTransform.ReleaseAndGetAddressOf(), m_hwMFT))) { + m_hwMFT = TRUE; hr = ConfigDecoder(spTransform.Get(), gInSubType); } if (FAILED(hr)) { // Try creating SW deocder hr = S_OK; + m_hwMFT = FALSE; DMFTCHECKHR_GOTO(EnumSWDecoder(spTransform.ReleaseAndGetAddressOf(), gInSubType), done); DMFTCHECKHR_GOTO(ConfigDecoder(spTransform.Get(), gInSubType), done); } @@ -907,7 +909,7 @@ HRESULT CDecoderTee::ProcessFormatChange() // Also note, The platform doesn't support dynamic media type changes from the stream coming from the // source. // - ComPtr<CXvptee> spXvpTee; + ComPtr<CVideoProcTee> spXvpTee; DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidPreviousSubType), done); for (DWORD i = 0; ; i++) @@ -935,9 +937,21 @@ HRESULT CDecoderTee::ProcessFormatChange() // // Create the XVP and insert it into the chain manually. set the output to the mediatype requested by the platform // - spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get() ,m_streamCategory); + if (m_bXvpAdded && m_spXvp.Get()) + { + // The XVP was already created. change the xvp to handle format change + spXvpTee = m_spXvp; + } + else + { + spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get(), m_streamCategory); + m_spXvp = spXvpTee; + } DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY); - (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + if(m_hwMFT) + { + (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + } DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done); m_spObjectWrapped = spXvpTee; @@ -965,6 +979,8 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid DWORD dwMediaTypeIndex = 0; DWORD dwFlags = 0; ComPtr<IMFDXGIDeviceManager> spDxgiManager; + DWORD dwDesiredFlags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_DATA; + UNREFERENCED_PARAMETER(guidSubType); DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG); @@ -995,7 +1011,7 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done); DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done); - if (m_spDeviceManagerUnk.Get()) + if (m_hwMFT && m_spDeviceManagerUnk.Get()) { DMFTCHECKHR_GOTO(m_spDeviceManagerUnk.As(&spDxgiManager), done); if (m_D3daware && SUCCEEDED(IsDXFormatSupported(spDxgiManager.Get(), guidSubtype, nullptr, nullptr))) @@ -1025,22 +1041,30 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid spMediaType = nullptr; dwMediaTypeIndex++; } - // If cannot find a matchig mediatype, bail out. DMFTCHECKNULL_GOTO(spMediaType.Get(), done, MF_E_INVALIDMEDIATYPE); - // Try to set output type on the MJPG decoder. - DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(m_dwMFTOutputId, spMediaType.Get(), 0), done); - if (S_OK != (spMediaType->IsEqual(m_pOutputMediaType.Get(), &dwFlags))) + hr = spMediaType->IsEqual(m_pOutputMediaType.Get(), &dwFlags); + if ((S_OK == hr) || + (hr == S_FALSE && ((dwFlags & dwDesiredFlags) == dwDesiredFlags))) + { + // Try to set output type on the MJPG decoder. + DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(m_dwMFTOutputId, spMediaType.Get(), 0), done); + } + else { + // Set the media type and also create an XVP to manage the conversion + DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(m_dwMFTOutputId, spMediaType.Get(), 0), done); ComPtr<CXvptee> spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get(), m_streamCategory); DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY); - (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + if (m_hwMFT) + { + (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get()); + } DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spMediaType.Get(), m_pOutputMediaType.Get()), done); m_spObjectWrapped = spXvpTee; m_pOutputMediaType = spMediaType; //Recreate the Allocator - DMFTCHECKHR_GOTO(CreateAllocator(), done); m_bXvpAdded = TRUE; } done: diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h index 4237dbf4..4181bcca 100644 --- a/avstream/sampledevicemft/multipinmfthelpers.h +++ b/avstream/sampledevicemft/multipinmfthelpers.h @@ -201,11 +201,11 @@ public: private: DWORD m_dwInPinId; /* This is the input pin */ IMFSampleList m_sampleList; /* List storing the samples */ - IMFDeviceTransform* m_pTransform; /* Weak reference to the the device MFT */ GUID m_streamCategory; ULONG m_cRef; protected: - ComPtr<Ctee> m_spTeer; /*Tee that acts as a passthrough or an XVP */ + IMFDeviceTransform* m_pTransform; /* Weak reference to the the device MFT */ + ComPtr<Ctee> m_spTeer; /*Tee that acts as a passthrough or an XVP */ }; @@ -473,6 +473,7 @@ protected: DWORD m_lNeedInputRequest; GUID m_streamCategory; // Needed for bind flags BOOL m_bXvpAdded; + ComPtr<CVideoProcTee> m_spXvp; DWORD m_dwMFTInputId; DWORD m_dwMFTOutputId; ComPtr<IMFSample> m_spUnprocessedSample; diff --git a/avstream/sampledevicemft/multipinmftutils.cpp b/avstream/sampledevicemft/multipinmftutils.cpp index e4a62d52..cbd64f72 100644 --- a/avstream/sampledevicemft/multipinmftutils.cpp +++ b/avstream/sampledevicemft/multipinmftutils.cpp @@ -1292,7 +1292,10 @@ UpdateAllocatorAttributes( level = spDevice->GetFeatureLevel(); dwBindFlags |= ((level >= D3D_FEATURE_LEVEL_10_0) ? D3D11_BIND_SHADER_RESOURCE : 0); } - + else + { + dwBindFlags |= D3D11_BIND_RENDER_TARGET; + } DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_BINDFLAGS, dwBindFlags), done); done: |
