[avstream/sampledevicemft] Fix format change error for YUY2 (#984)

This commit is contained in:
jk 2023-08-25 15:16:49 -07:00 коммит произвёл GitHub
Родитель a24deb382e
Коммит d35df21596
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 56 добавлений и 18 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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,

Просмотреть файл

@ -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:

Просмотреть файл

@ -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;

Просмотреть файл

@ -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: