summaryrefslogtreecommitdiff
path: root/avstream/sampledevicemft/multipinmfthelpers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'avstream/sampledevicemft/multipinmfthelpers.cpp')
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp988
1 files changed, 0 insertions, 988 deletions
diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp
deleted file mode 100644
index 078ca337..00000000
--- a/avstream/sampledevicemft/multipinmfthelpers.cpp
+++ /dev/null
@@ -1,988 +0,0 @@
-#include "stdafx.h"
-#include "common.h"
-#include "multipinmfthelpers.h"
-#include "multipinmft.h"
-#include "basepin.h"
-#include <wincodec.h>
-
-#ifdef MF_WPP
-#include "multipinmfthelpers.tmh" //--REF_ANALYZER_DONT_REMOVE--
-#endif
-class CMediaTypePrinter;
-//
-//Queue implementation
-//
-
-CPinQueue::CPinQueue( _In_ DWORD _InpinId )
-: m_teer(0),
- m_discotinuity(0),
- m_sampleCount(0),
- m_dwInPinId(_InpinId)
- /*
- Description
- _InpinId is the input pin Id to which this queue corresponds
- */
-{
-}
-CPinQueue::~CPinQueue( )
-{
-}
-
-/*++
-Description:
- Insert sample into the list once we reach the open queue
---*/
-STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
-{
- pSample->AddRef();
- HRESULT hr = ExceptionBoundary([&]()
- {
- m_sampleList.push_back(pSample);
- });
-
- if (FAILED(hr))
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
- SAFE_RELEASE(pSample);
- }
-}
-
-STDMETHODIMP_(BOOL) CPinQueue::Insert( _In_ IMFSample *pSample )
-//
-//m_teer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee, which inserts an xvp into the queue
-//
-{
- return SUCCEEDED( m_teer->PassThrough( pSample, this ) );
-}
-
-
-/*++
-Description:
- This extracts the first sample from the queue. called from Pin's ProcessOutput
---*/
-
-STDMETHODIMP_(BOOL) CPinQueue::Remove( _Outptr_result_maybenull_ IMFSample **ppSample)
-{
- HRESULT hr = S_OK;
- DMFTCHECKNULL_GOTO( ppSample, done,E_INVALIDARG );
- *ppSample = nullptr;
-
- if ( !m_sampleList.empty() )
- {
- *ppSample = m_sampleList.front();
- }
-
- DMFTCHECKNULL_GOTO( *ppSample, done, MF_E_TRANSFORM_NEED_MORE_INPUT );
-
- (*ppSample)->Release( );
-
- m_sampleList.erase( m_sampleList.begin() );
-done:
- return SUCCEEDED( hr ) ? TRUE : FALSE;
-}
-
-/*++
-Description:
- Empties the Queue. used by the flush
---*/
-VOID CPinQueue::Clear( )
-{
- IMFSample* pSample = nullptr;
- while ( !Empty() )
- {
- Remove( &pSample );
- SAFE_RELEASE( pSample );
- }
-}
-
-/*++
-Description:
- RecreateTee creates the underlying Tees in the queue. It accepts the input media type
- which is the media type set on the input pin and the output mediatype, which (duh) is the
- media type on the output pin
- It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
- have an xvp in the path i.e. inputMediatype =! outputMediatype
---*/
-
-STDMETHODIMP CPinQueue::RecreateTee( _In_ IMFMediaType *inMediatype,
- _In_ IMFMediaType *outMediatype,
- _In_opt_ IUnknown* punkManager )
-{
- HRESULT hr = S_OK;
- MF_TRANSFORM_XVP_OPERATION operation = DeviceMftTransformXVPIllegal;
-
- DMFTCHECKNULL_GOTO(inMediatype, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(outMediatype, done, E_INVALIDARG);
-
- SAFE_DELETE(m_teer);
-
- CNullTee *nulltee = new (std::nothrow) CNullTee();
- DMFTCHECKNULL_GOTO( nulltee, done, E_OUTOFMEMORY);
-
- DMFTCHECKHR_GOTO( CompareMediaTypesForXVP(inMediatype, outMediatype, &operation), done);
-
- if ( (operation != DeviceMftTransformXVPCurrent) && (operation!= DeviceMftTransformXVPIllegal) )
- {
- CXvptee* pXvptee = new (std::nothrow) CXvptee(nulltee);
- DMFTCHECKNULL_GOTO(pXvptee, done, E_OUTOFMEMORY);
- (void)pXvptee->SetD3DManager( punkManager );
- (void)pXvptee->SetMediaTypes( inMediatype, outMediatype );
- m_teer = dynamic_cast< Ctee* >( pXvptee );
- }
- else
- {
- m_teer = nulltee; /*A simple passthrough*/
- }
-
-done:
- DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr );
-
- if (FAILED(hr))
- {
- if (m_teer){
- delete(m_teer);
- m_teer = NULL;
- }
-
- }
- return hr;
-}
-
-//
-//State implementation
-//
-CPinOpenState::CPinOpenState(CBasePin *_pin)
-:CPinState(DeviceStreamState_Run), m_pin(_pin)
-{
-
-}
-
-
-
-/*++
-Description:
- This is the passthrough Tee in the literal sense i.e. It just dumps the sample
- into the queue qupplied as an argument
---*/
-STDMETHODIMP CNullTee::PassThrough( _In_ IMFSample *pSample, _In_ CPinQueue *que )
-{
- HRESULT hr = S_OK;
-
- DMFTCHECKNULL_GOTO(pSample, done, S_OK); //No OP for a NULL Sample!!!
- (VOID)que->InsertInternal(pSample);
-
- done:
- return hr;
-}
-
-/*++
-Description:
- This function sets the Media types on the XVP or the decoder transform. Here is where we configure the XVP
- or the Decoder or the Encoder tee if present. The first iteration only has the XVP added
---*/
-STDMETHODIMP CWrapTee::SetMediaTypes( _In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType )
-{
- HRESULT hr = S_OK;
- IMFTransform *pTransform = nullptr;
-
- DMFTCHECKHR_GOTO(Configure( pInMediaType, pOutMediaType, &pTransform ),done);
- m_videoProcessor = pTransform;
- m_pInputMediaType = pInMediaType;
- m_pOutputMediaType = pOutMediaType;
-
-done:
- SAFE_RELEASE(pTransform);
- return hr;
-}
-
-/*++
-Description:
-This is used when an XVP is present in the Pin. If the path is a passthrough i.e.
-the media type on the input and the output pins are the same then we will not see
-this path traversed. This function feeds the sample to the XVP or the decoding Tee
---*/
-STDMETHODIMP CWrapTee::PassThrough(_In_ IMFSample* pInSample, _In_ CPinQueue *pQue)
-{
- HRESULT hr = S_OK;
- IMFSample* pOutSample = nullptr;
-
- DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample),done);
-
- if (m_objectWrapped)
- {
- hr = m_objectWrapped->PassThrough(pOutSample, pQue);
- }
-
-done:
- if (FAILED(hr))
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
- }
-
- return hr;
-}
-
-
-/*++
-CXvptee::Do
-Description:
-Called to do what an XVP is supposed to do i.e. scaling, resize etc.
-This function is called when the samples are desposited from the input pin to the
-output pin queue during a ProcessInput call on the device transform. Of course the
-outpin should be in Open state for the sample to reach the XVP and consequetively the
-Output Pin.
-
-If the DX manager is set on the Transform and we receieve a DX sample then we will
-undertake the DX transform in the XVP else we will skip it and go the software way
---*/
-STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** pOutSample)
-{
- //
- //Since we are streaming in the software mode we will create a new sample
- //
- HRESULT hr = S_OK,pohr = S_OK;
- MFT_OUTPUT_DATA_BUFFER outputSample;
- MFT_OUTPUT_STREAM_INFO StreamInfo;
- IMFSample* spXVPOutputSample = nullptr;
- IMFMediaType* pOutMediaType = nullptr;
- ComPtr <IMFMediaBuffer> spIMFMediaBuffer = nullptr;
- GUID guidOutputSubType = GUID_NULL;
- pOutMediaType = getOutMediaType();
-
- DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
-
- DMFTCHECKHR_GOTO(pOutMediaType->GetGUID(MF_MT_SUBTYPE, &guidOutputSubType), done);
-
- BOOL isDx = false;
-
- if (SUCCEEDED(IsInputDxSample(pSample, &isDx)) && isDx)
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! DX Sample sent to XVP %p", pSample);
- }
-
- outputSample.dwStreamID = 0;
- outputSample.pSample = NULL;
-
- if (!(isDx && m_spDeviceManagerUnk!=nullptr))
- {
- //
- //Create a new sample for software encoding
- //
- DMFTCHECKHR_GOTO(MFCreateSample(&spXVPOutputSample), done);
-
- DMFTCHECKHR_GOTO(pSample->CopyAllItems(spXVPOutputSample), done);
-
- outputSample.pSample = spXVPOutputSample;
-
-
- DMFTCHECKHR_GOTO(Transform()->MFTGetOutputStreamInfo(0, &StreamInfo), done);
-
- if (!m_isOutPutImage)
- {
- DMFTCHECKHR_GOTO(MFGetAttributeSize(pOutMediaType, MF_MT_FRAME_SIZE, &m_uWidth, &m_uHeight), done);
- hr = MFCreate2DMediaBuffer(
- m_uWidth,
- m_uHeight,
- guidOutputSubType.Data1,
- FALSE, // top-down buffer (DX compatible)
- &spIMFMediaBuffer);
- if (FAILED(hr))
- {
- spIMFMediaBuffer = nullptr;
- spXVPOutputSample->Release();
-
- DMFTCHECKHR_GOTO(MFCreateAlignedMemoryBuffer(
- StreamInfo.cbSize,
- StreamInfo.cbAlignment,
- &spIMFMediaBuffer), done);
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP Configured without DX, Created a 1D buffer");
-
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP Configured with DX, Created a 2D buffer");
- }
- DMFTCHECKHR_GOTO(spXVPOutputSample->AddBuffer(spIMFMediaBuffer.Get()), done);
- }
- }
-
-
- //
- //Start streaming the xvp transform..
- //
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done); // ulParam set to zero
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done); // ulParam set to zero
-
-
- DMFTCHECKHR_GOTO(Transform()->MFTProcessInput(0, pSample, 0),done);
-
- DWORD dwStatus = 0;
-
- pohr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
-
- if (FAILED(pohr))
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP ProcessOutput,failure %x sample =%p", pohr, &outputSample);
- SAFERELEASE(spXVPOutputSample);
- }
-
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), done); // Flush the stream
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0), done); // Notify end of stream
- DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0), done); // Notify end of streaming
-
- spXVPOutputSample = outputSample.pSample;
-
- if ( SUCCEEDED(pohr) )
- {
- //Let us copy the timestamps
- LONGLONG hnsSampleDuration = 0;
- LONGLONG hnsSampleTime = 0;
-
- pSample->GetSampleDuration(&hnsSampleDuration);
- pSample->GetSampleTime(&hnsSampleTime);
- spXVPOutputSample->SetSampleDuration(hnsSampleDuration);
- spXVPOutputSample->SetSampleTime(hnsSampleTime);
- }
-
- *pOutSample = spXVPOutputSample;
- //
- //Release the Sample back to the pipeline
- //
- pSample->Release();
-
-done:
- hr = FAILED(pohr) ? pohr : hr;
- return hr;
-}
-
-/*++
-Description:
- Set the D3D Manager on the XVP
---*/
-STDMETHODIMP_(VOID) CXvptee::SetD3DManager(IUnknown* pUnk)
-{
- m_spDeviceManagerUnk = pUnk;
-}
-/*++
-Descrtiption:
- Create the XVP Transform with the media types supplied.
- This is invoked when an XVP is added to the Queue in the Output pins
- and the input pins media type and the output pins media type don't match.
-
---*/
-STDMETHODIMP CXvptee::Configure(
- _In_opt_ IMFMediaType* inMediaType,
- _In_opt_ IMFMediaType* outMediaType,
- _Outptr_ IMFTransform **ppTransform
- )
-{
- HRESULT hr = S_OK;
- GUID inMajorType = GUID_NULL;
- GUID outMajorType = GUID_NULL;
- bool imageType = false;
- bool optimized = false;
- bool optimizedxvpneeded = false;
- IMFMediaType *pXvpOutputMediaType = nullptr;
- ComPtr<IMFAttributes> pXvpTransformAttributes = nullptr;
- UINT32 width = 0, height = 0;
-
- DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
-
- m_isOutPutImage = false;
- m_isoptimizedPlanarInputOutput = false;
-
- //
- //Print out the Media type set on the XVP
- //
- {
- CMediaTypePrinter inType(inMediaType);
- CMediaTypePrinter outType(outMediaType);
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Input MediaType %s", inType.ToString());
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Output MediaType %s", outType.ToString());
- }
-
- DMFTCHECKHR_GOTO( CoCreateInstance(
- CLSID_VideoProcessorMFT,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARGS(ppTransform)), done);
-
-
-
- DMFTCHECKHR_GOTO( inMediaType->GetMajorType( &inMajorType ),done );
- DMFTCHECKHR_GOTO( outMediaType->GetMajorType( &outMajorType ), done );
- //
- //Configuring DX Manager in SW mode. We will look to make it DX complaint in the next phase
- //
- if ( !IsEqualGUID(MFMediaType_Video, outMajorType ) )
- {
- imageType = true;
- m_isOutPutImage = true;
- IsOptimizedPlanarVideoInputImageOutputPair(
- inMediaType,
- outMediaType,
- &optimized,
- &optimizedxvpneeded );
- }
-
- //
- //Disable frame rate conversion
- //
- DMFTCHECKHR_GOTO((*ppTransform)->GetAttributes(&pXvpTransformAttributes),done);
- pXvpTransformAttributes->SetUINT32(MF_XVP_DISABLE_FRC, TRUE);
- DMFTCHECKHR_GOTO( (*ppTransform)->MFTProcessMessage( MFT_MESSAGE_SET_D3D_MANAGER, NULL ), done );
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetInputType(0, inMediaType, 0), done);
-
-
- DMFTCHECKHR_GOTO(MFCreateMediaType(&pXvpOutputMediaType), done);
- DMFTCHECKHR_GOTO(outMediaType->CopyAllItems(pXvpOutputMediaType), done);
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), done); //Video propcessor doesn't understand image types
-
-
- if ( imageType )
- {
- GUID guidSub;
-
- if ( !optimized )
- {
- DMFTCHECKHR_GOTO( inMediaType->GetGUID(MF_MT_SUBTYPE, &guidSub ), done );
- if ( IsEqualGUID( guidSub, MFVideoFormat_ARGB32 ) )
- {
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_ARGB32), done);
- }
- else
- {
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), done);
- }
- DMFTCHECKHR_GOTO(MFGetAttributeSize(pXvpOutputMediaType, MF_MT_FRAME_SIZE, &width, &height), done);
-
- m_uWidth = width;
- m_uHeight = height;
-
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetUINT32(MF_MT_DEFAULT_STRIDE, width * 4), done); //So we always get a top down buffer
-
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, pXvpOutputMediaType, 0), done);
- }
- else
- {
- //*** If we come here we know that the XVP is needed
- //This case should be for non planar and xvp needed cases which we will always assume
- LONG cStride = 0;
- //For now we will just assume that we need the xvp in all cases
- DMFTCHECKHR_GOTO( inMediaType->GetGUID(MF_MT_SUBTYPE, &guidSub ), done );
-
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetGUID(MF_MT_SUBTYPE, guidSub), done);
-
- DMFTCHECKHR_GOTO(MFGetAttributeSize(pXvpOutputMediaType, MF_MT_FRAME_SIZE, &width, &height), done);
-
- DMFTCHECKHR_GOTO( MFGetStrideForBitmapInfoHeader( guidSub.Data1, width, &cStride ), done );
-
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetUINT32(MF_MT_DEFAULT_STRIDE, cStride), done); //So we always get a top down buffer for Nv12/Yv12
-
- DMFTCHECKHR_GOTO(pXvpOutputMediaType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255), done); //Always set nominal range to 0-255 to feed into a WIC encoder
-
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, pXvpOutputMediaType, 0), done);
- }
- }
- else
- {
- DMFTCHECKHR_GOTO((*ppTransform)->MFTSetOutputType(0, outMediaType, 0), done);
- }
- if ((m_spDeviceManagerUnk != nullptr))
- {
- //
- //Set the D3D Manager on the XVP if present
- //
- DMFTCHECKHR_GOTO((*ppTransform)->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER,
- reinterpret_cast<ULONG_PTR>(m_spDeviceManagerUnk.Get())), done);
- }
-done:
- SAFE_RELEASE(pXvpOutputMediaType);
- return hr;
-
-}
-
-
-CXvptee::CXvptee( _In_ Ctee *tee) :
-CWrapTee(tee),
- m_isOutPutImage(false),
- m_isoptimizedPlanarInputOutput(true),
- m_spDeviceManagerUnk(nullptr),
- m_uHeight(0),
- m_uWidth(0)
-
-{
-
-}
-
-
-CXvptee::~CXvptee()
-{
- m_spDeviceManagerUnk = nullptr;
-}
-
-//To be implemented..Not needed for the sample!!
-/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-
-STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Out_ IMFSample **pOutSample )
-{
- UNREFERENCED_PARAMETER(pSample);
- UNREFERENCED_PARAMETER(pOutSample);
- return S_OK;
-}
-STDMETHODIMP CDecoderTee::Configure( _In_opt_ IMFMediaType *inMediaType, _In_opt_ IMFMediaType *outMediaType, _Outptr_ IMFTransform** ppTransform)
-{
- HRESULT hr = S_OK;
- GUID guidcategory = GUID_NULL;
- BOOL IsDecoder = true;
- UINT32 unFlags = 0;
- MFT_REGISTER_TYPE_INFO in;
- MFT_REGISTER_TYPE_INFO out;
- UINT32 cActivates = 0;
- UINT32 unMFTFlags = 0;
- ComPtr<IMFMediaType> pInputMediaType = nullptr;
- ComPtr<IMFMediaType> pOutputMediaType = nullptr;
- IMFActivate **ppActivates = nullptr;
- DWORD dwInputStreams;
- DWORD dwOutputStreams;
- UNREFERENCED_PARAMETER(outMediaType);
- UNREFERENCED_PARAMETER(inMediaType);
- UNREFERENCED_PARAMETER(ppTransform);
-
- guidcategory = (IsDecoder)?MFT_CATEGORY_VIDEO_DECODER : MFT_CATEGORY_VIDEO_ENCODER;
-
- if (IsDecoder)
- {
- DMFTCHECKHR_GOTO(pInputMediaType->GetGUID(MF_MT_MAJOR_TYPE, &in.guidMajorType), done);
- DMFTCHECKHR_GOTO(pInputMediaType->GetGUID(MF_MT_SUBTYPE, &in.guidSubtype), done);
- }
- else
- {
- DMFTCHECKHR_GOTO(pOutputMediaType->GetGUID(MF_MT_MAJOR_TYPE, &out.guidMajorType), done);
- DMFTCHECKHR_GOTO(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &out.guidSubtype), done);
- }
-
- //
- //Use all possible plugins
- //
-
- unFlags = MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_SORTANDFILTER | MFT_ENUM_FLAG_SORTANDFILTER_WEB_ONLY;
- DMFTCHECKHR_GOTO(MFTEnumEx(guidcategory,
- unFlags,
- IsDecoder ? &in : NULL,
- IsDecoder ? NULL : &out,
- &ppActivates,
- &cActivates
- ),done);
- if (cActivates!=0)
- {
- DMFTCHECKHR_GOTO(MF_E_TOPO_CODEC_NOT_FOUND, done);
- }
- for (DWORD dwIndex = 0; dwIndex < cActivates; dwIndex++)
- {
- //
- //Check if this MFT requires an unlocking.. skip if it does
- //
- unMFTFlags = MFGetAttributeUINT32(ppActivates[dwIndex], MF_TRANSFORM_FLAGS_Attribute, 0);
- if (unMFTFlags & MFT_ENUM_FLAG_FIELDOFUSE)
- {
- //
- //If you have the unlocking key set MFT_FIELDOFUSE_UNLOCK_Attribute on the activate
- //
- continue;
- }
-
- hr = ppActivates[dwIndex]->ActivateObject(IID_PPV_ARGS(ppTransform));
- if (FAILED(hr))
- continue; //hope the next activate is activable
- ppActivates[dwIndex]->DetachObject();
-
- hr = (*ppTransform)->MFTGetStreamCount(&dwInputStreams, &dwOutputStreams);
-
- if (FAILED(hr) || dwInputStreams != 1 || dwOutputStreams > 127)//remove the hardcoding
- {
- //
- //Exception.. we can't use a stream that doesn't give us an idea about it's streams
- //
- continue;
- }
- if (IsDecoder)
- {
- hr = ConfigureDecoder(*ppTransform);
- }
- else
- {
- hr = ConfigureEncoder(*ppTransform);
- }
- if (FAILED(hr))
- {
- SAFE_RELEASE(*ppTransform);
- }
- }
-
-done:
- return hr;
-}
-
-/*++
-
---*/
-
-STDMETHODIMP CDecoderTee::ConfigureEncoder( _In_ IMFTransform *pTransform )
-{
- HRESULT hr = S_OK;
- //
- //Set the input media type and the output media type and that should be pretty much it
- //
- ComPtr<IMFMediaType> pInputType = nullptr;
- ComPtr<IMFMediaType> pOutputType = nullptr;
-
- pInputType = getInMediaType();
- pOutputType = getOutMediaType();
-
- if (pInputType && pOutputType)
- {
- //We should be good by now
- DMFTCHECKHR_GOTO( pTransform->MFTSetInputType( 0,pInputType.Get(), 0), done);
- //If we have D3D enabled then try again with D3D disabled and see the result
- //
- DMFTCHECKHR_GOTO(pTransform->MFTSetOutputType(0,pOutputType.Get(), 0), done);
- //
- //If the above operation fails and we are allowing partial media types then
- //we have to find the full media type and then check again
- }
- else
- {
- hr = E_FAIL;
- }
-done:
- return hr;
-}
-
-STDMETHODIMP CDecoderTee::ConfigureDecoder( _In_ IMFTransform *pTransform)
-{
- UNREFERENCED_PARAMETER( pTransform );
- return S_OK;
-}
-
-/*++
-Descrtiption:
- Handles events sent by the pipeline
- --*/
-STDMETHODIMP CDMFTEventHandler::KSEvent(
- _In_reads_bytes_(ulEventLength) PKSEVENT pEvent,
- _In_ ULONG ulEventLength,
- _Inout_updates_bytes_opt_(ulDataLength) LPVOID pEventData,
- _In_ ULONG ulDataLength,
- _Inout_ ULONG* pBytesReturned)
-{
- HRESULT hr = S_OK;
- UNREFERENCED_PARAMETER(ulDataLength);
- UNREFERENCED_PARAMETER(pBytesReturned);
-
- if (pEvent == nullptr)
- {
- //
- // We can have an Event Reset here
- //
- if (pEventData == nullptr)
- {
- //
- // Invalid input. KSEVENT and KSEVENTDATA cannot both be null
- //
- DMFTCHECKHR_GOTO(E_INVALIDARG, done);
- }
- //
- // The way KSevents work are, KSEVENT and KSEVENTDATA both have to be non null for events to be Set
- // on the driver. If the pipeline wishes to reset the event we pass the KSEVENT structure as NULL and
- // the KSEVENTDATA to be nonnull.
- // ********** EVENT RESET here since KSEVENT is null and KSEVENTDATA is not**********
- // We will never get Event Reset for One shot events
- // Search the list of regular events to find the KSEVENTDATA pointer and then free the entry
- //
- for ( vector<PDMFTEventEntry>::iterator it = m_RegularEventList.begin(); it != m_RegularEventList.end(); ++it )
- {
- PDMFTEventEntry pEntry = nullptr;
- pEntry = *it;
- DMFTCHECKNULL_GOTO(pEntry, done, E_UNEXPECTED); // We should never see a null data structure entry
- if (pEntry->m_pEventData == pEventData)
- {
- it = m_RegularEventList.erase(it);
- delete(pEntry); // Delete the entry!
- goto done;
- }
- }
-
- DMFTCHECKHR_GOTO(E_NOT_SET, done);
- }
- else
- {
- //
- // If we are here the pipeline wants to do the following things
- // 1) Store a regular event
- // 2) Store a oneshot event
- //
- HANDLE evtHandle = nullptr;
- PKSEVENT pEvt = pEvent;
- PKSEVENTDATA pEvtdata = reinterpret_cast<PKSEVENTDATA>(pEventData);
-
- if (ulEventLength < sizeof(KSEVENT))
- {
- DMFTCHECKNULL_GOTO(pBytesReturned, done, E_INVALIDARG);
- *pBytesReturned = sizeof(KSEVENT);
- DMFTCHECKHR_GOTO(HRESULT_FROM_WIN32(ERROR_MORE_DATA), done);
- }
-
- if (!pEvtdata)
- {
- //
- // Need the event data to be present to service the call properly!
- //
- DMFTCHECKHR_GOTO(E_INVALIDARG, done);
- }
-
- if (pEvt->Flags & KSEVENT_TYPE_ENABLE) // Regular/ Manual Reset Event
- {
- vector<PDMFTEventEntry>::iterator it = m_RegularEventList.begin();
- for (; it != m_RegularEventList.end(); it++)
- {
- PDMFTEventEntry pEntry = *it;
- DMFTCHECKNULL_GOTO(pEntry, done, E_FAIL);
- if (pEntry->m_pEventData == pEventData)
- {
- break;
- }
- }
- if (it != m_RegularEventList.end())
- {
- //
- // Duplicate entry found.
- //
- DMFTCHECKHR_GOTO(E_NOT_VALID_STATE, done);
- }
- }
- else if (pEvt->Flags & KSEVENT_TYPE_ONESHOT)
- {
- ULONG ulEventCommand = pEvt->Id;
- hr = ExceptionBoundary([&]()
- {
- map<ULONG, HANDLE>::iterator it = m_OneShotEventMap.find(ulEventCommand);
- if (it != m_OneShotEventMap.end())
- {
- //
- // Duplicate entry found.
- //
- hr = E_NOT_VALID_STATE;
- }
- });
- DMFTCHECKHR_GOTO(hr, done);
- }
- else
- {
- DMFTCHECKHR_GOTO(E_NOTIMPL, done);
- }
-
- //
- // Duplicate the handle
- //
- DMFTCHECKHR_GOTO(Dupe(pEvtdata->EventHandle.Event, &evtHandle),done);
- ULONG ulEventCommand = pEvt->Id;
-
- if (pEvt->Flags & KSEVENT_TYPE_ENABLE)
- {
- // ************** REGULAR EVENT ****************************
- // Regualar event. When this needs to be cleqared we will geta call with KSEVENT = null
- // and KSEVENTDATA with the same address as this call(pEvtdata). Hence store it
- // To set the event all we need is the EVENT id.
- //
- PDMFTEventEntry pEntry = new DMFTEventEntry(ulEventCommand, pEvtdata, evtHandle);
- DMFTCHECKNULL_GOTO(pEntry, done, E_OUTOFMEMORY);
- hr = ExceptionBoundary([&]()
- {
- (VOID)m_RegularEventList.push_back(pEntry);
- });
- }
- else if(pEvt->Flags & KSEVENT_TYPE_ONESHOT)
- {
- // *************** SINGLE SHOT EVENT ************************
- // Single Shot event store. Store the event Id and the Handle.
- //
- hr = ExceptionBoundary([&]()
- {
- (VOID)m_OneShotEventMap.insert(std::pair<ULONG, HANDLE>(ulEventCommand, evtHandle));
- });
- DMFTCHECKHR_GOTO(hr, done);
- }
- }
-
-done:
- return hr;
-}
-
-/*++
-Descrtiption:
- Used to set the One shot events sent by the pipeline.
- One shot events should be closed by the component after firing. The Pipeline
- will not send a reset or a clear for one shot events
---*/
-
-STDMETHODIMP CDMFTEventHandler::SetOneShot( ULONG ulEventId )
-{
- HRESULT hr = S_OK;
- hr = ExceptionBoundary([&]()
- {
- map<ULONG, HANDLE>::iterator it = m_OneShotEventMap.find(ulEventId);
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! trying to Set OneShot %d ", ulEventId);
-
- if (it != m_OneShotEventMap.end())
- {
- // Found the event
- HANDLE hOneShot = it->second;
- if (SetEvent(hOneShot))
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting OneShot %d Succeeded",
- ulEventId);
- CloseHandle(hOneShot);
- m_OneShotEventMap.erase(it);
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting OneShot %d failed %x",
- ulEventId,
- HRESULT_FROM_WIN32(GetLastError()));
- }
- }
- else
- {
- hr = E_NOT_SET;
- }
- });
- DMFTCHECKHR_GOTO(hr, done);
-done:
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting OneShot %d failed %x",
- ulEventId,
- HRESULT_FROM_WIN32(GetLastError()));
- return hr;
-}
-
-/*++
-Descrtiption:
- Used to set the Regular events sent by the pipeline.
- Regular events unlike the one shot events must be persisted
- until the pipeline explicitly needs the event to be unset.
---*/
-
-STDMETHODIMP CDMFTEventHandler::SetRegularEvent(ULONG ulEventId)
-{
- BOOL bEvtFound = FALSE;
- HRESULT hr = ExceptionBoundary([&]()
- {
-
- for (vector<PDMFTEventEntry>::iterator it = m_RegularEventList.begin(); it != m_RegularEventList.end(); ++it)
- {
- PDMFTEventEntry pEntry = *it;
- if (ulEventId == pEntry->m_ulEventId)
- {
- // Found the event
- bEvtFound = TRUE;
- if (!::SetEvent(pEntry->m_hHandle))
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting Event %d Failed 0x%x",
- ulEventId, hr);
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting Event %d s",
- ulEventId);
- }
- }
- }
- });
- if (!bEvtFound)
- {
- DMFTCHECKHR_GOTO(E_NOT_SET, done);
- }
-done:
- return hr;
-}
-
-/*++
-Descrtiption:
- Duplicates the handle passed.
---*/
-
-STDMETHODIMP CDMFTEventHandler::Dupe(_In_ HANDLE hEventHandle, _Outptr_ LPHANDLE lpTargetHandle)
-{
- HRESULT hr = S_OK;
- DMFTCHECKNULL_GOTO(hEventHandle, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(lpTargetHandle, done, E_INVALIDARG);
- //
- // Duplicate handle and store it for when it needs to be fired
- //
- if (!DuplicateHandle(GetCurrentProcess(), hEventHandle,
- GetCurrentProcess(), lpTargetHandle,
- 0,
- false,
- DUPLICATE_SAME_ACCESS
- ))
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Duplicating Event Handle failed %x",
- hr);
- DMFTCHECKHR_GOTO(hr, done);
- }
-done:
- return hr;
-}
-
-/*++
-
-Descrtiption:
- Cleans the event lists, both the Single shot and the Regular ones
-
---*/
-STDMETHODIMP CDMFTEventHandler::Clear()
-{
- HRESULT hr = S_OK;
- hr = ExceptionBoundary([&]()
- {
- map<ULONG, HANDLE>::iterator it = m_OneShotEventMap.begin();
- for (; it != m_OneShotEventMap.end(); ++it)
- {
- //
- // Delete the one shot entries. We should not see this path usually
- // as the pipeline will send a one shot event and set it soon. We
- // should remore the entry then.
- //
- CloseHandle(it->second);
- it = m_OneShotEventMap.erase(it);
- if (it == m_OneShotEventMap.end())
- {
- // We've reached the end break
- break;
- }
- }
- });
- DMFTCHECKHR_GOTO(hr, done);
- hr = ExceptionBoundary([=]()
- {
- vector<PDMFTEventEntry>::iterator it2 = m_RegularEventList.begin();
- for (; it2 != m_RegularEventList.end(); ++it2)
- {
- //
- // Delete the entries. This will be traversed
- //
- PDMFTEventEntry pEntry = *it2;
- it2 = m_RegularEventList.erase(it2);
- SAFE_DELETE(pEntry);
- if (it2 == m_RegularEventList.end())
- {
- break;
- }
- }
- });
- DMFTCHECKHR_GOTO(hr, done);
-done:
- return hr;
-}