diff options
Diffstat (limited to 'AVStream/sampledevicemft/basepin.cpp')
| -rw-r--r-- | AVStream/sampledevicemft/basepin.cpp | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/AVStream/sampledevicemft/basepin.cpp b/AVStream/sampledevicemft/basepin.cpp new file mode 100644 index 00000000..a1f71860 --- /dev/null +++ b/AVStream/sampledevicemft/basepin.cpp @@ -0,0 +1,847 @@ +#include "stdafx.h" +#include "common.h" +#include "multipinmft.h" +#include "multipinmfthelpers.h" +#include "basepin.h" + +#ifdef MF_WPP +#include "basepin.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif +/* -------> New STATE + | + |old State +DeviceStreamState_Stop DeviceStreamState_Pause DeviceStreamState_Run DeviceStreamState_Disabled +DeviceStreamState_Pause +DeviceStreamState_Run +DeviceStreamState_Disabled +*/ + +DeviceStreamState pinStateTransition[4][4] = { + { DeviceStreamState_Stop, DeviceStreamState_Pause, DeviceStreamState_Run, DeviceStreamState_Disabled }, + { DeviceStreamState_Stop, DeviceStreamState_Pause, DeviceStreamState_Run, DeviceStreamState_Disabled }, + { DeviceStreamState_Stop, DeviceStreamState_Pause, DeviceStreamState_Run, DeviceStreamState_Disabled }, + { DeviceStreamState_Disabled, DeviceStreamState_Disabled, DeviceStreamState_Disabled, DeviceStreamState_Disabled } +}; + +CBasePin::CBasePin( _In_ ULONG id, _In_ CMultipinMft *parent) : + m_StreamId(id) + , m_Parent(parent) + , m_setMediaType(nullptr) +{ + +} + +CBasePin::~CBasePin() +{ + IMFMediaType *pMediaType = nullptr; + for ( ULONG ulIndex = 0, ulSize = (ULONG)m_listOfMediaTypes.size(); ulIndex < ulSize; ulIndex++ ) + { + pMediaType = m_listOfMediaTypes[ulIndex]; + SAFE_RELEASE(pMediaType); + } + m_listOfMediaTypes.clear(); + m_spAttributes = nullptr; +} + +HRESULT CBasePin::AddMediaType( _Inout_ DWORD *pos, _In_ IMFMediaType *pMediaType) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + DMFTCHECKNULL_GOTO(pMediaType, done, E_INVALIDARG); + + hr = ExceptionBoundary([&]() + { + m_listOfMediaTypes.push_back(pMediaType); + }); + + DMFTCHECKHR_GOTO(hr, done); + pMediaType->AddRef(); + + if (pos) + { + *pos = (DWORD)(m_listOfMediaTypes.size() - 1); + } + +done: + return hr; +} + +HRESULT CBasePin::GetMediaTypeAt( _In_ DWORD pos, _Outptr_result_maybenull_ IMFMediaType **ppMediaType ) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + DMFTCHECKNULL_GOTO(ppMediaType,done,E_INVALIDARG); + + if (pos >= m_listOfMediaTypes.size()) + { + DMFTCHECKHR_GOTO(MF_E_NO_MORE_TYPES,done); + } + *ppMediaType = m_listOfMediaTypes[pos]; + if (*ppMediaType) + { + (*ppMediaType)->AddRef(); + } +done: + return hr; +} + +STDMETHODIMP_(BOOL) CBasePin::IsMediaTypeSupported +( + _In_ IMFMediaType *pMediaType, + _When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_) + IMFMediaType **ppIMFMediaTypeFull +) +{ + HRESULT hr = S_OK; + BOOL bFound = FALSE; + CAutoLock Lock(lock()); + DMFTCHECKNULL_GOTO(pMediaType,done,E_INVALIDARG); + if (ppIMFMediaTypeFull) + { + *ppIMFMediaTypeFull = nullptr; + } + + for (UINT uIIndex = 0, uISize = (UINT)m_listOfMediaTypes.size(); uIIndex < uISize ; uIIndex++ ) + { + DWORD dwResult = 0; + hr = m_listOfMediaTypes[ uIIndex ]->IsEqual( pMediaType, &dwResult ); + if (hr == S_FALSE) + { + + if ((dwResult & MF_MEDIATYPE_EQUAL_MAJOR_TYPES) && + (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_TYPES) && + (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_DATA)) + { + hr = S_OK; + } + } + if (hr == S_OK) + { + bFound = TRUE; + if (ppIMFMediaTypeFull) { + *ppIMFMediaTypeFull = m_listOfMediaTypes[uIIndex]; + (*ppIMFMediaTypeFull)->AddRef(); + } + break; + } + else if (FAILED(hr)) + { + DMFTCHECKHR_GOTO(hr,done); + } + } +done: + return SUCCEEDED(hr) ? TRUE : FALSE; +} + + +STDMETHODIMP CBasePin::GetOutputAvailableType(_In_ DWORD dwTypeIndex, _Out_opt_ IMFMediaType** ppType) +{ + return GetMediaTypeAt( dwTypeIndex, ppType ); +} + + +HRESULT CBasePin::QueryInterface( + _In_ REFIID iid, + _Outptr_result_maybenull_ void** ppv + ) +{ + HRESULT hr = S_OK; + + DMFTCHECKNULL_GOTO(ppv, out, E_POINTER); + + *ppv = nullptr; + + if ( iid == __uuidof( IUnknown ) ) + { + *ppv = static_cast<VOID*>(this); + AddRef(); + } + else + if ( iid == __uuidof( IMFAttributes ) ) + { + *ppv = static_cast< IMFAttributes* >( this ); + AddRef(); + } + else + if ( iid == __uuidof( IKsControl ) ) + { + *ppv = static_cast< IKsControl* >( this ); + AddRef(); + } + else + { + hr = E_NOINTERFACE; + } +out: + return hr; +} + + + + +// +//Input Pin implementation +// +CInPin::CInPin( + _In_opt_ IMFAttributes *pAttributes, + _In_ ULONG ulPinId, + _In_ CMultipinMft *pParent) + : + CBasePin(ulPinId, pParent), + m_stStreamType(GUID_NULL), + m_activeStreamCount(0), + m_state(DeviceStreamState_Stop), + m_prefferedMediaType(nullptr), + m_waitInputMediaTypeWaiter(NULL), + m_preferredStreamState(DeviceStreamState_Stop) +{ + setAttributes(pAttributes); +} + + + +CInPin::~CInPin() +{ + setAttributes( nullptr ); + m_spSourceTransform = nullptr; + + for (ULONG ulIndex = 0, ulSize = (ULONG)m_outpins.size(); + ulIndex < ulSize; + ulIndex++) + { + CBasePin *pPin = m_outpins[ulIndex]; + SAFERELEASE(pPin); + } + if (m_waitInputMediaTypeWaiter) + { + CloseHandle(m_waitInputMediaTypeWaiter); + } + +} + + + +STDMETHODIMP CInPin::Init( + _In_ IMFTransform* pTransform + ) +{ + + HRESULT hr = S_OK; + + DMFTCHECKNULL_GOTO( pTransform, done, E_INVALIDARG ); + + m_spSourceTransform = pTransform; + + DMFTCHECKHR_GOTO( GetGUID( MF_DEVICESTREAM_STREAM_CATEGORY, &m_stStreamType ), done ); + + // + //Get the DevProxy IKSControl.. used to send the KSControls or the device control IOCTLS over to devproxy and finally on to the driver!!!! + // + DMFTCHECKHR_GOTO( m_spAttributes.As( &m_spIkscontrol ), done ); + + m_waitInputMediaTypeWaiter = CreateEvent( NULL, + FALSE, + FALSE, + TEXT("MediaTypeWaiter") + ); + DMFTCHECKNULL_GOTO( m_waitInputMediaTypeWaiter, done, E_OUTOFMEMORY ); + + DMFTCHECKHR_GOTO( GenerateMFMediaTypeListFromDevice(streamId()),done ); + +done: + if ( FAILED(hr) ) + { + m_spSourceTransform = nullptr; + + if ( m_waitInputMediaTypeWaiter ) + { + CloseHandle( m_waitInputMediaTypeWaiter ); + m_waitInputMediaTypeWaiter = NULL; + } + + m_stStreamType = GUID_NULL; + } + + return hr; +} + + +STDMETHODIMP CInPin::GenerateMFMediaTypeListFromDevice( + _In_ UINT uiStreamId + ) +{ + HRESULT hr = S_OK; + GUID stSubType = { 0 }; + //This is only called in the begining when the input pin is constructed + DMFTCHECKNULL_GOTO( m_spSourceTransform, done, MF_E_TRANSFORM_TYPE_NOT_SET ); + for (UINT iMediaType = 0; SUCCEEDED(hr) ; iMediaType++) + { + ComPtr<IMFMediaType> spMediaType; + DWORD pos = 0; + + hr = m_spSourceTransform->MFTGetOutputAvailableType(uiStreamId, iMediaType, spMediaType.GetAddressOf()); + if (hr != S_OK) + break; + + DMFTCHECKHR_GOTO(AddMediaType(&pos, spMediaType.Get()), done); + } +done: + if (hr == MF_E_NO_MORE_TYPES) { + hr = S_OK; + } + return hr; +} + +STDMETHODIMP CInPin::SendSample( + _In_ IMFSample *pSample + ) +{ + HRESULT hr = S_OK; + BOOL sentOne = TRUE; + DMFTCHECKNULL_GOTO(pSample, done, S_OK); + + for ( ULONG ulIndex = 0, ulSize = (ULONG) m_outpins.size(); ulIndex < ulSize; ulIndex++ ) + { + COutPin *poPin = (COutPin *)m_outpins[ ulIndex ]; + + pSample->AddRef(); + + if (FAILED(hr = poPin->AddSample(pSample, this))) + { + pSample->Release(); + } + sentOne = (sentOne || SUCCEEDED(hr)); + } +done: + return sentOne ? S_OK : E_FAIL; +} + +STDMETHODIMP_(VOID) CInPin::ConnectPin( _In_ CBasePin * poPin ) +{ + CAutoLock Lock(lock()); + if (poPin!=nullptr) + { + m_outpins.push_back(poPin); + poPin->AddRef(); + } +} + +STDMETHODIMP_(DeviceStreamState) CInPin::GetState() +{ + return m_state; +} + +STDMETHODIMP_(DeviceStreamState) CInPin::SetState( _In_ DeviceStreamState state ) +{ + return (DeviceStreamState)InterlockedExchange((LONG*)&m_state, state ); +} + +STDMETHODIMP CInPin::WaitForSetInputPinMediaChange() +{ + DWORD dwWait = 0; + HRESULT hr = S_OK; + + dwWait = WaitForSingleObject( m_waitInputMediaTypeWaiter, INFINITE ); + + if ( dwWait != WAIT_OBJECT_0 ) + { + hr = E_FAIL; + goto done; + } +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CInPin::GetInputStreamPreferredState( + _Inout_ DeviceStreamState* value, + _Outptr_opt_result_maybenull_ IMFMediaType** ppMediaType + ) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + + if (value!=nullptr) + { + *value = m_preferredStreamState; + } + + if (ppMediaType ) + { + *ppMediaType = nullptr; + if ( m_prefferedMediaType != nullptr ) + { + m_prefferedMediaType.CopyTo(ppMediaType); + } + } + + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +HRESULT CInPin::SetInputStreamState( + _In_ IMFMediaType* pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags + ) +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwFlags); + + CAutoLock Lock(lock()); + // + //Set the media type + // + + setMediaType(pMediaType); + SetState(value); + + // + //Set the event. This event is being waited by an output media/state change operation + // + + m_prefferedMediaType = nullptr; + SetEvent(m_waitInputMediaTypeWaiter); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + + +// +//Output Pin Implementation +// +COutPin::COutPin( + _In_ ULONG ulPinId, + _In_opt_ CMultipinMft *pparent, + _In_ IKsControl* pIksControl + ) + : CBasePin( ulPinId, pparent ), + m_firstSample( false ) +{ + HRESULT hr = S_OK; + CPinState* pState = NULL; + ComPtr<IMFAttributes> spAttributes; + + for ( ULONG ulIndex = 0; ulIndex <= DeviceStreamState_Disabled; ulIndex++ ) + { + switch ( ulIndex ) + { + + case DeviceStreamState_Run: + pState = ( CPinState* )new CPinOpenState(this); + DMFTCHECKNULL_GOTO(pState, done, E_OUTOFMEMORY); + break; + case DeviceStreamState_Pause: + case DeviceStreamState_Stop: + case DeviceStreamState_Disabled: + //Currently both the closed and the drain state behave similarly + pState = ( CPinState* )new CPinClosedState(); + DMFTCHECKNULL_GOTO(pState, done, E_OUTOFMEMORY); + break; + } + + m_states.push_back( pState ); + + m_state = m_states[ DeviceStreamState_Stop ]; + } + // + //Get the input pin IKS control.. the pin IKS control talks to sourcetransform's IKS control + // + m_spIkscontrol = pIksControl; + + MFCreateAttributes( &spAttributes, 3 ); //Create the space for the attribute store!! + setAttributes( spAttributes.Get()); + DMFTCHECKHR_GOTO( SetUINT32( MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE ), done ); + DMFTCHECKHR_GOTO( SetString( MFT_ENUM_HARDWARE_URL_Attribute, L"Sample_CameraExtensionMft" ),done ); + DMFTCHECKHR_GOTO( SetUINT32( MF_TRANSFORM_ASYNC, TRUE ),done ); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); +} + +COutPin::~COutPin() +{ + CPinQueue *que = NULL; + m_spAttributes = nullptr; + + for ( ULONG ulIndex = 0, ulSize = (ULONG)m_queues.size(); ulIndex < ulSize; ulIndex++ ) + { + que = m_queues[ ulIndex ]; + delete(que); + que = NULL; + } + CPinState *pinState = NULL; + for (ULONG ulIndex = 0, ulSize = (ULONG)m_states.size(); ulIndex < ulSize; ulIndex++) + { + pinState = m_states[ ulIndex ]; + delete( pinState ); + pinState = NULL; + } + m_states.clear(); + m_queues.clear(); +} + +/*++ +COutPin::AddPin +Description: +Called from AddSample if the Output Pin is in open state. This function looks for the queue +corresponding to the input pin and adds it in the queue. +--*/ +STDMETHODIMP COutPin::AddPin( + _In_ DWORD inputPinId + ) +{ + // + //Add a new queue corresponding to the input pin + // + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + + CPinQueue *que = new (std::nothrow) CPinQueue(inputPinId); + DMFTCHECKNULL_GOTO( que, done, E_OUTOFMEMORY ); + hr = ExceptionBoundary([&]() + { + (void)m_queues.push_back(que); + }); + DMFTCHECKHR_GOTO(hr, done); + // + //Just ramdonmize media types for odd numbered pins + // + if ( streamId() != 0 && streamId() % 2 != 0 ) + { + RandomnizeMediaTypes(m_listOfMediaTypes); + } + +done: + + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return S_OK; +} + +/*++ +COutPin::AddSampleInternal +Description: +Called from AddSample if the Output Pin is in open state. This function looks for the queue +corresponding to the input pin and adds it in the queue. +--*/ + +STDMETHODIMP COutPin::AddSampleInternal( _In_ IMFSample *pSample, _In_ CBasePin *pPin ) +{ + BOOL res = true; + CAutoLock Lock( lock() ); + + for ( DWORD dwIndex = 0, dwSize = (DWORD)m_queues.size(); dwIndex < dwSize; dwIndex++ ) + { + // + //This output pin maybe connected to multiple input pins + //Only insert into the corresponding queue to the input pin on which the + //sample is received + // + if (m_queues[dwIndex]->pinStreamId() == pPin->streamId()) + { + if (! m_queues[ dwIndex ]->Insert( pSample ) ) + { + res |= false; + } + + } + } + return res ? S_OK : E_FAIL; +} + +/*++ +COutPin::AddSample +Description: +Called when ProcessInput is called on the Device Transform. The Input Pin puts the samples +in the pins connected. If the Output pins are in open state the sample lands in the queues +--*/ + +STDMETHODIMP COutPin::AddSample( _In_ IMFSample *pSample, _In_ CBasePin *pPin) +{ + HRESULT hr = S_OK; + CAutoLock lock( lock() ); + + DMFTCHECKHR_GOTO( m_state->Open(), done ); + + DMFTCHECKHR_GOTO( AddSampleInternal( pSample, pPin ),done ); + +done: + return hr; +} + +/*++ +COutPin::SetState +Description: +State setter for the output pin +--*/ +STDMETHODIMP_(VOID) COutPin::SetFirstSample( + _In_ BOOL fisrtSample ) +{ + m_firstSample = fisrtSample; +} + +/*++ +COutPin::GetState +Description: +State getter for the output pin +--*/ +DeviceStreamState COutPin::GetState() +{ + return m_state->State(); +} + +/*++ +COutPin::SetState +Description: +State setter for the output pin +--*/ + +DeviceStreamState COutPin::SetState(DeviceStreamState state) +{ + CAutoLock Lock(lock()); + DeviceStreamState oldState = m_state->State(); + m_state = m_states[state]; + return oldState; + +} + +/*++ +COutPin::FlushQueues +Description: +Called from the device Transform when the output queues have to be flushed + +--*/ +HRESULT COutPin::FlushQueues() +{ + HRESULT hr = S_OK; + CAutoLock Lock( lock() ); + + for ( DWORD dwIndex = 0, dwSize = (DWORD) m_queues.size(); dwIndex < dwSize; dwIndex++ ) + { + CPinQueue *que = m_queues[ dwIndex ]; + que->Clear(); + } + + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} +/*++ +COutPin::ChangeMediaTypeFromInpin +Description: +called from the Device Transfrom When the input media type is changed. This will result in +the xvp being possibly installed in the queue if the media types set on the input +and the output dont match +--*/ +HRESULT COutPin::ChangeMediaTypeFromInpin( + _In_ CInPin* inPin, + _In_ IMFMediaType *pInMediatype, + _In_ IMFMediaType* pOutMediaType, + _In_ DeviceStreamState state) +{ + HRESULT hr = S_OK; + CPinQueue *que = NULL; + CAutoLock Lock(lock()); + // + //Set the state to disabled and while going out we will reset the state back to the requested state + //Flush so that we drop any samples we have in store!! + // + SetState(DeviceStreamState_Disabled); + FlushQueues(); + + for (DWORD dwIndex = 0, dwSize = (DWORD) m_queues.size(); dwIndex < dwSize; dwIndex++) + { + que = m_queues[ dwIndex ]; + if (inPin->streamId() == que->pinStreamId()) + { + break; + } + que = NULL; + } + + if ( que ) + { + // + //recreate the tee, pass the D3D Manager to the Tee which will use DX if D3D manager is present + // + IUnknown *pD3DManagerUnk = NULL; + + (VOID)Parent()->GetD3DDeviceManager( &pD3DManagerUnk ); + hr = que->RecreateTee( pInMediatype, pOutMediaType, pD3DManagerUnk ); + if ( SUCCEEDED( hr ) ) + { + (VOID)setMediaType( pOutMediaType ); + (VOID)SetState( state ); + } + SAFE_RELEASE(pD3DManagerUnk); + } + return hr; +} + +/*++ +Description: + called from the IMFdeviceTransform's +--*/ + +STDMETHODIMP COutPin::GetOutputStreamInfo( + _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo + ) +{ + HRESULT hr = S_OK; + IMFMediaType* pMediatype = nullptr; + + getMediaType( &pMediatype ); + + if (SUCCEEDED(hr) && !pMediatype) { + pMediatype->Release(); + pStreamInfo->cbAlignment = 0; + pStreamInfo->cbSize = 0; + pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; + pStreamInfo->dwFlags |= MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + //We provide our samples.. + } + else { + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + } + return hr; +} + +/*++ +COutPin::ProcessOutput +Description: + called from the Device Transfrom when the transform manager demands output samples.. + If we have samples we forward it. + If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have recieved the transform or not. + If we have recieved the sample and we are passing out a sample we should reset the trigger set on the Device Transform +--*/ + +STDMETHODIMP COutPin::ProcessOutput(_In_ DWORD dwFlags, + _Inout_ MFT_OUTPUT_DATA_BUFFER *pOutputSample, + _Out_ DWORD *pdwStatus + ) +{ + HRESULT hr = S_OK; + IMFSample* pSample = nullptr; + GUID pinClsid = GUID_NULL; + BOOL IsImagePin = FALSE; + BOOL IsSkipSample = FALSE; + UNREFERENCED_PARAMETER(pdwStatus); + UNREFERENCED_PARAMETER(dwFlags); + CAutoLock lock(lock()); + DMFTCHECKHR_GOTO(m_state->Open(), done); + + // + //Check if we are an image photo pin. The process output in that case should only proceed if trigger has been sent + //Candidate for subclass! + // + + if (SUCCEEDED(GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &pinClsid)) + && ((IsEqualCLSID(pinClsid, PINNAME_IMAGE)) || IsEqualCLSID(pinClsid, PINNAME_VIDEO_STILL))) + { + IsImagePin = TRUE; + } + + if (IsImagePin && !Parent()->isPhotoTriggerSent()) + { + IsSkipSample = TRUE; + } + + + + for ( DWORD dwIndex = 0, dwSize = (DWORD) m_queues.size(); dwIndex < dwSize; dwIndex++ ) + { + CPinQueue *que = m_queues[dwIndex]; + + pOutputSample->dwStatus = S_OK; + + if (!que->Remove(&pSample)) + { + break; + } + + MFTIME llTime = 0L; + + if (FAILED(pSample->GetSampleTime(&llTime))) + { + llTime = MFGetSystemTime(); + pSample->SetSampleTime(llTime); + } + + if (!IsSkipSample) + { + if (m_firstSample) + { + pSample->SetUINT32(MFSampleExtension_Discontinuity,TRUE); + SetFirstSample(FALSE); + } + + // + // Any processing before we pass the sample to further in the pipeline should be done here + // PROCESSSAMPLE(pSample); + // + + pOutputSample->pSample = pSample; + pOutputSample->dwStatus = S_OK; + } + else + { + SAFERELEASE(pSample); + } + } + if (!IsSkipSample && IsImagePin && pSample) + { + // + //A sample has been sent over so image pin should exit + // +#if defined (MF_DEVICEMFT_PHTOTOCONFIRMATION) + if (Parent()->IsPhotoConfirmationEnabled()) + { + // + // Photo confirmation is enabled i.e. the pipeline has set up photo confirmation + // Service photo confirmation. + // + ComPtr<IMFMediaType> spMediaType = nullptr; + + DMFTCHECKHR_GOTO(getMediaType(spMediaType.GetAddressOf()), done); + + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Calling PhotoConfirmation %p, is passed", pSample); + + DMFTCHECKHR_GOTO(Parent()->ProcessCapturePhotoConfirmationCallBack(spMediaType.Get(), pSample), done); + } +#endif + if (!Parent()->isPhotoModePhotoSequence()) + { + // + //A sample has been sent over so image pin should exit + // + Parent()->setPhotoTriggerSent(FALSE); + } + } +done: + return hr; +} + +/*++ + COutPin::KsProperty +Description: +The KsProperty for the Pin.. this is to reroute all pin kscontrols to the input pin +--*/ +STDMETHODIMP COutPin::KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ) +{ + // + //Route it to input pin + // + return m_spIkscontrol->KsProperty(pProperty, + ulPropertyLength, + pPropertyData, + ulDataLength, + pBytesReturned); +} + + + |
