2025-11-28 00:35:46 +09:00

1349 lines
35 KiB
C++

#include "CHWMFT.h"
#include "CAutoLock.h"
#include <mferror.h>
#include <mfapi.h>
#include "CHWMFT_DebugLogger.h"
// Helper Macros
#define SAFERELEASE(x) \
if((x) != NULL) \
{ \
(x)->Release(); \
(x) = NULL; \
} \
/****************************
******* IMFTransform ********
****************************/
HRESULT CHWMFT::AddInputStreams(
DWORD dwStreams,
DWORD* pdwStreamIDs)
{
/*****************************************
** Todo: If your MFT does not have a fixed
** number of input streams, you must implement
** this function, see:
** http://msdn.microsoft.com/en-us/library/ms696211(v=VS.85).aspx
*****************************************/
return E_NOTIMPL;
}
HRESULT CHWMFT::DeleteInputStream(
DWORD dwStreamID)
{
/*****************************************
** Todo: If your MFT does not have a fixed
** number of input streams, you must implement
** this function, see:
** http://msdn.microsoft.com/en-us/library/ms703159(v=VS.85).aspx
*****************************************/
return E_NOTIMPL;
}
HRESULT CHWMFT::GetAttributes(
IMFAttributes** ppAttributes)
{
HRESULT hr = S_OK;
do
{
if(ppAttributes == NULL)
{
hr = E_POINTER;
break;
}
(*ppAttributes) = m_pAttributes;
if((*ppAttributes) == NULL)
{
hr = E_UNEXPECTED;
break;
}
(*ppAttributes)->AddRef();
}while(false);
return hr;
}
HRESULT CHWMFT::GetInputAvailableType(
DWORD dwInputStreamID,
DWORD dwTypeIndex,
IMFMediaType** ppType)
{
/*****************************************
** Todo: This function will return a media
** type at a given index. The SDK
** implementation uses a static array of
** media types. Your MFT may want to use
** a dynamic array and modify the list
** order depending on the MFTs state
** See http://msdn.microsoft.com/en-us/library/ms704814(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFMediaType* pMT = NULL;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(ppType == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
/*****************************************
** Todo: Modify the accepted input list
** g_ppguidInputTypes or use your own
** implementation of this function
*****************************************/
if(dwTypeIndex >= g_dwNumInputTypes)
{
hr = MF_E_NO_MORE_TYPES;
break;
}
{
CAutoLock lock(&m_csLock);
hr = MFCreateMediaType(&pMT);
if(FAILED(hr))
{
break;
}
hr = pMT->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
if(FAILED(hr))
{
break;
}
hr = pMT->SetGUID(MF_MT_SUBTYPE, *(g_ppguidInputTypes[dwTypeIndex]));
if(FAILED(hr))
{
break;
}
(*ppType) = pMT;
(*ppType)->AddRef();
}
}while(false);
SAFERELEASE(pMT);
return hr;
}
HRESULT CHWMFT::GetInputCurrentType(
DWORD dwInputStreamID,
IMFMediaType** ppType)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms705607(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFMediaType* pMT = NULL;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(ppType == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
{
CAutoLock lock(&m_csLock);
if(m_pInputMT == NULL)
{
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
break;
}
/*******************************************
** Return a copy of the media type, not the
** internal one. Returning the internal one
** will allow an external component to modify
** the internal media type
*******************************************/
hr = MFCreateMediaType(&pMT);
if(FAILED(hr))
{
break;
}
hr = DuplicateAttributes(pMT, m_pInputMT);
if(FAILED(hr))
{
break;
}
}
(*ppType) = pMT;
(*ppType)->AddRef();
}while(false);
SAFERELEASE(pMT);
return hr;
}
HRESULT CHWMFT::GetInputStatus(
DWORD dwInputStreamID,
DWORD* pdwFlags)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms697478(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pdwFlags == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
*pdwFlags = 0;
{
CAutoLock lock(&m_csLock);
if((m_dwStatus & MYMFT_STATUS_INPUT_ACCEPT_DATA) != 0)
{
*pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
}
}
}while(false);
return hr;
}
HRESULT CHWMFT::GetInputStreamAttributes(
DWORD dwInputStreamID,
IMFAttributes** ppAttributes)
{
/*****************************************
** Todo: Becuase this MFT is acting as a decoder
** There will not be an upstream HW MFT.
** As such, no input stream attributes
** are required.
** See http://msdn.microsoft.com/en-us/library/ms695366(v=VS.85).aspx,
** http://msdn.microsoft.com/en-us/library/dd940330(VS.85).aspx#handshake
*****************************************/
return E_NOTIMPL;
}
HRESULT CHWMFT::GetInputStreamInfo(
DWORD dwInputStreamID,
MFT_INPUT_STREAM_INFO* pStreamInfo)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms703894(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pStreamInfo == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
pStreamInfo->hnsMaxLatency = 0; // All input is turned directly into output
pStreamInfo->dwFlags = MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
pStreamInfo->cbSize = 0; // No minimum size is required
pStreamInfo->cbMaxLookahead = 0; // No lookahead is performed
pStreamInfo->cbAlignment = 0; // No memory allignment is required
}while(false);
return hr;
}
HRESULT CHWMFT::GetOutputAvailableType(
DWORD dwOutputStreamID,
DWORD dwTypeIndex,
IMFMediaType** ppType)
{
/*****************************************
** Todo: This function will return a media
** type at a given index. The SDK
** implementation uses a static array of
** media types. Your MFT may want to use
** a dynamic array and modify the list
** order depending on the MFTs state
** See http://msdn.microsoft.com/en-us/library/ms703812(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFMediaType* pMT = NULL;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(ppType == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwOutputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
/*****************************************
** Todo: Modify the accepted output list
** g_ppguidOutputTypes or use your own
** implementation of this function
*****************************************/
if(dwTypeIndex >= g_dwNumOutputTypes)
{
hr = MF_E_NO_MORE_TYPES;
break;
}
{
CAutoLock lock(&m_csLock);
hr = MFCreateMediaType(&pMT);
if(FAILED(hr))
{
break;
}
hr = pMT->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
if(FAILED(hr))
{
break;
}
hr = pMT->SetGUID(MF_MT_SUBTYPE, *(g_ppguidOutputTypes[dwTypeIndex]));
if(FAILED(hr))
{
break;
}
/*****************************************
** Todo: The following implementation
** forces a standard output resolution
** and framerate. Your MFT should set these
** values properly and update the Media
** Type as necessary after decoding the
** stream
*****************************************/
hr = MFSetAttributeSize(pMT, MF_MT_FRAME_SIZE, MFT_OUTPUT_WIDTH, MFT_OUTPUT_HEIGHT);
if(FAILED(hr))
{
break;
}
hr = MFSetAttributeRatio(pMT, MF_MT_FRAME_RATE, MFT_FRAMERATE_NUMERATOR, MFT_FRAMERATE_DENOMINATOR);
if(FAILED(hr))
{
break;
}
(*ppType) = pMT;
(*ppType)->AddRef();
}
}while(false);
SAFERELEASE(pMT);
return hr;
}
HRESULT CHWMFT::GetOutputCurrentType(
DWORD dwOutputStreamID,
IMFMediaType** ppType)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms696985(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFMediaType* pMT = NULL;
do
{
/************************************
** Since this MFT is a decoder, it
** must not allow this function to be
** called until it is unlocked. If
** your MFT is an encoder, this function
** CAN be called before the MFT is
** unlocked
************************************/
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(ppType == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwOutputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
{
CAutoLock lock(&m_csLock);
if(m_pOutputMT == NULL)
{
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
break;
}
/*******************************************
** Return a copy of the media type, not the
** internal one. Returning the internal one
** will allow an external component to modify
** the internal media type
*******************************************/
hr = MFCreateMediaType(&pMT);
if(FAILED(hr))
{
break;
}
hr = DuplicateAttributes(pMT, m_pOutputMT);
if(FAILED(hr))
{
break;
}
}
(*ppType) = pMT;
(*ppType)->AddRef();
}while(false);
SAFERELEASE(pMT);
return hr;
}
HRESULT CHWMFT::GetOutputStatus(
DWORD* pdwFlags)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms696269(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Enter", __FUNCTION__);
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pdwFlags == NULL)
{
hr = E_POINTER;
break;
}
(*pdwFlags) = 0;
{
CAutoLock lock(&m_csLock);
if((m_dwStatus & MYMFT_STATUS_OUTPUT_SAMPLE_READY) != 0)
{
*pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
}
}
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Output Status Flags: 0x%x", __FUNCTION__, (*pdwFlags));
}while(false);
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Exit (hr=0x%x)", __FUNCTION__, hr);
return hr;
}
HRESULT CHWMFT::GetOutputStreamAttributes(
DWORD dwOutputStreamID,
IMFAttributes** ppAttributes)
{
/*****************************************
** Todo: This MFT does not support a
** hardware handshake, so this function
** is not implemented
** See http://msdn.microsoft.com/en-us/library/ms703886(v=VS.85).aspx,
** http://msdn.microsoft.com/en-us/library/dd940330(VS.85).aspx#handshake
*****************************************/
return E_NOTIMPL;
}
HRESULT CHWMFT::GetOutputStreamInfo(
DWORD dwOutputStreamID,
MFT_OUTPUT_STREAM_INFO* pStreamInfo)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms693880(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pStreamInfo == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwOutputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES |
MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE |
MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES;
pStreamInfo->cbSize = (MFT_OUTPUT_WIDTH * MFT_OUTPUT_HEIGHT) * 4; // Since the MFT can output RGB32,
// it may need as many as 4 bytes
// per pixel, so the output buffer
// size must be set accordinly
// Todo: Change this value depending
// On the current output type
pStreamInfo->cbAlignment = 0; // No memory allignment is required
}while(false);
return hr;
}
HRESULT CHWMFT::GetStreamCount(
DWORD* pdwInputStreams,
DWORD* pdwOutputStreams)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms697018(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if((pdwInputStreams == NULL) || (pdwOutputStreams == NULL))
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
*pdwInputStreams = MFT_MAX_STREAMS;
*pdwOutputStreams = MFT_MAX_STREAMS;
}while(false);
return hr;
}
HRESULT CHWMFT::GetStreamIDs(
DWORD dwInputIDArraySize,
DWORD* pdwInputIDs,
DWORD dwOutputIDArraySize,
DWORD* pdwOutputIDs)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms693988(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if((pdwInputIDs == NULL) || (pdwOutputIDs == NULL))
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if((dwInputIDArraySize < MFT_MAX_STREAMS) || (dwOutputIDArraySize < MFT_MAX_STREAMS))
{
hr = MF_E_BUFFERTOOSMALL;
break;
}
pdwInputIDs[0] = 0;
pdwOutputIDs[0] = 0;
}while(false);
return hr;
}
HRESULT CHWMFT::GetStreamLimits(
DWORD* pdwInputMinimum,
DWORD* pdwInputMaximum,
DWORD* pdwOutputMinimum,
DWORD* pdwOutputMaximum)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms697040(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) ||
(pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
*pdwInputMinimum = MFT_MAX_STREAMS;
*pdwInputMaximum = MFT_MAX_STREAMS;
*pdwOutputMinimum = MFT_MAX_STREAMS;
*pdwOutputMaximum = MFT_MAX_STREAMS;
}while(false);
return hr;
}
HRESULT CHWMFT::ProcessEvent(
DWORD dwInputStreamID,
IMFMediaEvent* pEvent)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms695394(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pEvent == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
/****************************************
** Todo: this MFT does not handle any
** events. It allows them all to be
** propagated downstream. If your MFT
** needs to handle events, implement this
** function
****************************************/
hr = E_NOTIMPL;
}while(false);
return hr;
}
HRESULT CHWMFT::ProcessInput(
DWORD dwInputStreamID,
IMFSample* pSample,
DWORD dwFlags)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms703131(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Enter", __FUNCTION__);
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
{
CAutoLock lock(&m_csLock);
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): NeedInputCount: %u", __FUNCTION__, m_dwNeedInputCount);
if(m_dwNeedInputCount == 0)
{
// This call does not correspond to a need input call
hr = MF_E_NOTACCEPTING;
break;
}
else
{
m_dwNeedInputCount--;
}
}
if(pSample == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
// First, put sample into the input Queue
/***************************************
** Since this in an internal function
** we know m_pInputSampleQueue can never be
** NULL due to InitializeTransform()
***************************************/
hr = m_pInputSampleQueue->AddSample(pSample);
if(FAILED(hr))
{
break;
}
// Now schedule the work to decode the sample
hr = ScheduleFrameDecode();
if(FAILED(hr))
{
break;
}
}while(false);
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Exit (hr=0x%x)", __FUNCTION__, hr);
return hr;
}
HRESULT CHWMFT::ProcessMessage(
MFT_MESSAGE_TYPE eMessage,
ULONG_PTR ulParam)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms701863(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if((m_pInputMT == NULL) || (m_pOutputMT == NULL))
{
// Can't process messages until media types are set
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
break;
}
switch(eMessage)
{
case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
{
hr = OnStartOfStream();
if(FAILED(hr))
{
break;
}
}
break;
case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
{
hr = OnEndOfStream();
if(FAILED(hr))
{
break;
}
}
break;
case MFT_MESSAGE_COMMAND_DRAIN:
{
hr = OnDrain((UINT32)ulParam);
if(FAILED(hr))
{
break;
}
}
break;
case MFT_MESSAGE_COMMAND_FLUSH:
{
hr = OnFlush();
if(FAILED(hr))
{
break;
}
}
break;
case MFT_MESSAGE_COMMAND_MARKER:
{
hr = OnMarker(ulParam);
if(FAILED(hr))
{
break;
}
}
break;
/************************************************
** Todo: Add any MFT Messages that are not already
** covered
************************************************/
default:
// Nothing to do, return S_OK
break;
};
}while(false);
return hr;
}
HRESULT CHWMFT::ProcessOutput(
DWORD dwFlags,
DWORD dwOutputBufferCount,
MFT_OUTPUT_DATA_BUFFER* pOutputSamples,
DWORD* pdwStatus)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms704014(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFSample* pSample = NULL;
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Enter", __FUNCTION__);
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
{
CAutoLock lock(&m_csLock);
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): HaveOutputCount: %u", __FUNCTION__, m_dwHaveOutputCount);
if(m_dwHaveOutputCount == 0)
{
// This call does not correspond to a have output call
hr = E_UNEXPECTED;
break;
}
else
{
m_dwHaveOutputCount--;
}
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwOutputBufferCount < MFT_MAX_STREAMS)
{
hr = E_INVALIDARG;
break;
}
if(IsMFTReady() == FALSE)
{
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
break;
}
/***************************************
** Since this in an internal function
** we know m_pOutputSampleQueue can never be
** NULL due to InitializeTransform()
***************************************/
hr = m_pOutputSampleQueue->GetNextSample(&pSample);
if(FAILED(hr))
{
break;
}
if(pSample == NULL)
{
hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
break;
}
/*******************************
** Todo: This MFT only has one
** input stream, so the output
** samples array and stream ID
** will only use the first
** member
*******************************/
pOutputSamples[0].dwStreamID = 0;
if((pOutputSamples[0].pSample) == NULL)
{
// The MFT is providing it's own samples
(pOutputSamples[0].pSample) = pSample;
(pOutputSamples[0].pSample)->AddRef();
}
else
{
// The pipeline has allocated the samples
IMFMediaBuffer* pBuffer = NULL;
do
{
hr = pSample->ConvertToContiguousBuffer(&pBuffer);
if(FAILED(hr))
{
break;
}
hr = (pOutputSamples[0].pSample)->AddBuffer(pBuffer);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pBuffer);
if(FAILED(hr))
{
break;
}
}
/***************************************
** Since this in an internal function
** we know m_pOutputSampleQueue can never be
** NULL due to InitializeTransform()
***************************************/
if(m_pOutputSampleQueue->IsQueueEmpty() != FALSE)
{
// We're out of samples in the output queue
CAutoLock lock(&m_csLock);
if((m_dwStatus & MYMFT_STATUS_DRAINING) != 0)
{
// We're done draining, time to send the event
IMFMediaEvent* pDrainCompleteEvent = NULL;
do
{
hr = MFCreateMediaEvent(METransformDrainComplete , GUID_NULL, S_OK, NULL, &pDrainCompleteEvent);
if(FAILED(hr))
{
break;
}
/*******************************
** Todo: This MFT only has one
** input stream, so the drain
** is always on stream zero.
** Update this is your MFT
** has more than one stream
*******************************/
hr = pDrainCompleteEvent->SetUINT32(MF_EVENT_MFT_INPUT_STREAM_ID, 0);
if(FAILED(hr))
{
break;
}
/***************************************
** Since this in an internal function
** we know m_pEventQueue can never be
** NULL due to InitializeTransform()
***************************************/
hr = m_pEventQueue->QueueEvent(pDrainCompleteEvent);
if(FAILED(hr))
{
break;
}
}while(false);
SAFERELEASE(pDrainCompleteEvent);
if(FAILED(hr))
{
break;
}
m_dwStatus &= (~MYMFT_STATUS_DRAINING);
}
}
}while(false);
SAFERELEASE(pSample);
TraceString(CHMFTTracing::TRACE_INFORMATION, L"%S(): Exit (hr=0x%x)", __FUNCTION__, hr);
return hr;
}
HRESULT CHWMFT::SetInputType(
DWORD dwInputStreamID,
IMFMediaType* pType,
DWORD dwFlags)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms700113(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFMediaType* pMT = NULL;
do
{
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pType == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwInputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
hr = CheckInputType(pType);
if(FAILED(hr))
{
break;
}
/*******************************************
** Store a copy of the media type, not the
** one passed in by the caller. This way the
** caller is unable to modify the internal
** media type
*******************************************/
hr = MFCreateMediaType(&pMT);
if(FAILED(hr))
{
break;
}
hr = DuplicateAttributes(pMT, pType);
if(FAILED(hr))
{
break;
}
{
CAutoLock lock(&m_csLock);
SAFERELEASE(m_pInputMT);
m_pInputMT = pMT;
m_pInputMT->AddRef();
}
IsMFTReady();
}while(false);
SAFERELEASE(pMT);
return hr;
}
HRESULT CHWMFT::SetOutputBounds(
LONGLONG hnsLowerBound,
LONGLONG hnsUpperBound)
{
/*****************************************
** Todo: This MFT does not support
** sample boundries
** See http://msdn.microsoft.com/en-us/library/ms693812(v=VS.85).aspx
*****************************************/
return E_NOTIMPL;
}
HRESULT CHWMFT::SetOutputType(
DWORD dwOutputStreamID,
IMFMediaType* pType,
DWORD dwFlags)
{
/*****************************************
** See http://msdn.microsoft.com/en-us/library/ms702016(v=VS.85).aspx
*****************************************/
HRESULT hr = S_OK;
IMFMediaType* pMT = NULL;
do
{
/************************************
** Since this MFT is a decoder, it
** must not allow this function to be
** called until it is unlocked. If
** your MFT is an encoder, this function
** CAN be called before the MFT is
** unlocked
************************************/
if(IsLocked() != FALSE)
{
hr = MF_E_TRANSFORM_ASYNC_LOCKED;
break;
}
if(pType == NULL)
{
hr = E_POINTER;
break;
}
/*****************************************
** Todo: If your MFT supports more than one
** stream, make sure you modify
** MFT_MAX_STREAMS and adjust this function
** accordingly
*****************************************/
if(dwOutputStreamID >= MFT_MAX_STREAMS)
{
hr = MF_E_INVALIDSTREAMNUMBER;
break;
}
hr = CheckOutputType(pType);
if(FAILED(hr))
{
break;
}
/*******************************************
** Store a copy of the media type, not the
** one passed in by the caller. This way the
** caller is unable to modify the internal
** media type
*******************************************/
hr = MFCreateMediaType(&pMT);
if(FAILED(hr))
{
break;
}
hr = DuplicateAttributes(pMT, pType);
if(FAILED(hr))
{
break;
}
{
CAutoLock lock(&m_csLock);
SAFERELEASE(m_pOutputMT);
m_pOutputMT = pMT;
m_pOutputMT->AddRef();
}
IsMFTReady();
}while(false);
SAFERELEASE(pMT);
return hr;
}