summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjk <[email protected]>2023-08-25 15:16:49 -0700
committerAdonais Romero González <[email protected]>2023-08-25 15:28:29 -0700
commit2639b5d65fa4777c669c45be8f1a13142b0e49a0 (patch)
tree188b78a22b572b62729c68684662dcb7b65297f0
parente0c0afda943a63d5e6ce888e158096428c6654df (diff)
[avstream/sampledevicemft] Fix format change error for YUY2 (#984)
-rw-r--r--avstream/sampledevicemft/basepin.cpp4
-rw-r--r--avstream/sampledevicemft/basepin.h12
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp48
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.h5
-rw-r--r--avstream/sampledevicemft/multipinmftutils.cpp5
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: