diff options
Diffstat (limited to 'plugins/pluginWinMF/internals')
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_codec.cxx | 1161 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_codec.h | 163 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_codec_topology.cxx | 619 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_codec_topology.h | 66 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_custom_src.cxx | 821 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_custom_src.h | 126 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_devices.cxx | 95 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_devices.h | 12 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_display_watcher.cxx | 181 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_display_watcher.h | 32 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_sample_grabber.cxx | 99 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_sample_grabber.h | 18 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_sample_queue.cxx | 75 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_sample_queue.h | 37 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_utils.cxx | 2792 | ||||
-rwxr-xr-x | plugins/pluginWinMF/internals/mf_utils.h | 383 |
16 files changed, 3121 insertions, 3559 deletions
diff --git a/plugins/pluginWinMF/internals/mf_codec.cxx b/plugins/pluginWinMF/internals/mf_codec.cxx index e2968f4..27fb903 100755 --- a/plugins/pluginWinMF/internals/mf_codec.cxx +++ b/plugins/pluginWinMF/internals/mf_codec.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -40,13 +40,13 @@ #endif // Make sure usable on Win7 SDK targeting Win8 OS -#if !defined(CODECAPI_AVLowLatencyMode) +#if !defined(CODECAPI_AVLowLatencyMode) DEFINE_GUID(CODECAPI_AVLowLatencyMode, - 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee); + 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee); #endif #if !defined(CODECAPI_AVDecVideoH264ErrorConcealment) DEFINE_GUID(CODECAPI_AVDecVideoH264ErrorConcealment, -0xececace8, 0x3436, 0x462c, 0x92, 0x94, 0xcd, 0x7b, 0xac, 0xd7, 0x58, 0xa9); + 0xececace8, 0x3436, 0x462c, 0x92, 0x94, 0xcd, 0x7b, 0xac, 0xd7, 0x58, 0xa9); #endif // @@ -54,117 +54,105 @@ DEFINE_GUID(CODECAPI_AVDecVideoH264ErrorConcealment, // MFCodec::MFCodec(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT /*= NULL*/) -: m_nRefCount(1) -, m_eId(eId) -, m_eType(eType) -, m_pMFT(NULL) -, m_pCodecAPI(NULL) -, m_pOutputType(NULL) -, m_pInputType(NULL) -, m_dwInputID(0) -, m_dwOutputID(0) -, m_rtStart(0) -, m_rtDuration(0) -, m_pSampleIn(NULL) -, m_pSampleOut(NULL) -, m_pEventGenerator(NULL) -, m_bIsAsync(FALSE) -, m_bIsFirstFrame(TRUE) -, m_bIsBundled(FALSE) -, m_nMETransformNeedInputCount(0) -, m_nMETransformHaveOutputCount(0) -, m_pSampleQueueAsyncInput(NULL) + : m_nRefCount(1) + , m_eId(eId) + , m_eType(eType) + , m_pMFT(NULL) + , m_pCodecAPI(NULL) + , m_pOutputType(NULL) + , m_pInputType(NULL) + , m_dwInputID(0) + , m_dwOutputID(0) + , m_rtStart(0) + , m_rtDuration(0) + , m_pSampleIn(NULL) + , m_pSampleOut(NULL) + , m_pEventGenerator(NULL) + , m_bIsAsync(FALSE) + , m_bIsFirstFrame(TRUE) + , m_bIsBundled(FALSE) + , m_nMETransformNeedInputCount(0) + , m_nMETransformHaveOutputCount(0) + , m_pSampleQueueAsyncInput(NULL) { - MFUtils::Startup(); - - HRESULT hr = S_OK; - - switch(eId) - { - case MFCodecId_H264Base: - case MFCodecId_H264Main: - { - m_eMediaType = MFCodecMediaType_Video; - m_guidCompressedFormat = MFVideoFormat_H264; - break; - } - case MFCodecId_AAC: - { - m_eMediaType = MFCodecMediaType_Audio; - m_guidCompressedFormat = MFAudioFormat_AAC; - break; - } - default: - { - assert(false); - break; - } - } - CHECK_HR(hr = MFCreateMediaType(&m_pOutputType)); - CHECK_HR(hr = MFCreateMediaType(&m_pInputType)); - if(pMFT) // up to the caller to make sure all parameters are corrrect - { - m_pMFT = pMFT; - m_pMFT->AddRef(); - } - else - { - CHECK_HR(hr = MFUtils::GetBestCodec( - (m_eType == MFCodecType_Encoder) ? TRUE : FALSE, // Encoder ? - (m_eMediaType == MFCodecMediaType_Video) ? MFMediaType_Video : MFMediaType_Audio, // Media Type - (m_eType == MFCodecType_Encoder) ? kMFCodecUncompressedFormat : m_guidCompressedFormat/*GUID_NULL*/, // Input - (m_eType == MFCodecType_Encoder) ? m_guidCompressedFormat : kMFCodecUncompressedFormat, // Output - &m_pMFT)); - } - hr = m_pMFT->QueryInterface(IID_PPV_ARGS(&m_pCodecAPI)); - if(FAILED(hr) && m_eType == MFCodecType_Encoder) // Required only for Encoders - { - CHECK_HR(hr); - } - - - CHECK_HR(hr = MFUtils::IsAsyncMFT(m_pMFT, &m_bIsAsync)); - if(m_bIsAsync) - { - m_pSampleQueueAsyncInput = new MFSampleQueue(); - if(!m_pSampleQueueAsyncInput) - { - CHECK_HR(hr = E_OUTOFMEMORY); - } - CHECK_HR(hr = MFUtils::UnlockAsyncMFT(m_pMFT)); - CHECK_HR(hr = m_pMFT->QueryInterface(IID_PPV_ARGS(&m_pEventGenerator))); - } + MFUtils::Startup(); + + HRESULT hr = S_OK; + + switch(eId) { + case MFCodecId_H264Base: + case MFCodecId_H264Main: { + m_eMediaType = MFCodecMediaType_Video; + m_guidCompressedFormat = MFVideoFormat_H264; + break; + } + case MFCodecId_AAC: { + m_eMediaType = MFCodecMediaType_Audio; + m_guidCompressedFormat = MFAudioFormat_AAC; + break; + } + default: { + assert(false); + break; + } + } + CHECK_HR(hr = MFCreateMediaType(&m_pOutputType)); + CHECK_HR(hr = MFCreateMediaType(&m_pInputType)); + if(pMFT) { // up to the caller to make sure all parameters are corrrect + m_pMFT = pMFT; + m_pMFT->AddRef(); + } + else { + CHECK_HR(hr = MFUtils::GetBestCodec( + (m_eType == MFCodecType_Encoder) ? TRUE : FALSE, // Encoder ? + (m_eMediaType == MFCodecMediaType_Video) ? MFMediaType_Video : MFMediaType_Audio, // Media Type + (m_eType == MFCodecType_Encoder) ? kMFCodecUncompressedFormat : m_guidCompressedFormat/*GUID_NULL*/, // Input + (m_eType == MFCodecType_Encoder) ? m_guidCompressedFormat : kMFCodecUncompressedFormat, // Output + &m_pMFT)); + } + hr = m_pMFT->QueryInterface(IID_PPV_ARGS(&m_pCodecAPI)); + if(FAILED(hr) && m_eType == MFCodecType_Encoder) { // Required only for Encoders + CHECK_HR(hr); + } + + + CHECK_HR(hr = MFUtils::IsAsyncMFT(m_pMFT, &m_bIsAsync)); + if(m_bIsAsync) { + m_pSampleQueueAsyncInput = new MFSampleQueue(); + if(!m_pSampleQueueAsyncInput) { + CHECK_HR(hr = E_OUTOFMEMORY); + } + CHECK_HR(hr = MFUtils::UnlockAsyncMFT(m_pMFT)); + CHECK_HR(hr = m_pMFT->QueryInterface(IID_PPV_ARGS(&m_pEventGenerator))); + } bail: - if(FAILED(hr)) - { - SafeRelease(&m_pMFT); - SafeRelease(&m_pCodecAPI); - } - if(!IsValid()) - { - TSK_DEBUG_ERROR("Failed to create codec with id = %d", m_eId); - } -} + if(FAILED(hr)) { + SafeRelease(&m_pMFT); + SafeRelease(&m_pCodecAPI); + } + if(!IsValid()) { + TSK_DEBUG_ERROR("Failed to create codec with id = %d", m_eId); + } +} MFCodec::~MFCodec() { - assert(m_nRefCount == 0); + assert(m_nRefCount == 0); - if(m_bIsAsync && m_pMFT) - { - m_pMFT->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, NULL); - m_pMFT->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, NULL); - } + if(m_bIsAsync && m_pMFT) { + m_pMFT->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, NULL); + m_pMFT->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, NULL); + } - SafeRelease(&m_pMFT); - SafeRelease(&m_pCodecAPI); + SafeRelease(&m_pMFT); + SafeRelease(&m_pCodecAPI); SafeRelease(&m_pOutputType); - SafeRelease(&m_pInputType); - SafeRelease(&m_pSampleIn); - SafeRelease(&m_pSampleOut); - SafeRelease(&m_pEventGenerator); - SafeRelease(&m_pSampleQueueAsyncInput); + SafeRelease(&m_pInputType); + SafeRelease(&m_pSampleIn); + SafeRelease(&m_pSampleOut); + SafeRelease(&m_pEventGenerator); + SafeRelease(&m_pSampleQueueAsyncInput); } ULONG MFCodec::AddRef() @@ -175,8 +163,7 @@ ULONG MFCodec::AddRef() ULONG MFCodec::Release() { ULONG uCount = InterlockedDecrement(&m_nRefCount); - if (uCount == 0) - { + if (uCount == 0) { delete this; } // For thread safety, return a temporary variable. @@ -185,242 +172,210 @@ ULONG MFCodec::Release() HRESULT MFCodec::QueryInterface(REFIID iid, void** ppv) { - if(!IsValid()) - { - return E_FAIL; - } - return m_pMFT->QueryInterface(iid, ppv); + if(!IsValid()) { + return E_FAIL; + } + return m_pMFT->QueryInterface(iid, ppv); } // IMFAsyncCallback STDMETHODIMP MFCodec::GetParameters(DWORD *pdwFlags, DWORD *pdwQueue) { - return E_NOTIMPL; + return E_NOTIMPL; } STDMETHODIMP MFCodec::Invoke(IMFAsyncResult *pAsyncResult) { - HRESULT hr = S_OK, hrStatus = S_OK; + HRESULT hr = S_OK, hrStatus = S_OK; IMFMediaEvent* pEvent = NULL; MediaEventType meType = MEUnknown; - + CHECK_HR(hr = m_pEventGenerator->EndGetEvent(pAsyncResult, &pEvent)); - CHECK_HR(hr = pEvent->GetType(&meType)); + CHECK_HR(hr = pEvent->GetType(&meType)); CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); - if (SUCCEEDED(hrStatus)) - { - switch(meType) - { - case METransformNeedInput: - { - InterlockedIncrement(&m_nMETransformNeedInputCount); - break; - } - - case METransformHaveOutput: - { - InterlockedIncrement(&m_nMETransformHaveOutputCount); - break; - } - } - } - + if (SUCCEEDED(hrStatus)) { + switch(meType) { + case METransformNeedInput: { + InterlockedIncrement(&m_nMETransformNeedInputCount); + break; + } + + case METransformHaveOutput: { + InterlockedIncrement(&m_nMETransformHaveOutputCount); + break; + } + } + } + CHECK_HR(hr = m_pEventGenerator->BeginGetEvent(this, NULL)); bail: - SafeRelease(&pEvent); + SafeRelease(&pEvent); return hr; } HRESULT MFCodec::ProcessInput(IMFSample* pSample) { - assert(IsReady()); - - HRESULT hr = S_OK; - - if(m_bIsFirstFrame) - { - if(m_bIsAsync && !m_bIsBundled) - { - CHECK_HR(hr = m_pMFT->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL)); - CHECK_HR(hr = m_pEventGenerator->BeginGetEvent(this, NULL)); - } - m_bIsFirstFrame = FALSE; - } - - if(m_bIsAsync) - { - if(m_nMETransformNeedInputCount == 1 && m_pSampleQueueAsyncInput->IsEmpty()) - { - InterlockedDecrement(&m_nMETransformNeedInputCount); - return m_pMFT->ProcessInput(m_dwInputID, pSample, 0); - } - - if(m_pSampleQueueAsyncInput->Count() > kMFCodecQueuedFramesMax) - { - m_pSampleQueueAsyncInput->Clear(); - CHECK_HR(hr = E_UNEXPECTED); - } - - // Input sample holds shared memory (also used by other samples) - IMFSample *pSampleCopy = NULL; - IMFMediaBuffer *pMediaBuffer = NULL, *pMediaBufferCopy = NULL; - BYTE *pBufferPtr = NULL, *pBufferPtrCopy = NULL; - DWORD dwDataLength = 0; - BOOL bMediaBufferLocked = FALSE, bMediaBufferLockedCopy = FALSE; - - CHECK_HR(hr = pSample->GetBufferByIndex(0, &pMediaBuffer)); - hr = pMediaBuffer->GetCurrentLength(&dwDataLength); - if(FAILED(hr)) - { - goto endofcopy; - } - hr = pMediaBuffer->Lock(&pBufferPtr, NULL, NULL); - if(FAILED(hr)) - { - goto endofcopy; - } - bMediaBufferLocked = TRUE; - - hr = MFUtils::CreateMediaSample(dwDataLength, &pSampleCopy); - if(FAILED(hr)) - { - goto endofcopy; - } - hr = pSampleCopy->GetBufferByIndex(0, &pMediaBufferCopy); - if(FAILED(hr)) - { - goto endofcopy; - } - hr = pMediaBufferCopy->Lock(&pBufferPtrCopy, NULL, NULL); - if(FAILED(hr)) - { - goto endofcopy; - } - bMediaBufferLockedCopy = TRUE; - - memcpy(pBufferPtrCopy, pBufferPtr, dwDataLength); - hr = pMediaBufferCopy->SetCurrentLength(dwDataLength); - if(FAILED(hr)) - { - goto endofcopy; - } - - LONGLONG hnsSampleTime = 0; - LONGLONG hnsSampleDuration = 0; - hr = pSample->GetSampleTime(&hnsSampleTime); - if(SUCCEEDED(hr)) - { - hr = pSampleCopy->SetSampleTime(hnsSampleTime); - } - hr = pSample->GetSampleDuration(&hnsSampleDuration); - if(SUCCEEDED(hr)) - { - hr = pSampleCopy->SetSampleDuration(hnsSampleDuration); - } - - // EnQueue - hr = m_pSampleQueueAsyncInput->Queue(pSampleCopy); + assert(IsReady()); + + HRESULT hr = S_OK; + + if(m_bIsFirstFrame) { + if(m_bIsAsync && !m_bIsBundled) { + CHECK_HR(hr = m_pMFT->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL)); + CHECK_HR(hr = m_pEventGenerator->BeginGetEvent(this, NULL)); + } + m_bIsFirstFrame = FALSE; + } + + if(m_bIsAsync) { + if(m_nMETransformNeedInputCount == 1 && m_pSampleQueueAsyncInput->IsEmpty()) { + InterlockedDecrement(&m_nMETransformNeedInputCount); + return m_pMFT->ProcessInput(m_dwInputID, pSample, 0); + } + + if(m_pSampleQueueAsyncInput->Count() > kMFCodecQueuedFramesMax) { + m_pSampleQueueAsyncInput->Clear(); + CHECK_HR(hr = E_UNEXPECTED); + } + + // Input sample holds shared memory (also used by other samples) + IMFSample *pSampleCopy = NULL; + IMFMediaBuffer *pMediaBuffer = NULL, *pMediaBufferCopy = NULL; + BYTE *pBufferPtr = NULL, *pBufferPtrCopy = NULL; + DWORD dwDataLength = 0; + BOOL bMediaBufferLocked = FALSE, bMediaBufferLockedCopy = FALSE; + + CHECK_HR(hr = pSample->GetBufferByIndex(0, &pMediaBuffer)); + hr = pMediaBuffer->GetCurrentLength(&dwDataLength); + if(FAILED(hr)) { + goto endofcopy; + } + hr = pMediaBuffer->Lock(&pBufferPtr, NULL, NULL); + if(FAILED(hr)) { + goto endofcopy; + } + bMediaBufferLocked = TRUE; + + hr = MFUtils::CreateMediaSample(dwDataLength, &pSampleCopy); + if(FAILED(hr)) { + goto endofcopy; + } + hr = pSampleCopy->GetBufferByIndex(0, &pMediaBufferCopy); + if(FAILED(hr)) { + goto endofcopy; + } + hr = pMediaBufferCopy->Lock(&pBufferPtrCopy, NULL, NULL); + if(FAILED(hr)) { + goto endofcopy; + } + bMediaBufferLockedCopy = TRUE; + + memcpy(pBufferPtrCopy, pBufferPtr, dwDataLength); + hr = pMediaBufferCopy->SetCurrentLength(dwDataLength); + if(FAILED(hr)) { + goto endofcopy; + } + + LONGLONG hnsSampleTime = 0; + LONGLONG hnsSampleDuration = 0; + hr = pSample->GetSampleTime(&hnsSampleTime); + if(SUCCEEDED(hr)) { + hr = pSampleCopy->SetSampleTime(hnsSampleTime); + } + hr = pSample->GetSampleDuration(&hnsSampleDuration); + if(SUCCEEDED(hr)) { + hr = pSampleCopy->SetSampleDuration(hnsSampleDuration); + } + + // EnQueue + hr = m_pSampleQueueAsyncInput->Queue(pSampleCopy); endofcopy: - if(pMediaBuffer && bMediaBufferLocked) - { - pMediaBuffer->Unlock(); - } - if(pMediaBufferCopy && bMediaBufferLockedCopy) - { - pMediaBufferCopy->Unlock(); - } - SafeRelease(&pSampleCopy); - SafeRelease(&pMediaBuffer); - CHECK_HR(hr); - - while(m_nMETransformNeedInputCount > 0) - { - if(m_pSampleQueueAsyncInput->IsEmpty()) - { - break; - } - IMFSample *_pSample = NULL; - hr = m_pSampleQueueAsyncInput->Dequeue(&_pSample); - if(SUCCEEDED(hr)) - { - InterlockedDecrement(&m_nMETransformNeedInputCount); - hr = m_pMFT->ProcessInput(m_dwInputID, _pSample, 0); - } - SafeRelease(&_pSample); - CHECK_HR(hr); - } - } - else - { - CHECK_HR(hr = m_pMFT->ProcessInput(m_dwInputID, pSample, 0)); - } + if(pMediaBuffer && bMediaBufferLocked) { + pMediaBuffer->Unlock(); + } + if(pMediaBufferCopy && bMediaBufferLockedCopy) { + pMediaBufferCopy->Unlock(); + } + SafeRelease(&pSampleCopy); + SafeRelease(&pMediaBuffer); + CHECK_HR(hr); + + while(m_nMETransformNeedInputCount > 0) { + if(m_pSampleQueueAsyncInput->IsEmpty()) { + break; + } + IMFSample *_pSample = NULL; + hr = m_pSampleQueueAsyncInput->Dequeue(&_pSample); + if(SUCCEEDED(hr)) { + InterlockedDecrement(&m_nMETransformNeedInputCount); + hr = m_pMFT->ProcessInput(m_dwInputID, _pSample, 0); + } + SafeRelease(&_pSample); + CHECK_HR(hr); + } + } + else { + CHECK_HR(hr = m_pMFT->ProcessInput(m_dwInputID, pSample, 0)); + } bail: - return hr; + return hr; } HRESULT MFCodec::ProcessOutput(IMFSample **ppSample) { - assert(IsReady()); + assert(IsReady()); - if(m_bIsAsync) - { - if(m_nMETransformHaveOutputCount == 0) - { - return S_OK; - } - InterlockedDecrement(&m_nMETransformHaveOutputCount); - } + if(m_bIsAsync) { + if(m_nMETransformHaveOutputCount == 0) { + return S_OK; + } + InterlockedDecrement(&m_nMETransformHaveOutputCount); + } - *ppSample = NULL; + *ppSample = NULL; IMFMediaBuffer* pBufferOut = NULL; DWORD dwStatus; - HRESULT hr = S_OK; - + HRESULT hr = S_OK; + MFT_OUTPUT_STREAM_INFO mftStreamInfo = { 0 }; MFT_OUTPUT_DATA_BUFFER mftOutputData = { 0 }; - CHECK_HR(hr = m_pMFT->GetOutputStreamInfo(m_dwOutputID, &mftStreamInfo)); - - BOOL bOutputStreamProvidesSamples = (mftStreamInfo.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; - - if(!bOutputStreamProvidesSamples) - { - if(!m_pSampleOut) - { - CHECK_HR(hr = MFUtils::CreateMediaSample(mftStreamInfo.cbSize, &m_pSampleOut)); - hr = m_pSampleOut->GetBufferByIndex(0, &pBufferOut); - if(FAILED(hr)) - { - SafeRelease(&m_pSampleOut); - CHECK_HR(hr); - } - } - else - { - DWORD dwMaxLength = 0; - CHECK_HR(hr = m_pSampleOut->GetBufferByIndex(0, &pBufferOut)); - CHECK_HR(hr = pBufferOut->GetMaxLength(&dwMaxLength)); - if(dwMaxLength < mftStreamInfo.cbSize) - { - CHECK_HR(hr = m_pSampleOut->RemoveAllBuffers()); - SafeRelease(&pBufferOut); - CHECK_HR(hr = MFCreateMemoryBuffer(mftStreamInfo.cbSize, &pBufferOut)); - CHECK_HR(hr = m_pSampleOut->AddBuffer(pBufferOut)); - } - } - } - - if(pBufferOut) - { - CHECK_HR(hr = pBufferOut->SetCurrentLength(0)); - } - + CHECK_HR(hr = m_pMFT->GetOutputStreamInfo(m_dwOutputID, &mftStreamInfo)); + + BOOL bOutputStreamProvidesSamples = (mftStreamInfo.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + + if(!bOutputStreamProvidesSamples) { + if(!m_pSampleOut) { + CHECK_HR(hr = MFUtils::CreateMediaSample(mftStreamInfo.cbSize, &m_pSampleOut)); + hr = m_pSampleOut->GetBufferByIndex(0, &pBufferOut); + if(FAILED(hr)) { + SafeRelease(&m_pSampleOut); + CHECK_HR(hr); + } + } + else { + DWORD dwMaxLength = 0; + CHECK_HR(hr = m_pSampleOut->GetBufferByIndex(0, &pBufferOut)); + CHECK_HR(hr = pBufferOut->GetMaxLength(&dwMaxLength)); + if(dwMaxLength < mftStreamInfo.cbSize) { + CHECK_HR(hr = m_pSampleOut->RemoveAllBuffers()); + SafeRelease(&pBufferOut); + CHECK_HR(hr = MFCreateMemoryBuffer(mftStreamInfo.cbSize, &pBufferOut)); + CHECK_HR(hr = m_pSampleOut->AddBuffer(pBufferOut)); + } + } + } + + if(pBufferOut) { + CHECK_HR(hr = pBufferOut->SetCurrentLength(0)); + } + //Set the output sample mftOutputData.pSample = bOutputStreamProvidesSamples ? NULL : m_pSampleOut; //Set the output id @@ -428,167 +383,145 @@ HRESULT MFCodec::ProcessOutput(IMFSample **ppSample) //Generate the output sample hr = m_pMFT->ProcessOutput(0, 1, &mftOutputData, &dwStatus); - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) - { + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { hr = S_OK; goto bail; } - if (FAILED(hr)) - { + if (FAILED(hr)) { goto bail; } *ppSample = mftOutputData.pSample; - if(*ppSample) - { - (*ppSample)->AddRef(); - } + if(*ppSample) { + (*ppSample)->AddRef(); + } bail: - if(bOutputStreamProvidesSamples) - { - SafeRelease(&mftOutputData.pSample); - } + if(bOutputStreamProvidesSamples) { + SafeRelease(&mftOutputData.pSample); + } SafeRelease(&pBufferOut); return hr; } bool MFCodec::IsValid() { - return (m_pMFT && (m_eType == MFCodecType_Decoder || m_pCodecAPI)); + return (m_pMFT && (m_eType == MFCodecType_Decoder || m_pCodecAPI)); } bool MFCodec::IsReady() { - return (IsValid() && m_pOutputType && m_pInputType); + return (IsValid() && m_pOutputType && m_pInputType); } HRESULT MFCodec::Process(const void* pcInputPtr, UINT32 nInputSize, IMFSample **ppSampleOut) { - if(!pcInputPtr || !nInputSize || !ppSampleOut) - { - TSK_DEBUG_ERROR("Invalid parameter"); - return E_INVALIDARG; - } - - *ppSampleOut = NULL; - - HRESULT hr = S_OK; - - IMFMediaBuffer* pBufferIn = NULL; - BYTE* pBufferPtr = NULL; - BOOL bMediaChangeHandled = FALSE; // Endless loop guard - - if(!m_pSampleIn) - { - CHECK_HR(hr = MFUtils::CreateMediaSample(nInputSize, &m_pSampleIn)); - hr = m_pSampleIn->GetBufferByIndex(0, &pBufferIn); - if(FAILED(hr)) - { - SafeRelease(&m_pSampleIn); - CHECK_HR(hr); - } - } - else - { - DWORD dwMaxLength = 0; - CHECK_HR(hr = m_pSampleIn->GetBufferByIndex(0, &pBufferIn)); - CHECK_HR(hr = pBufferIn->GetMaxLength(&dwMaxLength)); - if(dwMaxLength < nInputSize) - { - CHECK_HR(hr = m_pSampleIn->RemoveAllBuffers()); - SafeRelease(&pBufferIn); - CHECK_HR(hr = MFCreateMemoryBuffer(nInputSize, &pBufferIn)); - CHECK_HR(hr = m_pSampleIn->AddBuffer(pBufferIn)); - } - } - - CHECK_HR(hr = pBufferIn->Lock(&pBufferPtr, NULL, NULL)); - memcpy(pBufferPtr, pcInputPtr, nInputSize); - CHECK_HR(hr = pBufferIn->Unlock()); - CHECK_HR(hr = pBufferIn->SetCurrentLength(nInputSize)); - - if(m_eType == MFCodecType_Encoder) - { - CHECK_HR(hr = m_pSampleIn->SetSampleDuration(m_rtDuration)); - CHECK_HR(hr = m_pSampleIn->SetSampleTime(m_rtStart)); // FIXME: use clock(), Same for custom source - } + if(!pcInputPtr || !nInputSize || !ppSampleOut) { + TSK_DEBUG_ERROR("Invalid parameter"); + return E_INVALIDARG; + } + + *ppSampleOut = NULL; + + HRESULT hr = S_OK; + + IMFMediaBuffer* pBufferIn = NULL; + BYTE* pBufferPtr = NULL; + BOOL bMediaChangeHandled = FALSE; // Endless loop guard + + if(!m_pSampleIn) { + CHECK_HR(hr = MFUtils::CreateMediaSample(nInputSize, &m_pSampleIn)); + hr = m_pSampleIn->GetBufferByIndex(0, &pBufferIn); + if(FAILED(hr)) { + SafeRelease(&m_pSampleIn); + CHECK_HR(hr); + } + } + else { + DWORD dwMaxLength = 0; + CHECK_HR(hr = m_pSampleIn->GetBufferByIndex(0, &pBufferIn)); + CHECK_HR(hr = pBufferIn->GetMaxLength(&dwMaxLength)); + if(dwMaxLength < nInputSize) { + CHECK_HR(hr = m_pSampleIn->RemoveAllBuffers()); + SafeRelease(&pBufferIn); + CHECK_HR(hr = MFCreateMemoryBuffer(nInputSize, &pBufferIn)); + CHECK_HR(hr = m_pSampleIn->AddBuffer(pBufferIn)); + } + } + + CHECK_HR(hr = pBufferIn->Lock(&pBufferPtr, NULL, NULL)); + memcpy(pBufferPtr, pcInputPtr, nInputSize); + CHECK_HR(hr = pBufferIn->Unlock()); + CHECK_HR(hr = pBufferIn->SetCurrentLength(nInputSize)); + + if(m_eType == MFCodecType_Encoder) { + CHECK_HR(hr = m_pSampleIn->SetSampleDuration(m_rtDuration)); + CHECK_HR(hr = m_pSampleIn->SetSampleTime(m_rtStart)); // FIXME: use clock(), Same for custom source + } Label_ProcessInput: - hr = ProcessInput(m_pSampleIn); - while(hr == MF_E_NOTACCEPTING) - { - TSK_DEBUG_INFO("MF_E_NOTACCEPTING"); - IMFSample* pSample = NULL; - hr = ProcessOutput(&pSample); - if(SUCCEEDED(hr) && pSample) - { - SafeRelease(ppSampleOut); - *ppSampleOut = pSample, pSample = NULL; - - hr = m_pSampleIn->SetUINT32(MFSampleExtension_Discontinuity, TRUE); - hr = ProcessInput(m_pSampleIn); - } - } - if(!*ppSampleOut) - { - hr = ProcessOutput(ppSampleOut); - if(hr == MF_E_TRANSFORM_STREAM_CHANGE) /* Handling Stream Changes: http://msdn.microsoft.com/en-us/library/windows/desktop/ee663587(v=vs.85).aspx */ - { - TSK_DEBUG_INFO("[MF Codec] Stream changed"); - if(m_eType == MFCodecType_Decoder) - { - IMFMediaType *pTypeOut = NULL; - hr = m_pMFT->GetOutputAvailableType(m_dwOutputID, 0, &pTypeOut); - if(SUCCEEDED(hr)) - { - UINT32 uWidth = 0, uHeight = 0; - hr = MFGetAttributeSize(pTypeOut, MF_MT_FRAME_SIZE, &uWidth, &uHeight); - if(SUCCEEDED(hr)) - { - TSK_DEBUG_INFO("[MF Decoder] New size: width=%u, height=%u", uWidth, uHeight); - hr = m_pMFT->SetOutputType(m_dwOutputID, pTypeOut, 0); - if(SUCCEEDED(hr)) - { - SafeRelease(&m_pOutputType); - pTypeOut->AddRef(); - m_pOutputType = pTypeOut; - if(m_eMediaType == MFCodecMediaType_Video) - { - dynamic_cast<MFCodecVideo*>(this)->m_nWidth = uWidth; - dynamic_cast<MFCodecVideo*>(this)->m_nHeight = uHeight; - } - } - } - } - SafeRelease(&pTypeOut); - if(SUCCEEDED(hr)) - { - if(!bMediaChangeHandled) - { - bMediaChangeHandled = TRUE; - goto Label_ProcessInput; - } - } - } - } - } - - m_rtStart += m_rtDuration; - + hr = ProcessInput(m_pSampleIn); + while(hr == MF_E_NOTACCEPTING) { + TSK_DEBUG_INFO("MF_E_NOTACCEPTING"); + IMFSample* pSample = NULL; + hr = ProcessOutput(&pSample); + if(SUCCEEDED(hr) && pSample) { + SafeRelease(ppSampleOut); + *ppSampleOut = pSample, pSample = NULL; + + hr = m_pSampleIn->SetUINT32(MFSampleExtension_Discontinuity, TRUE); + hr = ProcessInput(m_pSampleIn); + } + } + if(!*ppSampleOut) { + hr = ProcessOutput(ppSampleOut); + if(hr == MF_E_TRANSFORM_STREAM_CHANGE) { /* Handling Stream Changes: http://msdn.microsoft.com/en-us/library/windows/desktop/ee663587(v=vs.85).aspx */ + TSK_DEBUG_INFO("[MF Codec] Stream changed"); + if(m_eType == MFCodecType_Decoder) { + IMFMediaType *pTypeOut = NULL; + hr = m_pMFT->GetOutputAvailableType(m_dwOutputID, 0, &pTypeOut); + if(SUCCEEDED(hr)) { + UINT32 uWidth = 0, uHeight = 0; + hr = MFGetAttributeSize(pTypeOut, MF_MT_FRAME_SIZE, &uWidth, &uHeight); + if(SUCCEEDED(hr)) { + TSK_DEBUG_INFO("[MF Decoder] New size: width=%u, height=%u", uWidth, uHeight); + hr = m_pMFT->SetOutputType(m_dwOutputID, pTypeOut, 0); + if(SUCCEEDED(hr)) { + SafeRelease(&m_pOutputType); + pTypeOut->AddRef(); + m_pOutputType = pTypeOut; + if(m_eMediaType == MFCodecMediaType_Video) { + dynamic_cast<MFCodecVideo*>(this)->m_nWidth = uWidth; + dynamic_cast<MFCodecVideo*>(this)->m_nHeight = uHeight; + } + } + } + } + SafeRelease(&pTypeOut); + if(SUCCEEDED(hr)) { + if(!bMediaChangeHandled) { + bMediaChangeHandled = TRUE; + goto Label_ProcessInput; + } + } + } + } + } + + m_rtStart += m_rtDuration; + bail: - SafeRelease(&pBufferIn); - return hr; + SafeRelease(&pBufferIn); + return hr; } enum tmedia_chroma_e MFCodec::GetUncompressedChroma() { - if(kMFCodecUncompressedFormat == MFVideoFormat_NV12) - { - return tmedia_chroma_nv12; - } - assert(false); - return tmedia_chroma_none; + if(kMFCodecUncompressedFormat == MFVideoFormat_NV12) { + return tmedia_chroma_nv12; + } + assert(false); + return tmedia_chroma_none; } // @@ -596,12 +529,12 @@ enum tmedia_chroma_e MFCodec::GetUncompressedChroma() // MFCodecVideo::MFCodecVideo(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT /*= NULL*/) -: MFCodec(eId, eType, pMFT) -, m_nFrameRate(0) -, m_nWidth(0) -, m_nHeight(0) + : MFCodec(eId, eType, pMFT) + , m_nFrameRate(0) + , m_nWidth(0) + , m_nHeight(0) { - assert(m_eMediaType == MFCodecMediaType_Video); + assert(m_eMediaType == MFCodecMediaType_Video); } MFCodecVideo::~MFCodecVideo() @@ -610,279 +543,261 @@ MFCodecVideo::~MFCodecVideo() } HRESULT MFCodecVideo::Initialize( - UINT32 nFrameRate, - UINT32 nWidth, - UINT32 nHeight, - UINT32 nOutputBitRateInBps /*= 0*/ - ) + UINT32 nFrameRate, + UINT32 nWidth, + UINT32 nHeight, + UINT32 nOutputBitRateInBps /*= 0*/ +) { - assert(IsValid()); - - HRESULT hr = S_OK; + assert(IsValid()); - VARIANT var = {0}; + HRESULT hr = S_OK; - // make sure identifiers are zero-based (other layouts not supported yet) - hr = m_pMFT->GetStreamIDs(1, &m_dwInputID, 1, &m_dwOutputID); - if (hr == E_NOTIMPL) - { + VARIANT var = {0}; + + // make sure identifiers are zero-based (other layouts not supported yet) + hr = m_pMFT->GetStreamIDs(1, &m_dwInputID, 1, &m_dwOutputID); + if (hr == E_NOTIMPL) { m_dwInputID = 0; m_dwOutputID = 0; hr = S_OK; } - else if (FAILED(hr)) - { - TSK_DEBUG_ERROR("The stream identifiers are not zero-based"); + else if (FAILED(hr)) { + TSK_DEBUG_ERROR("The stream identifiers are not zero-based"); return hr; } - m_rtStart = 0; - CHECK_HR(hr = MFFrameRateToAverageTimePerFrame(nFrameRate, 1, &m_rtDuration)); + m_rtStart = 0; + CHECK_HR(hr = MFFrameRateToAverageTimePerFrame(nFrameRate, 1, &m_rtDuration)); + + CHECK_HR(hr = m_pOutputType->SetGUID(MF_MT_MAJOR_TYPE, (m_eMediaType == MFCodecMediaType_Video) ? MFMediaType_Video : MFMediaType_Audio)); + CHECK_HR(hr = m_pInputType->SetGUID(MF_MT_MAJOR_TYPE, (m_eMediaType == MFCodecMediaType_Video) ? MFMediaType_Video : MFMediaType_Audio)); - CHECK_HR(hr = m_pOutputType->SetGUID(MF_MT_MAJOR_TYPE, (m_eMediaType == MFCodecMediaType_Video) ? MFMediaType_Video : MFMediaType_Audio)); - CHECK_HR(hr = m_pInputType->SetGUID(MF_MT_MAJOR_TYPE, (m_eMediaType == MFCodecMediaType_Video) ? MFMediaType_Video : MFMediaType_Audio)); + CHECK_HR(hr = m_pOutputType->SetGUID(MF_MT_SUBTYPE, (m_eType == MFCodecType_Encoder) ? m_guidCompressedFormat : kMFCodecUncompressedFormat)); + CHECK_HR(hr = m_pInputType->SetGUID(MF_MT_SUBTYPE, (m_eType == MFCodecType_Encoder) ? kMFCodecUncompressedFormat : m_guidCompressedFormat)); - CHECK_HR(hr = m_pOutputType->SetGUID(MF_MT_SUBTYPE, (m_eType == MFCodecType_Encoder) ? m_guidCompressedFormat : kMFCodecUncompressedFormat)); - CHECK_HR(hr = m_pInputType->SetGUID(MF_MT_SUBTYPE, (m_eType == MFCodecType_Encoder) ? kMFCodecUncompressedFormat : m_guidCompressedFormat)); - - CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, (m_eType == MFCodecType_Encoder) ? FALSE : TRUE)); - CHECK_HR(hr = m_pInputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, (m_eType == MFCodecType_Encoder) ? TRUE : FALSE)); + CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, (m_eType == MFCodecType_Encoder) ? FALSE : TRUE)); + CHECK_HR(hr = m_pInputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, (m_eType == MFCodecType_Encoder) ? TRUE : FALSE)); + + CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, (m_eType == MFCodecType_Encoder) ? FALSE : TRUE)); + CHECK_HR(hr = m_pInputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, (m_eType == MFCodecType_Encoder) ? TRUE : FALSE)); + + // Set bitrate + // Set (MF_MT_AVG_BITRATE) for MediaType + // Set (CODECAPI_AVEncCommonMeanBitRate) for H.264 + hr = SetBitRate(nOutputBitRateInBps); - CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, (m_eType == MFCodecType_Encoder) ? FALSE : TRUE)); - CHECK_HR(hr = m_pInputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, (m_eType == MFCodecType_Encoder) ? TRUE : FALSE)); - - // Set bitrate - // Set (MF_MT_AVG_BITRATE) for MediaType - // Set (CODECAPI_AVEncCommonMeanBitRate) for H.264 - hr = SetBitRate(nOutputBitRateInBps); - CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); - CHECK_HR(hr = m_pInputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); + CHECK_HR(hr = m_pInputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); CHECK_HR(hr = MFSetAttributeSize(m_pOutputType, MF_MT_FRAME_SIZE, nWidth, nHeight)); - CHECK_HR(hr = MFSetAttributeSize(m_pInputType, MF_MT_FRAME_SIZE, nWidth, nHeight)); + CHECK_HR(hr = MFSetAttributeSize(m_pInputType, MF_MT_FRAME_SIZE, nWidth, nHeight)); CHECK_HR(hr = MFSetAttributeRatio(m_pOutputType, MF_MT_FRAME_RATE, nFrameRate, 1)); - CHECK_HR(hr = MFSetAttributeRatio(m_pInputType, MF_MT_FRAME_RATE, nFrameRate, 1)); + CHECK_HR(hr = MFSetAttributeRatio(m_pInputType, MF_MT_FRAME_RATE, nFrameRate, 1)); CHECK_HR(hr = MFSetAttributeRatio(m_pOutputType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); - CHECK_HR(hr = MFSetAttributeRatio(m_pInputType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); - - // Encoder: Output format must be set before input - // Decoder: Input format must be set before output - if(m_eType == MFCodecType_Encoder) - { - CHECK_HR(hr = m_pMFT->SetOutputType(m_dwOutputID, m_pOutputType, 0)); - CHECK_HR(hr = m_pMFT->SetInputType(m_dwInputID, m_pInputType, 0)); - } - else - { - CHECK_HR(hr = m_pMFT->SetInputType(m_dwInputID, m_pInputType, 0)); - CHECK_HR(hr = m_pMFT->SetOutputType(m_dwOutputID, m_pOutputType, 0)); - } - - if(m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main) - { - if(m_eType == MFCodecType_Decoder) - { - // Only decoder support GetAttributes() - IMFAttributes* pAttributes = NULL; - hr = m_pMFT->GetAttributes(&pAttributes); - if(SUCCEEDED(hr)) - { - // FIXME: Very strange that "CODECAPI_AVLowLatencyMode" only works with "IMFAttributes->" and not "ICodecAPI->SetValue()" - hr = pAttributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); - } - SafeRelease(&pAttributes); - } - else - { - var.vt = VT_BOOL; - var.boolVal = VARIANT_TRUE; - hr = m_pCodecAPI->SetValue(&CODECAPI_AVLowLatencyMode, &var); - - var.vt = VT_BOOL; - var.boolVal = VARIANT_TRUE; - hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncCommonLowLatency, &var); // Correct for the decoder - - // Disable B-Frames - var.vt = VT_UI4; - var.ulVal = 0; - hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncMPVDefaultBPictureCount, &var); - - // Constant bitrate (updated using RTCP) - var.vt = VT_UI4; - var.ulVal = eAVEncCommonRateControlMode_CBR; - hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); - } - - hr = S_OK; // Not mandatory features - } + CHECK_HR(hr = MFSetAttributeRatio(m_pInputType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); + + // Encoder: Output format must be set before input + // Decoder: Input format must be set before output + if(m_eType == MFCodecType_Encoder) { + CHECK_HR(hr = m_pMFT->SetOutputType(m_dwOutputID, m_pOutputType, 0)); + CHECK_HR(hr = m_pMFT->SetInputType(m_dwInputID, m_pInputType, 0)); + } + else { + CHECK_HR(hr = m_pMFT->SetInputType(m_dwInputID, m_pInputType, 0)); + CHECK_HR(hr = m_pMFT->SetOutputType(m_dwOutputID, m_pOutputType, 0)); + } + + if(m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main) { + if(m_eType == MFCodecType_Decoder) { + // Only decoder support GetAttributes() + IMFAttributes* pAttributes = NULL; + hr = m_pMFT->GetAttributes(&pAttributes); + if(SUCCEEDED(hr)) { + // FIXME: Very strange that "CODECAPI_AVLowLatencyMode" only works with "IMFAttributes->" and not "ICodecAPI->SetValue()" + hr = pAttributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); + } + SafeRelease(&pAttributes); + } + else { + var.vt = VT_BOOL; + var.boolVal = VARIANT_TRUE; + hr = m_pCodecAPI->SetValue(&CODECAPI_AVLowLatencyMode, &var); + + var.vt = VT_BOOL; + var.boolVal = VARIANT_TRUE; + hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncCommonLowLatency, &var); // Correct for the decoder + + // Disable B-Frames + var.vt = VT_UI4; + var.ulVal = 0; + hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncMPVDefaultBPictureCount, &var); + + // Constant bitrate (updated using RTCP) + var.vt = VT_UI4; + var.ulVal = eAVEncCommonRateControlMode_CBR; + hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); + } + + hr = S_OK; // Not mandatory features + } bail: - if(SUCCEEDED(hr)) - { - m_nFrameRate = nFrameRate; - m_nWidth = nWidth; - m_nHeight = nHeight; - } + if(SUCCEEDED(hr)) { + m_nFrameRate = nFrameRate; + m_nWidth = nWidth; + m_nHeight = nHeight; + } - return hr; + return hr; } HRESULT MFCodecVideo::SetGOPSize(UINT32 nFramesCount) { - assert(IsValid()); + assert(IsValid()); - HRESULT hr = S_OK; + HRESULT hr = S_OK; - if(m_eType == MFCodecType_Encoder && (m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) - { - VARIANT var = {0}; - var.vt = VT_UI4; - var.ullVal = nFramesCount; - CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncMPVGOPSize, &var)); - } + if(m_eType == MFCodecType_Encoder && (m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) { + VARIANT var = {0}; + var.vt = VT_UI4; + var.ullVal = nFramesCount; + CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncMPVGOPSize, &var)); + } bail: - return hr; + return hr; } HRESULT MFCodecVideo::SetBitRate(UINT32 nBitRateInBps) { - assert(IsValid()); + assert(IsValid()); - HRESULT hr = S_OK; + HRESULT hr = S_OK; - if(nBitRateInBps > 0 && m_eType == MFCodecType_Encoder) - { - CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_AVG_BITRATE, nBitRateInBps)); + if(nBitRateInBps > 0 && m_eType == MFCodecType_Encoder) { + CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_AVG_BITRATE, nBitRateInBps)); - if((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) - { - VARIANT var = {0}; + if((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) { + VARIANT var = {0}; - // Set BitRate - var.vt = VT_UI4; - var.ullVal = nBitRateInBps; - CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var)); - } - } + // Set BitRate + var.vt = VT_UI4; + var.ullVal = nBitRateInBps; + CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var)); + } + } bail: - return hr; + return hr; } HRESULT MFCodecVideo::IsSetSliceMaxSizeInBytesSupported(BOOL &supported) { - HRESULT hr = S_OK; - supported = FALSE; + HRESULT hr = S_OK; + supported = FALSE; - if ((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) - { + if ((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) { #if defined(CODECAPI_AVEncSliceControlMode) && defined(CODECAPI_AVEncSliceControlSize) - if (m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlMode) == S_OK && m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlSize) == S_OK) { - supported = TRUE; - } + if (m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlMode) == S_OK && m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlSize) == S_OK) { + supported = TRUE; + } #endif - } - return hr; + } + return hr; } HRESULT MFCodecVideo::SetSliceMaxSizeInBytes(UINT32 nSliceMaxSizeInBytes) { - assert(IsValid() && nSliceMaxSizeInBytes > 0); + assert(IsValid() && nSliceMaxSizeInBytes > 0); - HRESULT hr = S_OK; + HRESULT hr = S_OK; - if ((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) - { + if ((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) { #if defined(CODECAPI_AVEncSliceControlMode) && defined(CODECAPI_AVEncSliceControlSize) - if (m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlMode) == S_OK && m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlSize) == S_OK) { - VARIANT var = { 0 }; - var.vt = VT_UI4; + if (m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlMode) == S_OK && m_pCodecAPI->IsSupported(&CODECAPI_AVEncSliceControlSize) == S_OK) { + VARIANT var = { 0 }; + var.vt = VT_UI4; - var.ulVal = 1; // Bits - CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncSliceControlMode, &var)); + var.ulVal = 1; // Bits + CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncSliceControlMode, &var)); - var.ulVal = (nSliceMaxSizeInBytes << 3); // From Bytes to Bits - CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncSliceControlSize, &var)); - } + var.ulVal = (nSliceMaxSizeInBytes << 3); // From Bytes to Bits + CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncSliceControlSize, &var)); + } #else - CHECK_HR(hr = S_OK); + CHECK_HR(hr = S_OK); #endif - } + } bail: - return hr; + return hr; } HRESULT MFCodecVideo::RequestKeyFrame() { - assert(IsValid()); - - HRESULT hr = S_OK; + assert(IsValid()); + + HRESULT hr = S_OK; - if ((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) - { + if ((m_eId == MFCodecId_H264Base || m_eId == MFCodecId_H264Main)) { #if defined(CODECAPI_AVEncVideoForceKeyFrame) - if (m_pCodecAPI->IsSupported(&CODECAPI_AVEncVideoForceKeyFrame) == S_OK) { - VARIANT var = { 0 }; + if (m_pCodecAPI->IsSupported(&CODECAPI_AVEncVideoForceKeyFrame) == S_OK) { + VARIANT var = { 0 }; - var.vt = VT_UI4; - var.ulVal = 1; - CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncVideoForceKeyFrame, &var)); - } + var.vt = VT_UI4; + var.ulVal = 1; + CHECK_HR(hr = m_pCodecAPI->SetValue(&CODECAPI_AVEncVideoForceKeyFrame, &var)); + } #else - CHECK_HR(hr = S_OK); + CHECK_HR(hr = S_OK); #endif - } + } bail: - return hr; + return hr; } // // MFCodecVideo // MFCodecVideoH264::MFCodecVideoH264(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT /*= NULL*/) -: MFCodecVideo(eId, eType, pMFT) + : MFCodecVideo(eId, eType, pMFT) { - assert(eId == MFCodecId_H264Base || eId == MFCodecId_H264Main); - - HRESULT hr = S_OK; + assert(eId == MFCodecId_H264Base || eId == MFCodecId_H264Main); - if(m_pOutputType) - { - CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_MPEG2_PROFILE, (m_eId == MFCodecId_H264Base) ? eAVEncH264VProfile_Base : eAVEncH264VProfile_Main)); - } + HRESULT hr = S_OK; + + if(m_pOutputType) { + CHECK_HR(hr = m_pOutputType->SetUINT32(MF_MT_MPEG2_PROFILE, (m_eId == MFCodecId_H264Base) ? eAVEncH264VProfile_Base : eAVEncH264VProfile_Main)); + } bail: - assert(SUCCEEDED(hr)); + assert(SUCCEEDED(hr)); } MFCodecVideoH264::~MFCodecVideoH264() { - + } MFCodecVideoH264* MFCodecVideoH264::CreateCodecH264Base(MFCodecType_t eType, IMFTransform *pMFT /*= NULL*/) { - MFCodecVideoH264* pCodec = new MFCodecVideoH264(MFCodecId_H264Base, eType, pMFT); - if(pCodec && !pCodec->IsValid()) - { - SafeRelease(&pCodec); - } - return pCodec; + MFCodecVideoH264* pCodec = new MFCodecVideoH264(MFCodecId_H264Base, eType, pMFT); + if(pCodec && !pCodec->IsValid()) { + SafeRelease(&pCodec); + } + return pCodec; } MFCodecVideoH264* MFCodecVideoH264::CreateCodecH264Main(MFCodecType_t eType, IMFTransform *pMFT /*= NULL*/) { - MFCodecVideoH264* pCodec = new MFCodecVideoH264(MFCodecId_H264Main, eType, pMFT); - if(pCodec && !pCodec->IsValid()) - { - SafeRelease(&pCodec); - } - return pCodec; + MFCodecVideoH264* pCodec = new MFCodecVideoH264(MFCodecId_H264Main, eType, pMFT); + if(pCodec && !pCodec->IsValid()) { + SafeRelease(&pCodec); + } + return pCodec; } diff --git a/plugins/pluginWinMF/internals/mf_codec.h b/plugins/pluginWinMF/internals/mf_codec.h index 51b06dc..d4f00c7 100755 --- a/plugins/pluginWinMF/internals/mf_codec.h +++ b/plugins/pluginWinMF/internals/mf_codec.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -30,125 +30,136 @@ class MFSampleQueue; -typedef enum MFCodecId_e -{ - MFCodecId_H264Base, - MFCodecId_H264Main, - MFCodecId_AAC +typedef enum MFCodecId_e { + MFCodecId_H264Base, + MFCodecId_H264Main, + MFCodecId_AAC } MFCodecId_t; -typedef enum MFCodecType_e -{ - MFCodecType_Encoder, - MFCodecType_Decoder +typedef enum MFCodecType_e { + MFCodecType_Encoder, + MFCodecType_Decoder } MFCodecType_t; -typedef enum MFCodecMediaType_e -{ - MFCodecMediaType_Audio, - MFCodecMediaType_Video +typedef enum MFCodecMediaType_e { + MFCodecMediaType_Audio, + MFCodecMediaType_Video } MFCodecMediaType_t; -class MFCodec : IMFAsyncCallback +class MFCodec : IMFAsyncCallback { protected: - MFCodec(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT = NULL); - virtual ~MFCodec(); - HRESULT ProcessInput(IMFSample* pSample); - HRESULT ProcessOutput(IMFSample **ppSample); + MFCodec(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT = NULL); + virtual ~MFCodec(); + HRESULT ProcessInput(IMFSample* pSample); + HRESULT ProcessOutput(IMFSample **ppSample); public: - virtual bool IsValid(); - virtual bool IsReady(); - virtual HRESULT Process(const void* pcInputPtr, UINT32 nInputSize, IMFSample **ppSampleOut); - static enum tmedia_chroma_e GetUncompressedChroma(); - inline IMFTransform* GetMFT(){ return m_pMFT; } - inline MFCodecId_t GetId() { return m_eId; } - inline MFCodecType_t GetType() { return m_eType; } - inline void setBundled(BOOL bBundled) { m_bIsBundled = bBundled; } - - // IUnknown + virtual bool IsValid(); + virtual bool IsReady(); + virtual HRESULT Process(const void* pcInputPtr, UINT32 nInputSize, IMFSample **ppSampleOut); + static enum tmedia_chroma_e GetUncompressedChroma(); + inline IMFTransform* GetMFT() { + return m_pMFT; + } + inline MFCodecId_t GetId() { + return m_eId; + } + inline MFCodecType_t GetType() { + return m_eType; + } + inline void setBundled(BOOL bBundled) { + m_bIsBundled = bBundled; + } + + // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); - // IMFAsyncCallback - STDMETHODIMP GetParameters(DWORD *pdwFlags, DWORD *pdwQueue); - STDMETHODIMP Invoke(IMFAsyncResult *pAsyncResult); + // IMFAsyncCallback + STDMETHODIMP GetParameters(DWORD *pdwFlags, DWORD *pdwQueue); + STDMETHODIMP Invoke(IMFAsyncResult *pAsyncResult); private: - long m_nRefCount; + long m_nRefCount; protected: - MFCodecId_t m_eId; // Codec Id - MFCodecType_t m_eType; // Codec type. - MFCodecMediaType_t m_eMediaType; // Codec Media type. - DWORD m_dwInputID; // Input stream ID. + MFCodecId_t m_eId; // Codec Id + MFCodecType_t m_eType; // Codec type. + MFCodecMediaType_t m_eMediaType; // Codec Media type. + DWORD m_dwInputID; // Input stream ID. DWORD m_dwOutputID; // Output stream ID. - GUID m_guidCompressedFormat; // Compressed Media format (e.g. MFVideoFormat_H264) + GUID m_guidCompressedFormat; // Compressed Media format (e.g. MFVideoFormat_H264) IMFTransform *m_pMFT; // Pointer to the encoder MFT. - ICodecAPI *m_pCodecAPI; // Pointer to CodecAPI. + ICodecAPI *m_pCodecAPI; // Pointer to CodecAPI. IMFMediaType *m_pOutputType; // Output media type of the codec. - IMFMediaType *m_pInputType; // Input media type of the codec. + IMFMediaType *m_pInputType; // Input media type of the codec. - LONGLONG m_rtStart; + LONGLONG m_rtStart; UINT64 m_rtDuration; - IMFSample *m_pSampleIn; - IMFSample *m_pSampleOut; + IMFSample *m_pSampleIn; + IMFSample *m_pSampleOut; - MFSampleQueue *m_pSampleQueueAsyncInput; - BOOL m_bIsBundled; // Bundled with a producer or cosumer -> do not monitor events - BOOL m_bIsAsync; - IMFMediaEventGenerator *m_pEventGenerator; - BOOL m_bIsFirstFrame; - long m_nMETransformNeedInputCount, m_nMETransformHaveOutputCount; + MFSampleQueue *m_pSampleQueueAsyncInput; + BOOL m_bIsBundled; // Bundled with a producer or cosumer -> do not monitor events + BOOL m_bIsAsync; + IMFMediaEventGenerator *m_pEventGenerator; + BOOL m_bIsFirstFrame; + long m_nMETransformNeedInputCount, m_nMETransformHaveOutputCount; }; class MFCodecVideo : public MFCodec { - friend class MFCodec; + friend class MFCodec; protected: - MFCodecVideo(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT = NULL); - virtual ~MFCodecVideo(); + MFCodecVideo(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT = NULL); + virtual ~MFCodecVideo(); public: - virtual HRESULT Initialize( - UINT32 nFrameRate, - UINT32 nWidth, - UINT32 nHeight, - UINT32 nOutputBitRateInBps = 0 // Only for encoders - ); - virtual HRESULT SetGOPSize(UINT32 nFramesCount); - virtual HRESULT SetBitRate(UINT32 nBitRateInBps); - virtual HRESULT SetSliceMaxSizeInBytes(UINT32 nSliceMaxSizeInBytes); - virtual HRESULT RequestKeyFrame(); - - virtual HRESULT IsSetSliceMaxSizeInBytesSupported(BOOL &supported); - virtual inline UINT32 GetFrameRate() { return m_nFrameRate; } - virtual inline UINT32 GetWidth() { return m_nWidth; } - virtual inline UINT32 GetHeight() { return m_nHeight; } + virtual HRESULT Initialize( + UINT32 nFrameRate, + UINT32 nWidth, + UINT32 nHeight, + UINT32 nOutputBitRateInBps = 0 // Only for encoders + ); + virtual HRESULT SetGOPSize(UINT32 nFramesCount); + virtual HRESULT SetBitRate(UINT32 nBitRateInBps); + virtual HRESULT SetSliceMaxSizeInBytes(UINT32 nSliceMaxSizeInBytes); + virtual HRESULT RequestKeyFrame(); + + virtual HRESULT IsSetSliceMaxSizeInBytesSupported(BOOL &supported); + virtual inline UINT32 GetFrameRate() { + return m_nFrameRate; + } + virtual inline UINT32 GetWidth() { + return m_nWidth; + } + virtual inline UINT32 GetHeight() { + return m_nHeight; + } protected: - UINT32 m_nFrameRate; - UINT32 m_nWidth; - UINT32 m_nHeight; + UINT32 m_nFrameRate; + UINT32 m_nWidth; + UINT32 m_nHeight; }; class MFCodecVideoH264 : public MFCodecVideo { protected: - MFCodecVideoH264(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT = NULL); + MFCodecVideoH264(MFCodecId_t eId, MFCodecType_t eType, IMFTransform *pMFT = NULL); public: - virtual ~MFCodecVideoH264(); - static MFCodecVideoH264* CreateCodecH264Base(MFCodecType_t eType, IMFTransform *pMFT = NULL); - static MFCodecVideoH264* CreateCodecH264Main(MFCodecType_t eType, IMFTransform *pMFT = NULL); + virtual ~MFCodecVideoH264(); + static MFCodecVideoH264* CreateCodecH264Base(MFCodecType_t eType, IMFTransform *pMFT = NULL); + static MFCodecVideoH264* CreateCodecH264Main(MFCodecType_t eType, IMFTransform *pMFT = NULL); protected: diff --git a/plugins/pluginWinMF/internals/mf_codec_topology.cxx b/plugins/pluginWinMF/internals/mf_codec_topology.cxx index 1ee2a16..1f63466 100755 --- a/plugins/pluginWinMF/internals/mf_codec_topology.cxx +++ b/plugins/pluginWinMF/internals/mf_codec_topology.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -25,134 +25,117 @@ // MFCodecTopologySampleGrabberCB // -class MFCodecTopologySampleGrabberCB : public IMFSampleGrabberSinkCallback +class MFCodecTopologySampleGrabberCB : public IMFSampleGrabberSinkCallback { long m_cRef; MFCodecTopology *m_pCodecTopology; MFCodecTopologySampleGrabberCB(MFCodecTopology *pCodecTopology) - : m_cRef(1) - { - m_pCodecTopology = pCodecTopology; - m_pCodecTopology->AddRef(); - } - virtual ~MFCodecTopologySampleGrabberCB() - { - SafeRelease(&m_pCodecTopology); - } + : m_cRef(1) { + m_pCodecTopology = pCodecTopology; + m_pCodecTopology->AddRef(); + } + virtual ~MFCodecTopologySampleGrabberCB() { + SafeRelease(&m_pCodecTopology); + } public: // Create a new instance of the object. - static HRESULT MFCodecTopologySampleGrabberCB::CreateInstance(MFCodecTopology *pCodecTopology, MFCodecTopologySampleGrabberCB **ppCB) - { - *ppCB = new (std::nothrow) MFCodecTopologySampleGrabberCB(pCodecTopology); - - if (ppCB == NULL) - { - return E_OUTOFMEMORY; - } - return S_OK; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::QueryInterface(REFIID riid, void** ppv) - { - static const QITAB qit[] = - { - QITABENT(MFCodecTopologySampleGrabberCB, IMFSampleGrabberSinkCallback), - QITABENT(MFCodecTopologySampleGrabberCB, IMFClockStateSink), - { 0 } - }; - return QISearch(this, qit, riid, ppv); - } - - STDMETHODIMP_(ULONG) MFCodecTopologySampleGrabberCB::AddRef() - { - return InterlockedIncrement(&m_cRef); - } - - STDMETHODIMP_(ULONG) MFCodecTopologySampleGrabberCB::Release() - { - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - { - delete this; - } - return cRef; - - } - - // IMFClockStateSink methods - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockStart(%lld, %lld)", hnsSystemTime, llClockStartOffset); - return S_OK; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockStop(MFTIME hnsSystemTime) - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockStop(%lld)", hnsSystemTime); - return S_OK; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockPause(MFTIME hnsSystemTime) - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockPause(%lld)", hnsSystemTime); - return S_OK; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockRestart(MFTIME hnsSystemTime) - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockRestart(%lld)", hnsSystemTime); - return S_OK; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockSetRate(MFTIME hnsSystemTime, float flRate) - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockSetRate(%lld, %f)", hnsSystemTime, flRate); - return S_OK; - } - - // IMFSampleGrabberSink methods. - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnSetPresentationClock(IMFPresentationClock* pClock) - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnSetPresentationClock"); - return S_OK; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnProcessSample( - REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize) - { - HRESULT hr = S_OK; - IMFSample *pSample = NULL; - IMFMediaBuffer* pMediaBuffer = NULL; - BYTE* _pcBufferPtr = NULL; - - CHECK_HR(hr = MFUtils::CreateMediaSample(dwSampleSize, &pSample)); - CHECK_HR(hr = pSample->SetSampleTime(llSampleTime)); - CHECK_HR(hr = pSample->SetSampleDuration(llSampleDuration)); - CHECK_HR(hr = pSample->GetBufferByIndex(0, &pMediaBuffer)); - CHECK_HR(hr = pMediaBuffer->Lock(&_pcBufferPtr, NULL, NULL)); - memcpy(_pcBufferPtr, pSampleBuffer, dwSampleSize); - CHECK_HR(hr = pMediaBuffer->SetCurrentLength(dwSampleSize)); - CHECK_HR(hr = pMediaBuffer->Unlock()); - - m_pCodecTopology->m_SampleQueue.Queue(pSample); // thread-safe - + static HRESULT MFCodecTopologySampleGrabberCB::CreateInstance(MFCodecTopology *pCodecTopology, MFCodecTopologySampleGrabberCB **ppCB) { + *ppCB = new (std::nothrow) MFCodecTopologySampleGrabberCB(pCodecTopology); + + if (ppCB == NULL) { + return E_OUTOFMEMORY; + } + return S_OK; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::QueryInterface(REFIID riid, void** ppv) { + static const QITAB qit[] = { + QITABENT(MFCodecTopologySampleGrabberCB, IMFSampleGrabberSinkCallback), + QITABENT(MFCodecTopologySampleGrabberCB, IMFClockStateSink), + { 0 } + }; + return QISearch(this, qit, riid, ppv); + } + + STDMETHODIMP_(ULONG) MFCodecTopologySampleGrabberCB::AddRef() { + return InterlockedIncrement(&m_cRef); + } + + STDMETHODIMP_(ULONG) MFCodecTopologySampleGrabberCB::Release() { + ULONG cRef = InterlockedDecrement(&m_cRef); + if (cRef == 0) { + delete this; + } + return cRef; + + } + + // IMFClockStateSink methods + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockStart(%lld, %lld)", hnsSystemTime, llClockStartOffset); + return S_OK; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockStop(MFTIME hnsSystemTime) { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockStop(%lld)", hnsSystemTime); + return S_OK; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockPause(MFTIME hnsSystemTime) { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockPause(%lld)", hnsSystemTime); + return S_OK; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockRestart(MFTIME hnsSystemTime) { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockRestart(%lld)", hnsSystemTime); + return S_OK; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnClockSetRate(MFTIME hnsSystemTime, float flRate) { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnClockSetRate(%lld, %f)", hnsSystemTime, flRate); + return S_OK; + } + + // IMFSampleGrabberSink methods. + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnSetPresentationClock(IMFPresentationClock* pClock) { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnSetPresentationClock"); + return S_OK; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnProcessSample( + REFGUID guidMajorMediaType, DWORD dwSampleFlags, + LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, + DWORD dwSampleSize) { + HRESULT hr = S_OK; + IMFSample *pSample = NULL; + IMFMediaBuffer* pMediaBuffer = NULL; + BYTE* _pcBufferPtr = NULL; + + CHECK_HR(hr = MFUtils::CreateMediaSample(dwSampleSize, &pSample)); + CHECK_HR(hr = pSample->SetSampleTime(llSampleTime)); + CHECK_HR(hr = pSample->SetSampleDuration(llSampleDuration)); + CHECK_HR(hr = pSample->GetBufferByIndex(0, &pMediaBuffer)); + CHECK_HR(hr = pMediaBuffer->Lock(&_pcBufferPtr, NULL, NULL)); + memcpy(_pcBufferPtr, pSampleBuffer, dwSampleSize); + CHECK_HR(hr = pMediaBuffer->SetCurrentLength(dwSampleSize)); + CHECK_HR(hr = pMediaBuffer->Unlock()); + + m_pCodecTopology->m_SampleQueue.Queue(pSample); // thread-safe + bail: - SafeRelease(&pSample); - SafeRelease(&pMediaBuffer); - return hr; - } - - STDMETHODIMP MFCodecTopologySampleGrabberCB::OnShutdown() - { - TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnShutdown"); - return S_OK; - } + SafeRelease(&pSample); + SafeRelease(&pMediaBuffer); + return hr; + } + + STDMETHODIMP MFCodecTopologySampleGrabberCB::OnShutdown() { + TSK_DEBUG_INFO("MFCodecTopologySampleGrabberCB::OnShutdown"); + return S_OK; + } }; // @@ -161,36 +144,36 @@ bail: MFCodecTopology::MFCodecTopology(MFCodec* pCodec, HRESULT &hr) -: m_nRefCount(1) -, m_bInitialized(FALSE) -, m_bStarted(FALSE) -, m_pCodec(NULL) -, m_pSource(NULL) -, m_pSession(NULL) -, m_pTopologyFull(NULL) -, m_pTopologyPartial(NULL) -, m_pOutputType(NULL) -, m_pInputType(NULL) -, m_pGrabberCallback(NULL) -, m_pGrabberActivate(NULL) -, m_pTread(NULL) + : m_nRefCount(1) + , m_bInitialized(FALSE) + , m_bStarted(FALSE) + , m_pCodec(NULL) + , m_pSource(NULL) + , m_pSession(NULL) + , m_pTopologyFull(NULL) + , m_pTopologyPartial(NULL) + , m_pOutputType(NULL) + , m_pInputType(NULL) + , m_pGrabberCallback(NULL) + , m_pGrabberActivate(NULL) + , m_pTread(NULL) { - hr = S_OK; + hr = S_OK; - if(!pCodec) - { - CHECK_HR(hr = E_POINTER); - } + if(!pCodec) { + CHECK_HR(hr = E_POINTER); + } - m_pCodec = pCodec; - m_pCodec->AddRef(); + m_pCodec = pCodec; + m_pCodec->AddRef(); -bail: ; +bail: + ; } MFCodecTopology::~MFCodecTopology() { - DeInitialize(); + DeInitialize(); } ULONG MFCodecTopology::AddRef() @@ -201,8 +184,7 @@ ULONG MFCodecTopology::AddRef() ULONG MFCodecTopology::Release() { ULONG uCount = InterlockedDecrement(&m_nRefCount); - if (uCount == 0) - { + if (uCount == 0) { delete this; } // For thread safety, return a temporary variable. @@ -211,245 +193,226 @@ ULONG MFCodecTopology::Release() HRESULT MFCodecTopology::QueryInterface(REFIID iid, void** ppv) { - return E_NOTIMPL; + return E_NOTIMPL; } HRESULT MFCodecTopology::Start() { - HRESULT hr = S_OK; - - if(m_bStarted) - { - return S_OK; - } - - if(!m_bInitialized) - { - CHECK_HR(hr = E_FAIL); - } - - CHECK_HR(hr = MFUtils::RunSession(m_pSession, m_pTopologyFull)); - - // Start asynchronous watcher thread - m_bStarted = TRUE; - int ret = tsk_thread_create(&m_pTread, MFCodecTopology::RunSessionThread, this); - if(ret != 0) - { - TSK_DEBUG_ERROR("Failed to create thread"); - m_bStarted = FALSE; - if(m_pTread) - { - tsk_thread_join(&m_pTread); - } - MFUtils::ShutdownSession(m_pSession, m_pSource); - CHECK_HR(hr = E_FAIL); - } - - // FIXME - Sleep(2000); + HRESULT hr = S_OK; + + if(m_bStarted) { + return S_OK; + } + + if(!m_bInitialized) { + CHECK_HR(hr = E_FAIL); + } + + CHECK_HR(hr = MFUtils::RunSession(m_pSession, m_pTopologyFull)); + + // Start asynchronous watcher thread + m_bStarted = TRUE; + int ret = tsk_thread_create(&m_pTread, MFCodecTopology::RunSessionThread, this); + if(ret != 0) { + TSK_DEBUG_ERROR("Failed to create thread"); + m_bStarted = FALSE; + if(m_pTread) { + tsk_thread_join(&m_pTread); + } + MFUtils::ShutdownSession(m_pSession, m_pSource); + CHECK_HR(hr = E_FAIL); + } + + // FIXME + Sleep(2000); bail: - return hr; + return hr; } HRESULT MFCodecTopology::Stop() { - HRESULT hr = S_OK; + HRESULT hr = S_OK; - if(!m_bStarted) - { - return S_OK; - } + if(!m_bStarted) { + return S_OK; + } - m_bStarted = FALSE; + m_bStarted = FALSE; hr = MFUtils::ShutdownSession(m_pSession, NULL); // stop session to wakeup the asynchronous thread - if(m_pTread) - { + if(m_pTread) { tsk_thread_join(&m_pTread); } hr = MFUtils::ShutdownSession(NULL, m_pSource); - - return hr; + + return hr; } HRESULT MFCodecTopology::Initialize() { - HRESULT hr = S_OK; - IMFAttributes* pSessionAttributes = NULL; + HRESULT hr = S_OK; + IMFAttributes* pSessionAttributes = NULL; - if(m_bInitialized) - { - CHECK_HR(hr = E_FAIL); - } + if(m_bInitialized) { + CHECK_HR(hr = E_FAIL); + } - // Set session attributes - CHECK_HR(hr = MFCreateAttributes(&pSessionAttributes, 1)); - CHECK_HR(hr = pSessionAttributes->SetUINT32(PLUGIN_MF_LOW_LATENCY, 1)); + // Set session attributes + CHECK_HR(hr = MFCreateAttributes(&pSessionAttributes, 1)); + CHECK_HR(hr = pSessionAttributes->SetUINT32(PLUGIN_MF_LOW_LATENCY, 1)); - // Get input and output type - CHECK_HR(hr = m_pCodec->GetInputType(&m_pInputType)); - CHECK_HR(hr = m_pCodec->GetOutputType(&m_pOutputType)); + // Get input and output type + CHECK_HR(hr = m_pCodec->GetInputType(&m_pInputType)); + CHECK_HR(hr = m_pCodec->GetOutputType(&m_pOutputType)); - // Create custom source - CHECK_HR(hr = CMFSource::CreateInstanceEx(IID_IMFMediaSource, (void**)&m_pSource, m_pInputType)); + // Create custom source + CHECK_HR(hr = CMFSource::CreateInstanceEx(IID_IMFMediaSource, (void**)&m_pSource, m_pInputType)); - // Create the sample grabber sink. - CHECK_HR(hr = MFCodecTopologySampleGrabberCB::CreateInstance(this, &m_pGrabberCallback)); - CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(m_pOutputType, m_pGrabberCallback, &m_pGrabberActivate)); + // Create the sample grabber sink. + CHECK_HR(hr = MFCodecTopologySampleGrabberCB::CreateInstance(this, &m_pGrabberCallback)); + CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(m_pOutputType, m_pGrabberCallback, &m_pGrabberActivate)); - // To run as fast as possible, set this attribute (requires Windows 7 or later): - CHECK_HR(hr = m_pGrabberActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE)); + // To run as fast as possible, set this attribute (requires Windows 7 or later): + CHECK_HR(hr = m_pGrabberActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE)); - // Create the Media Session. - CHECK_HR(hr = MFCreateMediaSession(pSessionAttributes, &m_pSession)); + // Create the Media Session. + CHECK_HR(hr = MFCreateMediaSession(pSessionAttributes, &m_pSession)); - // Create the topology. - CHECK_HR(hr = MFUtils::CreateTopology( - m_pSource, - m_pCodec->GetMFT(), - m_pGrabberActivate, - NULL, // no preview - m_pOutputType, - &m_pTopologyPartial)); - // Resolve topology (adds video processors if needed). - CHECK_HR(hr = MFUtils::ResolveTopology(m_pTopologyPartial, &m_pTopologyFull)); + // Create the topology. + CHECK_HR(hr = MFUtils::CreateTopology( + m_pSource, + m_pCodec->GetMFT(), + m_pGrabberActivate, + NULL, // no preview + m_pOutputType, + &m_pTopologyPartial)); + // Resolve topology (adds video processors if needed). + CHECK_HR(hr = MFUtils::ResolveTopology(m_pTopologyPartial, &m_pTopologyFull)); - m_bInitialized = TRUE; + m_bInitialized = TRUE; bail: - SafeRelease(&pSessionAttributes); + SafeRelease(&pSessionAttributes); - if(FAILED(hr)) - { - DeInitialize(); - } + if(FAILED(hr)) { + DeInitialize(); + } - return hr; + return hr; } void* TSK_STDCALL MFCodecTopology::RunSessionThread(void *pArg) { - MFCodecTopology *pSelf = (MFCodecTopology *)pArg; - HRESULT hrStatus = S_OK; - HRESULT hr = S_OK; - IMFMediaEvent *pEvent = NULL; - MediaEventType met; - - TSK_DEBUG_INFO("RunSessionThread (MFCodecTopology) - ENTER"); - - while(pSelf->isStarted()) - { - CHECK_HR(hr = pSelf->m_pSession->GetEvent(0, &pEvent)); - CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); - CHECK_HR(hr = pEvent->GetType(&met)); - - if (FAILED(hrStatus) /*&& hrStatus != MF_E_NO_SAMPLE_TIMESTAMP*/) - { - TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met); - hr = hrStatus; - goto bail; - } - if (met == MESessionEnded) - { - break; - } - SafeRelease(&pEvent); - } + MFCodecTopology *pSelf = (MFCodecTopology *)pArg; + HRESULT hrStatus = S_OK; + HRESULT hr = S_OK; + IMFMediaEvent *pEvent = NULL; + MediaEventType met; + + TSK_DEBUG_INFO("RunSessionThread (MFCodecTopology) - ENTER"); + + while(pSelf->isStarted()) { + CHECK_HR(hr = pSelf->m_pSession->GetEvent(0, &pEvent)); + CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); + CHECK_HR(hr = pEvent->GetType(&met)); + + if (FAILED(hrStatus) /*&& hrStatus != MF_E_NO_SAMPLE_TIMESTAMP*/) { + TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met); + hr = hrStatus; + goto bail; + } + if (met == MESessionEnded) { + break; + } + SafeRelease(&pEvent); + } bail: - TSK_DEBUG_INFO("RunSessionThread (MFCodecTopology) - EXIT"); + TSK_DEBUG_INFO("RunSessionThread (MFCodecTopology) - EXIT"); - return NULL; + return NULL; } HRESULT MFCodecTopology::DeInitialize() { - Stop(); - - SafeRelease(&m_pCodec); - SafeRelease(&m_pSource); - SafeRelease(&m_pCodec); - SafeRelease(&m_pSession); - SafeRelease(&m_pTopologyFull); - SafeRelease(&m_pTopologyPartial); - SafeRelease(&m_pOutputType); - SafeRelease(&m_pInputType); - SafeRelease(&m_pGrabberCallback); - SafeRelease(&m_pGrabberActivate); - - if(m_pTread) - { - tsk_thread_join(&m_pTread); - } + Stop(); + + SafeRelease(&m_pCodec); + SafeRelease(&m_pSource); + SafeRelease(&m_pCodec); + SafeRelease(&m_pSession); + SafeRelease(&m_pTopologyFull); + SafeRelease(&m_pTopologyPartial); + SafeRelease(&m_pOutputType); + SafeRelease(&m_pInputType); + SafeRelease(&m_pGrabberCallback); + SafeRelease(&m_pGrabberActivate); + + if(m_pTread) { + tsk_thread_join(&m_pTread); + } - m_SampleQueue.Clear(); + m_SampleQueue.Clear(); - m_bInitialized = FALSE; + m_bInitialized = FALSE; - return S_OK; + return S_OK; } HRESULT MFCodecTopology::ProcessInput(IMFSample* pSample) { - HRESULT hr = S_OK; - IMFMediaBuffer* pMediaBuffer = NULL; - BYTE* _pcBufferPtr = NULL; - - if(!pSample) - { - CHECK_HR(hr = E_POINTER); - } - - if(m_pCodec->GetMediaType() != MFCodecMediaType_Video) - { - CHECK_HR(hr = E_NOTIMPL); - } - - if(!m_bStarted) - { - CHECK_HR(hr = Start()); - } - - CHECK_HR(hr = pSample->GetBufferByIndex(0, &pMediaBuffer)); - - DWORD dwDataLength = 0; - BOOL bLocked = FALSE; - CHECK_HR(hr = pMediaBuffer->GetCurrentLength(&dwDataLength)); - bLocked = TRUE; - if(dwDataLength > 0) - { - CHECK_HR(hr = pMediaBuffer->Lock(&_pcBufferPtr, NULL, NULL)); - CHECK_HR(hr = m_pSource->CopyVideoBuffer( - dynamic_cast<MFCodecVideo*>(m_pCodec)->GetWidth(), - dynamic_cast<MFCodecVideo*>(m_pCodec)->GetHeight(), - _pcBufferPtr, dwDataLength)); - } + HRESULT hr = S_OK; + IMFMediaBuffer* pMediaBuffer = NULL; + BYTE* _pcBufferPtr = NULL; + + if(!pSample) { + CHECK_HR(hr = E_POINTER); + } + + if(m_pCodec->GetMediaType() != MFCodecMediaType_Video) { + CHECK_HR(hr = E_NOTIMPL); + } + + if(!m_bStarted) { + CHECK_HR(hr = Start()); + } + + CHECK_HR(hr = pSample->GetBufferByIndex(0, &pMediaBuffer)); + + DWORD dwDataLength = 0; + BOOL bLocked = FALSE; + CHECK_HR(hr = pMediaBuffer->GetCurrentLength(&dwDataLength)); + bLocked = TRUE; + if(dwDataLength > 0) { + CHECK_HR(hr = pMediaBuffer->Lock(&_pcBufferPtr, NULL, NULL)); + CHECK_HR(hr = m_pSource->CopyVideoBuffer( + dynamic_cast<MFCodecVideo*>(m_pCodec)->GetWidth(), + dynamic_cast<MFCodecVideo*>(m_pCodec)->GetHeight(), + _pcBufferPtr, dwDataLength)); + } bail: - if(bLocked) - { - pMediaBuffer->Unlock(); - } - SafeRelease(&pMediaBuffer); - return hr; + if(bLocked) { + pMediaBuffer->Unlock(); + } + SafeRelease(&pMediaBuffer); + return hr; } HRESULT MFCodecTopology::ProcessOutput(IMFSample **ppSample) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; - if(!ppSample) - { - CHECK_HR(hr = E_POINTER); - } + if(!ppSample) { + CHECK_HR(hr = E_POINTER); + } - if(!m_SampleQueue.IsEmpty()) - { - CHECK_HR(hr = m_SampleQueue.Dequeue(ppSample)); // thread-safe - } + if(!m_SampleQueue.IsEmpty()) { + CHECK_HR(hr = m_SampleQueue.Dequeue(ppSample)); // thread-safe + } bail: - return hr; + return hr; } // @@ -458,11 +421,11 @@ bail: MFCodecVideoTopology::MFCodecVideoTopology(MFCodec* pCodec, HRESULT &hr) -: MFCodecTopology(pCodec, hr) -, m_nWidth(0) -, m_nHeight(0) + : MFCodecTopology(pCodec, hr) + , m_nWidth(0) + , m_nHeight(0) { - assert(pCodec->GetMediaType() == MFCodecMediaType_Video); + assert(pCodec->GetMediaType() == MFCodecMediaType_Video); } MFCodecVideoTopology::~MFCodecVideoTopology() diff --git a/plugins/pluginWinMF/internals/mf_codec_topology.h b/plugins/pluginWinMF/internals/mf_codec_topology.h index c5d2f34..6a4bb94 100755 --- a/plugins/pluginWinMF/internals/mf_codec_topology.h +++ b/plugins/pluginWinMF/internals/mf_codec_topology.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -28,59 +28,63 @@ class MFCodecTopologySampleGrabberCB; class MFCodecTopology : IUnknown { - friend class MFCodecTopologySampleGrabberCB; + friend class MFCodecTopologySampleGrabberCB; public: - MFCodecTopology(MFCodec* pCodec, HRESULT &hr); - virtual ~MFCodecTopology(); + MFCodecTopology(MFCodec* pCodec, HRESULT &hr); + virtual ~MFCodecTopology(); - virtual HRESULT Initialize(); - virtual HRESULT DeInitialize(); + virtual HRESULT Initialize(); + virtual HRESULT DeInitialize(); - virtual HRESULT ProcessInput(IMFSample* pSample); - virtual HRESULT ProcessOutput(IMFSample **ppSample); + virtual HRESULT ProcessInput(IMFSample* pSample); + virtual HRESULT ProcessOutput(IMFSample **ppSample); - // IUnknown + // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); - inline BOOL isStarted() { return m_bStarted; } - inline BOOL isInitialized() { return m_bInitialized; } + inline BOOL isStarted() { + return m_bStarted; + } + inline BOOL isInitialized() { + return m_bInitialized; + } private: - static void* TSK_STDCALL RunSessionThread(void *pArg); + static void* TSK_STDCALL RunSessionThread(void *pArg); protected: - HRESULT Start(); - HRESULT Stop(); + HRESULT Start(); + HRESULT Stop(); private: - long m_nRefCount; + long m_nRefCount; protected: - BOOL m_bInitialized; - BOOL m_bStarted; - MFCodec* m_pCodec; - CMFSource *m_pSource; - IMFMediaSession *m_pSession; + BOOL m_bInitialized; + BOOL m_bStarted; + MFCodec* m_pCodec; + CMFSource *m_pSource; + IMFMediaSession *m_pSession; IMFTopology *m_pTopologyFull; - IMFTopology *m_pTopologyPartial; - IMFMediaType *m_pOutputType; - IMFMediaType *m_pInputType; - MFCodecTopologySampleGrabberCB *m_pGrabberCallback; + IMFTopology *m_pTopologyPartial; + IMFMediaType *m_pOutputType; + IMFMediaType *m_pInputType; + MFCodecTopologySampleGrabberCB *m_pGrabberCallback; IMFActivate *m_pGrabberActivate; - tsk_thread_handle_t* m_pTread; - SampleQueue m_SampleQueue; + tsk_thread_handle_t* m_pTread; + SampleQueue m_SampleQueue; }; class MFCodecVideoTopology : public MFCodecTopology { public: - MFCodecVideoTopology(MFCodec* pCodec, HRESULT &hr); - virtual ~MFCodecVideoTopology(); + MFCodecVideoTopology(MFCodec* pCodec, HRESULT &hr); + virtual ~MFCodecVideoTopology(); private: - UINT32 m_nWidth, m_nHeight; + UINT32 m_nWidth, m_nHeight; }; diff --git a/plugins/pluginWinMF/internals/mf_custom_src.cxx b/plugins/pluginWinMF/internals/mf_custom_src.cxx index 1de9904..186887e 100755 --- a/plugins/pluginWinMF/internals/mf_custom_src.cxx +++ b/plugins/pluginWinMF/internals/mf_custom_src.cxx @@ -1,20 +1,20 @@ -/* +/* * Copyright (C) Microsoft Corporation. All rights reserved. * Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -63,7 +63,7 @@ LONGLONG BufferSizeFromAudioDuration(const WAVEFORMATEX *pWav, LONGLONG duration HRESULT CMFSource_CreateInstance(REFIID iid, void **ppMFT) { - return CMFSource::CreateInstance(iid, ppMFT); + return CMFSource::CreateInstance(iid, ppMFT); } @@ -77,30 +77,26 @@ HRESULT CMFSource_CreateInstance(REFIID iid, void **ppMFT) HRESULT CMFSource::CreateInstance(REFIID iid, void **ppSource) // Called when source used as plugin { - return CreateInstanceEx(iid, ppSource, NULL); + return CreateInstanceEx(iid, ppSource, NULL); } HRESULT CMFSource::CreateInstanceEx(REFIID iid, void **ppSource, IMFMediaType *pMediaType) // Called when source directly called { - if (ppSource == NULL) - { + if (ppSource == NULL) { return E_POINTER; } HRESULT hr = S_OK; CMFSource *pSource = new (std::nothrow) CMFSource(hr, pMediaType); // Created with ref count = 1. - if (pSource == NULL) - { + if (pSource == NULL) { return E_OUTOFMEMORY; } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pSource->QueryInterface(iid, ppSource); - if(SUCCEEDED(hr)) - { - ((CMFSource*)(*ppSource))->AddRef(); - } + if(SUCCEEDED(hr)) { + ((CMFSource*)(*ppSource))->AddRef(); + } } SafeRelease(&pSource); @@ -115,22 +111,21 @@ HRESULT CMFSource::CreateInstanceEx(REFIID iid, void **ppSource, IMFMediaType *p //------------------------------------------------------------------- CMFSource::CMFSource(HRESULT& hr, IMFMediaType *pMediaType) - : m_nRefCount(1), - m_pEventQueue(NULL), - m_pPresentationDescriptor(NULL), - m_IsShutdown(FALSE), - m_state(STATE_STOPPED), - m_pStream(NULL), - m_pMediaType(NULL) + : m_nRefCount(1), + m_pEventQueue(NULL), + m_pPresentationDescriptor(NULL), + m_IsShutdown(FALSE), + m_state(STATE_STOPPED), + m_pStream(NULL), + m_pMediaType(NULL) { // Create the media event queue. hr = MFCreateEventQueue(&m_pEventQueue); - if(pMediaType) - { - m_pMediaType = pMediaType; - pMediaType->AddRef(); - } + if(pMediaType) { + m_pMediaType = pMediaType; + pMediaType->AddRef(); + } InitializeCriticalSection(&m_critSec); } @@ -145,7 +140,7 @@ CMFSource::~CMFSource() { assert(m_IsShutdown); assert(m_nRefCount == 0); - SafeRelease(&m_pMediaType); + SafeRelease(&m_pMediaType); DeleteCriticalSection(&m_critSec); } @@ -154,26 +149,22 @@ CMFSource::~CMFSource() HRESULT CMFSource::CopyVideoBuffer(UINT32 nWidth, UINT32 nHeight, const void* pBufferPtr, UINT32 nBufferSize) { - if(!pBufferPtr) - { - TSK_DEBUG_ERROR("Invalid buffer pointer"); - return E_POINTER; - } - - if(!nWidth || !nHeight || !nBufferSize) - { - TSK_DEBUG_ERROR("Invalid parameter"); - return E_INVALIDARG; - } - if(m_pStream) - { - return m_pStream->CopyVideoBuffer(nWidth, nHeight, pBufferPtr, nBufferSize); - } - else - { - TSK_DEBUG_ERROR("No stream associated to this source"); - return E_NOT_VALID_STATE; - } + if(!pBufferPtr) { + TSK_DEBUG_ERROR("Invalid buffer pointer"); + return E_POINTER; + } + + if(!nWidth || !nHeight || !nBufferSize) { + TSK_DEBUG_ERROR("Invalid parameter"); + return E_INVALIDARG; + } + if(m_pStream) { + return m_pStream->CopyVideoBuffer(nWidth, nHeight, pBufferPtr, nBufferSize); + } + else { + TSK_DEBUG_ERROR("No stream associated to this source"); + return E_NOT_VALID_STATE; + } } // IUnknown methods @@ -186,8 +177,7 @@ ULONG CMFSource::AddRef() ULONG CMFSource::Release() { ULONG uCount = InterlockedDecrement(&m_nRefCount); - if (uCount == 0) - { + if (uCount == 0) { delete this; } // For thread safety, return a temporary variable. @@ -196,8 +186,7 @@ ULONG CMFSource::Release() HRESULT CMFSource::QueryInterface(REFIID iid, void** ppv) { - static const QITAB qit[] = - { + static const QITAB qit[] = { QITABENT(CMFSource, IMFMediaEventGenerator), QITABENT(CMFSource, IMFMediaSource), { 0 } @@ -220,8 +209,7 @@ HRESULT CMFSource::BeginGetEvent(IMFAsyncCallback* pCallback, IUnknown* punkStat hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pEventQueue->BeginGetEvent(pCallback, punkState); } @@ -238,8 +226,7 @@ HRESULT CMFSource::EndGetEvent(IMFAsyncResult* pResult, IMFMediaEvent** ppEvent) hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pEventQueue->EndGetEvent(pResult, ppEvent); } @@ -263,16 +250,14 @@ HRESULT CMFSource::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) // Check shutdown hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { pQueue = m_pEventQueue; pQueue->AddRef(); } LeaveCriticalSection(&m_critSec); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } @@ -288,8 +273,7 @@ HRESULT CMFSource::QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRES hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); } @@ -309,8 +293,7 @@ HRESULT CMFSource::QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRES HRESULT CMFSource::CreatePresentationDescriptor(IMFPresentationDescriptor** ppPresentationDescriptor) { - if (ppPresentationDescriptor == NULL) - { + if (ppPresentationDescriptor == NULL) { return E_POINTER; } @@ -320,17 +303,14 @@ HRESULT CMFSource::CreatePresentationDescriptor(IMFPresentationDescriptor** ppPr hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { - if (m_pPresentationDescriptor == NULL) - { + if (SUCCEEDED(hr)) { + if (m_pPresentationDescriptor == NULL) { hr = CreatePresentationDescriptor(); } } // Clone our default presentation descriptor. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pPresentationDescriptor->Clone(ppPresentationDescriptor); } @@ -347,8 +327,7 @@ HRESULT CMFSource::CreatePresentationDescriptor(IMFPresentationDescriptor** ppPr HRESULT CMFSource::GetCharacteristics(DWORD* pdwCharacteristics) { - if (pdwCharacteristics == NULL) - { + if (pdwCharacteristics == NULL) { return E_POINTER; } @@ -358,8 +337,7 @@ HRESULT CMFSource::GetCharacteristics(DWORD* pdwCharacteristics) hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { *pdwCharacteristics = MFMEDIASOURCE_CAN_PAUSE | MFMEDIASOURCE_IS_LIVE; } @@ -377,7 +355,7 @@ HRESULT CMFSource::Start( IMFPresentationDescriptor* pPresentationDescriptor, const GUID* pguidTimeFormat, const PROPVARIANT* pvarStartPosition - ) +) { HRESULT hr = S_OK; LONGLONG llStartOffset = 0; @@ -392,14 +370,12 @@ HRESULT CMFSource::Start( // Check parameters. // Start position and presentation descriptor cannot be NULL. - if (pvarStartPosition == NULL || pPresentationDescriptor == NULL) - { + if (pvarStartPosition == NULL || pPresentationDescriptor == NULL) { return E_INVALIDARG; } // Check the time format. Must be "reference time" units. - if ((pguidTimeFormat != NULL) && (*pguidTimeFormat != GUID_NULL)) - { + if ((pguidTimeFormat != NULL) && (*pguidTimeFormat != GUID_NULL)) { // Unrecognized time format GUID. return MF_E_UNSUPPORTED_TIME_FORMAT; } @@ -410,33 +386,27 @@ HRESULT CMFSource::Start( CHECK_HR(hr = CheckShutdown()); // Check the start position. - if (pvarStartPosition->vt == VT_I8) - { + if (pvarStartPosition->vt == VT_I8) { // Start position is given in pvarStartPosition in 100-ns units. llStartOffset = pvarStartPosition->hVal.QuadPart; - if (m_state != STATE_STOPPED) - { + if (m_state != STATE_STOPPED) { // Source is running or paused, so this is a seek. bIsSeek = TRUE; } } - else if (pvarStartPosition->vt == VT_EMPTY) - { + else if (pvarStartPosition->vt == VT_EMPTY) { // Start position is "current position". // For stopped, that means 0. Otherwise, use the current position. - if (m_state == STATE_STOPPED) - { + if (m_state == STATE_STOPPED) { llStartOffset = 0; } - else - { + else { llStartOffset = GetCurrentPosition(); bIsRestartFromCurrentPosition = TRUE; } } - else - { + else { // We don't support this time format. hr = MF_E_UNSUPPORTED_TIME_FORMAT; goto bail; @@ -457,12 +427,10 @@ HRESULT CMFSource::Start( var.hVal.QuadPart = llStartOffset; // Send the source event. - if (bIsSeek) - { + if (bIsSeek) { CHECK_HR(hr = QueueEvent(MESourceSeeked, GUID_NULL, hr, &var)); } - else - { + else { // For starting, if we are RESTARTING from the current position and our // previous state was running/paused, then we need to add the // MF_EVENT_SOURCE_ACTUAL_START attribute to the event. This requires @@ -472,8 +440,7 @@ HRESULT CMFSource::Start( CHECK_HR(hr = MFCreateMediaEvent(MESourceStarted, GUID_NULL, hr, &var, &pEvent)); // For restarts, set the actual start time as an attribute. - if (bIsRestartFromCurrentPosition) - { + if (bIsRestartFromCurrentPosition) { CHECK_HR(hr = pEvent->SetUINT64(MF_EVENT_SOURCE_ACTUAL_START, llStartOffset)); } @@ -484,31 +451,26 @@ HRESULT CMFSource::Start( bQueuedStartEvent = TRUE; // Send the stream event. - if (m_pStream) - { - if (bIsSeek) - { + if (m_pStream) { + if (bIsSeek) { CHECK_HR(hr = m_pStream->QueueEvent(MEStreamSeeked, GUID_NULL, hr, &var)); } - else - { + else { CHECK_HR(hr = m_pStream->QueueEvent(MEStreamStarted, GUID_NULL, hr, &var)); } } - if (bIsSeek) - { + if (bIsSeek) { // For seek requests, flush any queued samples. CHECK_HR(hr = m_pStream->Flush()); } - else - { + else { // Otherwise, deliver any queued samples. CHECK_HR(hr = m_pStream->DeliverQueuedSamples()); } - // Initialize Stream parameters - CHECK_HR(hr = m_pStream->InitializeParams()); + // Initialize Stream parameters + CHECK_HR(hr = m_pStream->InitializeParams()); m_state = STATE_STARTED; @@ -522,8 +484,7 @@ bail: // event (with a success code), then we need to raise an // MEError event. - if (FAILED(hr) && bQueuedStartEvent) - { + if (FAILED(hr) && bQueuedStartEvent) { hr = QueueEvent(MEError, GUID_NULL, hr, &var); } @@ -531,7 +492,7 @@ bail: SafeRelease(&pEvent); LeaveCriticalSection(&m_critSec); - + return hr; } @@ -550,31 +511,25 @@ HRESULT CMFSource::Pause() hr = CheckShutdown(); // Pause is only allowed from started state. - if (SUCCEEDED(hr)) - { - if (m_state != STATE_STARTED) - { + if (SUCCEEDED(hr)) { + if (m_state != STATE_STARTED) { hr = MF_E_INVALID_STATE_TRANSITION; } } // Send the appropriate events. - if (SUCCEEDED(hr)) - { - if (m_pStream) - { + if (SUCCEEDED(hr)) { + if (m_pStream) { hr = m_pStream->QueueEvent(MEStreamPaused, GUID_NULL, S_OK, NULL); } } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = QueueEvent(MESourcePaused, GUID_NULL, S_OK, NULL); } // Update our state. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { m_state = STATE_PAUSED; } @@ -597,8 +552,7 @@ HRESULT CMFSource::Stop() hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // Update our state. m_state = STATE_STOPPED; @@ -610,15 +564,12 @@ HRESULT CMFSource::Stop() // Queue events. // - if (SUCCEEDED(hr)) - { - if (m_pStream) - { + if (SUCCEEDED(hr)) { + if (m_pStream) { hr = m_pStream->QueueEvent(MEStreamStopped, GUID_NULL, S_OK, NULL); } } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = QueueEvent(MESourceStopped, GUID_NULL, S_OK, NULL); } @@ -645,17 +596,14 @@ HRESULT CMFSource::Shutdown() hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // Shut down the stream object. - if (m_pStream) - { + if (m_pStream) { (void)m_pStream->Shutdown(); } // Shut down the event queue. - if (m_pEventQueue) - { + if (m_pEventQueue) { (void)m_pEventQueue->Shutdown(); } @@ -694,44 +642,39 @@ HRESULT CMFSource::CreatePresentationDescriptor() // Create the stream descriptor. hr = MFCreateStreamDescriptor( - 0, // stream identifier - 1, // Number of media types. - &m_pMediaType, // Array of media types - &pStreamDescriptor - ); + 0, // stream identifier + 1, // Number of media types. + &m_pMediaType, // Array of media types + &pStreamDescriptor + ); // Set the default media type on the media type handler. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pStreamDescriptor->GetMediaTypeHandler(&pHandler); } - - if (SUCCEEDED(hr)) - { - hr = pHandler->SetCurrentMediaType(m_pMediaType); + + if (SUCCEEDED(hr)) { + hr = pHandler->SetCurrentMediaType(m_pMediaType); } // Create the presentation descriptor. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = MFCreatePresentationDescriptor( - 1, // Number of stream descriptors - &pStreamDescriptor, // Array of stream descriptors - &m_pPresentationDescriptor - ); + 1, // Number of stream descriptors + &pStreamDescriptor, // Array of stream descriptors + &m_pPresentationDescriptor + ); } // Select the first stream - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pPresentationDescriptor->SelectStream(0); } // Set the file/stream duration as an attribute on the presentation descriptor. - if (SUCCEEDED(hr)) - { - hr = m_pPresentationDescriptor->SetUINT64(MF_PD_DURATION, (UINT64)ULLONG_MAX); + if (SUCCEEDED(hr)) { + hr = m_pPresentationDescriptor->SetUINT64(MF_PD_DURATION, (UINT64)ULLONG_MAX); } - + SafeRelease(&pStreamDescriptor); SafeRelease(&pHandler); return hr; @@ -764,7 +707,7 @@ HRESULT CMFSource::ValidatePresentationDescriptor(IMFPresentationDescriptor *pPD IMFStreamDescriptor *pStreamDescriptor = NULL; IMFMediaTypeHandler *pHandler = NULL; IMFMediaType *pMediaType = NULL; - GUID majorType; + GUID majorType; DWORD cStreamDescriptors = 0; BOOL fSelected = FALSE; @@ -772,85 +715,71 @@ HRESULT CMFSource::ValidatePresentationDescriptor(IMFPresentationDescriptor *pPD // Make sure there is only one stream. hr = pPD->GetStreamDescriptorCount(&cStreamDescriptors); - if (SUCCEEDED(hr)) - { - if (cStreamDescriptors != 1) - { + if (SUCCEEDED(hr)) { + if (cStreamDescriptors != 1) { hr = MF_E_UNSUPPORTED_REPRESENTATION; } } // Get the stream descriptor. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pStreamDescriptor); } // Make sure it's selected. (This media source has only one stream, so it // is not useful to deselect the only stream.) - if (SUCCEEDED(hr)) - { - if (!fSelected) - { + if (SUCCEEDED(hr)) { + if (!fSelected) { hr = MF_E_UNSUPPORTED_REPRESENTATION; } } // Get the media type handler, so that we can get the media type. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pStreamDescriptor->GetMediaTypeHandler(&pHandler); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pHandler->GetCurrentMediaType(&pMediaType); } - hr = pMediaType->GetMajorType(&majorType); - - if (SUCCEEDED(hr)) - { - if(majorType == MFMediaType_Video) - { - if (SUCCEEDED(hr)) - { - hr = MFUtils::ValidateVideoFormat(pMediaType); - } - } - else - { - WAVEFORMATEX *pFormat = NULL; - UINT32 cbWaveFormat = 0; - - if (SUCCEEDED(hr)) - { - hr = MFCreateWaveFormatExFromMFMediaType( - pMediaType, - &pFormat, - &cbWaveFormat); - } - if (SUCCEEDED(hr)) - { - /*assert(this->WaveFormat() != NULL); - - if (cbWaveFormat < this->WaveFormatSize()) - { - hr = MF_E_INVALIDMEDIATYPE; - }*/ - } - - if (SUCCEEDED(hr)) - { - /*if (memcmp(pFormat, WaveFormat(), WaveFormatSize()) != 0) - { - hr = MF_E_INVALIDMEDIATYPE; - }*/ - } - - CoTaskMemFree(pFormat); - } - } + hr = pMediaType->GetMajorType(&majorType); + + if (SUCCEEDED(hr)) { + if(majorType == MFMediaType_Video) { + if (SUCCEEDED(hr)) { + hr = MFUtils::ValidateVideoFormat(pMediaType); + } + } + else { + WAVEFORMATEX *pFormat = NULL; + UINT32 cbWaveFormat = 0; + + if (SUCCEEDED(hr)) { + hr = MFCreateWaveFormatExFromMFMediaType( + pMediaType, + &pFormat, + &cbWaveFormat); + } + if (SUCCEEDED(hr)) { + /*assert(this->WaveFormat() != NULL); + + if (cbWaveFormat < this->WaveFormatSize()) + { + hr = MF_E_INVALIDMEDIATYPE; + }*/ + } + + if (SUCCEEDED(hr)) { + /*if (memcmp(pFormat, WaveFormat(), WaveFormatSize()) != 0) + { + hr = MF_E_INVALIDMEDIATYPE; + }*/ + } + + CoTaskMemFree(pFormat); + } + } SafeRelease(&pStreamDescriptor); SafeRelease(&pHandler); @@ -882,27 +811,23 @@ HRESULT CMFSource::QueueNewStreamEvent(IMFPresentationDescriptor *pPD) hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // The stream must be selected, because we don't allow the app // to de-select the stream. See ValidatePresentationDescriptor. assert(fSelected); - if (m_pStream) - { + if (m_pStream) { // The stream already exists, and is still selected. // Send the MEUpdatedStream event. hr = QueueEventWithIUnknown(this, MEUpdatedStream, S_OK, m_pStream); } - else - { + else { // The stream does not exist, and is now selected. // Create a new stream. hr = CreateCMFStreamSource(pSD); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // CreateCMFStreamSource creates the stream, so m_pStream is no longer NULL. assert(m_pStream != NULL); @@ -926,13 +851,11 @@ HRESULT CMFSource::CreateCMFStreamSource(IMFStreamDescriptor *pSD) HRESULT hr = S_OK; m_pStream = new (std::nothrow) CMFStreamSource(this, pSD, hr); - if (m_pStream == NULL) - { + if (m_pStream == NULL) { hr = E_OUTOFMEMORY; } - if (FAILED(hr)) - { + if (FAILED(hr)) { SafeRelease(&m_pStream); } @@ -948,12 +871,10 @@ HRESULT CMFSource::CreateCMFStreamSource(IMFStreamDescriptor *pSD) LONGLONG CMFSource::GetCurrentPosition() const { - if (m_pStream) - { + if (m_pStream) { return m_pStream->GetCurrentPosition(); } - else - { + else { // If no stream is selected, we are at time 0 by definition. return 0; } @@ -977,11 +898,11 @@ CMFStreamSource::CMFStreamSource(CMFSource *pSource, IMFStreamDescriptor *pSD, m_pEventQueue(NULL), m_IsShutdown(FALSE), m_rtCurrentPosition(0), - m_rtDuration(0), + m_rtDuration(0), m_discontinuity(FALSE), m_EOS(FALSE), - m_pMediaBuffer(NULL), - m_nBufferSize(0) + m_pMediaBuffer(NULL), + m_nBufferSize(0) { m_pSource = pSource; m_pSource->AddRef(); @@ -992,12 +913,12 @@ CMFStreamSource::CMFStreamSource(CMFSource *pSource, IMFStreamDescriptor *pSD, // Create the media event queue. CHECK_HR(hr = MFCreateEventQueue(&m_pEventQueue)); - //CHECK_HR(hr = InitializeParams()); - + //CHECK_HR(hr = InitializeParams()); + InitializeCriticalSection(&m_critSec); bail: - return; + return; } @@ -1010,7 +931,7 @@ CMFStreamSource::~CMFStreamSource() assert(m_IsShutdown); assert(m_nRefCount == 0); - SafeRelease(&m_pMediaBuffer); + SafeRelease(&m_pMediaBuffer); DeleteCriticalSection(&m_critSec); } @@ -1020,38 +941,36 @@ CMFStreamSource::~CMFStreamSource() HRESULT CMFStreamSource::CopyVideoBuffer(UINT32 nWidth, UINT32 nHeight, const void* pBufferPtr, UINT32 nBufferSize) { - // Buffer pointer and size validity already checked by source (caller) - if(m_guidMajorType != MFMediaType_Video) - { - TSK_DEBUG_ERROR("Calling CopyVideoBuffer on no-video stream"); + // Buffer pointer and size validity already checked by source (caller) + if(m_guidMajorType != MFMediaType_Video) { + TSK_DEBUG_ERROR("Calling CopyVideoBuffer on no-video stream"); #if defined(E_ILLEGAL_METHOD_CALL) - return E_ILLEGAL_METHOD_CALL; + return E_ILLEGAL_METHOD_CALL; #else - return _HRESULT_TYPEDEF_(0x8000000EL); + return _HRESULT_TYPEDEF_(0x8000000EL); #endif - } - if(nWidth != m_structVideoParams.nWidth || nHeight != m_structVideoParams.nHeigh || nBufferSize != m_nBufferSize) - { - TSK_DEBUG_ERROR("Invalid argument %u#%u or %u#%u or %u#%u. If the call is from a video consumer then, you can safely ignore this message.", nWidth, m_structVideoParams.nWidth, nHeight, m_structVideoParams.nHeigh, nBufferSize, m_nBufferSize); + } + if(nWidth != m_structVideoParams.nWidth || nHeight != m_structVideoParams.nHeigh || nBufferSize != m_nBufferSize) { + TSK_DEBUG_ERROR("Invalid argument %u#%u or %u#%u or %u#%u. If the call is from a video consumer then, you can safely ignore this message.", nWidth, m_structVideoParams.nWidth, nHeight, m_structVideoParams.nHeigh, nBufferSize, m_nBufferSize); #if defined(E_BOUNDS) - return E_BOUNDS; + return E_BOUNDS; #else - return _HRESULT_TYPEDEF_(0x8000000BL); + return _HRESULT_TYPEDEF_(0x8000000BL); #endif - } - - HRESULT hr = S_OK; - - BYTE* pMediaBufferPtr = NULL; - DWORD cbMaxLength = nBufferSize, cbCurrentLength = nBufferSize; - CHECK_HR(hr = m_pMediaBuffer->Lock(&pMediaBufferPtr, &cbMaxLength, &cbCurrentLength)); - - memcpy(pMediaBufferPtr, pBufferPtr, nBufferSize); - CHECK_HR(hr = m_pMediaBuffer->SetCurrentLength(nBufferSize)); - CHECK_HR(hr = m_pMediaBuffer->Unlock()); - + } + + HRESULT hr = S_OK; + + BYTE* pMediaBufferPtr = NULL; + DWORD cbMaxLength = nBufferSize, cbCurrentLength = nBufferSize; + CHECK_HR(hr = m_pMediaBuffer->Lock(&pMediaBufferPtr, &cbMaxLength, &cbCurrentLength)); + + memcpy(pMediaBufferPtr, pBufferPtr, nBufferSize); + CHECK_HR(hr = m_pMediaBuffer->SetCurrentLength(nBufferSize)); + CHECK_HR(hr = m_pMediaBuffer->Unlock()); + bail: - return hr; + return hr; } // IUnknown methods @@ -1064,8 +983,7 @@ ULONG CMFStreamSource::AddRef() ULONG CMFStreamSource::Release() { ULONG uCount = InterlockedDecrement(&m_nRefCount); - if (uCount == 0) - { + if (uCount == 0) { delete this; } // For thread safety, return a temporary variable. @@ -1074,8 +992,7 @@ ULONG CMFStreamSource::Release() HRESULT CMFStreamSource::QueryInterface(REFIID iid, void** ppv) { - static const QITAB qit[] = - { + static const QITAB qit[] = { QITABENT(CMFStreamSource, IMFMediaEventGenerator), QITABENT(CMFStreamSource, IMFMediaStream), { 0 } @@ -1094,8 +1011,7 @@ HRESULT CMFStreamSource::BeginGetEvent(IMFAsyncCallback* pCallback, IUnknown* pu EnterCriticalSection(&m_critSec); hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pEventQueue->BeginGetEvent(pCallback, punkState); } @@ -1110,8 +1026,7 @@ HRESULT CMFStreamSource::EndGetEvent(IMFAsyncResult* pResult, IMFMediaEvent** pp EnterCriticalSection(&m_critSec); hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pEventQueue->EndGetEvent(pResult, ppEvent); } @@ -1129,16 +1044,14 @@ HRESULT CMFStreamSource::GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { pQueue = m_pEventQueue; pQueue->AddRef(); } LeaveCriticalSection(&m_critSec); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pQueue->GetEvent(dwFlags, ppEvent); } @@ -1153,8 +1066,7 @@ HRESULT CMFStreamSource::QueueEvent(MediaEventType met, REFGUID guidExtendedType EnterCriticalSection(&m_critSec); hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); } @@ -1173,8 +1085,7 @@ HRESULT CMFStreamSource::QueueEvent(MediaEventType met, REFGUID guidExtendedType HRESULT CMFStreamSource::GetMediaSource(IMFMediaSource** ppMediaSource) { - if (ppMediaSource == NULL) - { + if (ppMediaSource == NULL) { return E_POINTER; } @@ -1187,16 +1098,13 @@ HRESULT CMFStreamSource::GetMediaSource(IMFMediaSource** ppMediaSource) hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { - if (m_pSource == NULL) - { + if (SUCCEEDED(hr)) { + if (m_pSource == NULL) { hr = E_UNEXPECTED; } } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = m_pSource->QueryInterface(IID_PPV_ARGS(ppMediaSource)); } @@ -1212,13 +1120,11 @@ HRESULT CMFStreamSource::GetMediaSource(IMFMediaSource** ppMediaSource) HRESULT CMFStreamSource::GetStreamDescriptor(IMFStreamDescriptor** ppStreamDescriptor) { - if (ppStreamDescriptor == NULL) - { + if (ppStreamDescriptor == NULL) { return E_POINTER; } - if (m_pStreamDescriptor == NULL) - { + if (m_pStreamDescriptor == NULL) { return E_UNEXPECTED; } @@ -1228,8 +1134,7 @@ HRESULT CMFStreamSource::GetStreamDescriptor(IMFStreamDescriptor** ppStreamDescr hr = CheckShutdown(); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { *ppStreamDescriptor = m_pStreamDescriptor; (*ppStreamDescriptor)->AddRef(); } @@ -1250,8 +1155,7 @@ HRESULT CMFStreamSource::GetStreamDescriptor(IMFStreamDescriptor** ppStreamDescr HRESULT CMFStreamSource::RequestSample(IUnknown* pToken) { - if (m_pSource == NULL) - { + if (m_pSource == NULL) { return E_UNEXPECTED; } @@ -1266,60 +1170,49 @@ HRESULT CMFStreamSource::RequestSample(IUnknown* pToken) hr = CheckShutdown(); // Check if we already reached the end of the stream. - if (SUCCEEDED(hr)) - { - if (m_EOS) - { + if (SUCCEEDED(hr)) { + if (m_EOS) { hr = MF_E_END_OF_STREAM; } } // Check the source is stopped. // GetState does not hold the source's critical section. Safe to call. - if (SUCCEEDED(hr)) - { - if (m_pSource->GetState() == CMFSource::STATE_STOPPED) - { + if (SUCCEEDED(hr)) { + if (m_pSource->GetState() == CMFSource::STATE_STOPPED) { hr = MF_E_INVALIDREQUEST; } } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // Create a new audio sample. hr = CreateSample(&pSample); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // If the caller provided a token, attach it to the sample as // an attribute. // NOTE: If we processed sample requests asynchronously, we would // need to call AddRef on the token and put the token onto a FIFO // queue. See documenation for IMFMediaStream::RequestSample. - if (pToken && pSample) - { + if (pToken && pSample) { hr = pSample->SetUnknown(MFSampleExtension_Token, pToken); } } // If paused, queue the sample for later delivery. Otherwise, deliver the sample now. - if (SUCCEEDED(hr) && pSample) - { - if (m_pSource->GetState() == CMFSource::STATE_PAUSED) - { + if (SUCCEEDED(hr) && pSample) { + if (m_pSource->GetState() == CMFSource::STATE_PAUSED) { hr = m_sampleQueue.Queue(pSample); } - else - { + else { hr = DeliverSample(pSample); } } // Cache a pointer to the source, prior to leaving the critical section. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { pSource = m_pSource; pSource->AddRef(); } @@ -1334,10 +1227,8 @@ HRESULT CMFStreamSource::RequestSample(IUnknown* pToken) // source's critical section while holding the stream's critical section, at // risk of deadlock. - if (SUCCEEDED(hr)) - { - if (m_EOS) - { + if (SUCCEEDED(hr)) { + if (m_EOS) { hr = pSource->QueueEvent(MEEndOfPresentation, GUID_NULL, S_OK, NULL); } } @@ -1352,78 +1243,72 @@ HRESULT CMFStreamSource::RequestSample(IUnknown* pToken) HRESULT CMFStreamSource::InitializeParams() { - HRESULT hr = S_OK; - - IMFMediaTypeHandler *pMediaTypeHandler = NULL; - IMFMediaType* pMediaType = NULL; - - CHECK_HR(hr = m_pStreamDescriptor->GetMediaTypeHandler(&pMediaTypeHandler)); - CHECK_HR(hr = pMediaTypeHandler->GetCurrentMediaType(&pMediaType)); - - GUID majorType, subType; - pMediaType->GetMajorType(&majorType); - if(majorType == MFMediaType_Video) - { - memset(&m_structVideoParams, 0, sizeof(m_structVideoParams)); - CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &m_structVideoParams.nWidth, &m_structVideoParams.nHeigh)); - CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); - - m_guidMajorType = MFMediaType_Video; - m_guidSubType = subType; - - // Guess video size - UINT32 nBufferSize; - if(subType == MFVideoFormat_RGB32) - { - nBufferSize = (m_structVideoParams.nWidth * m_structVideoParams.nHeigh << 2); - } - else if(subType == MFVideoFormat_RGB24) - { - nBufferSize = (m_structVideoParams.nWidth * m_structVideoParams.nHeigh << 2); - } - else if(subType == MFVideoFormat_NV12 || subType == MFVideoFormat_I420) - { - nBufferSize = (m_structVideoParams.nWidth * m_structVideoParams.nHeigh * 3) >> 1; - } - else - { - TSK_DEBUG_ERROR("Video subType not supported"); - CHECK_HR(hr = E_NOTIMPL); - } - - // Allocate media buffer - SafeRelease(&m_pMediaBuffer); - CHECK_HR(hr = MFCreateMemoryBuffer(nBufferSize, &m_pMediaBuffer)); - m_nBufferSize = nBufferSize; - { - //FIXME: DeliverSample() stops if no data - BYTE* pBuffer = NULL; - CHECK_HR(hr = m_pMediaBuffer->Lock(&pBuffer, NULL, NULL)); - memset(pBuffer, 0, nBufferSize); - CHECK_HR(hr = m_pMediaBuffer->SetCurrentLength(nBufferSize)); - CHECK_HR(hr = m_pMediaBuffer->Unlock()); - } - - // Retrieve video Frame rate - UINT32 unNumerator, unDenominator; - CHECK_HR(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &unNumerator, &unDenominator)); - m_structVideoParams.nFps = (unNumerator / unDenominator); - - // Retrieve sample duration based on framerate - m_rtCurrentPosition = 0; - CHECK_HR(hr = MFFrameRateToAverageTimePerFrame(m_structVideoParams.nFps, 1, &m_rtDuration)); - } - else - { - TSK_DEBUG_ERROR("Only video media type is supported"); - CHECK_HR(hr = E_NOTIMPL); - } + HRESULT hr = S_OK; + + IMFMediaTypeHandler *pMediaTypeHandler = NULL; + IMFMediaType* pMediaType = NULL; + + CHECK_HR(hr = m_pStreamDescriptor->GetMediaTypeHandler(&pMediaTypeHandler)); + CHECK_HR(hr = pMediaTypeHandler->GetCurrentMediaType(&pMediaType)); + + GUID majorType, subType; + pMediaType->GetMajorType(&majorType); + if(majorType == MFMediaType_Video) { + memset(&m_structVideoParams, 0, sizeof(m_structVideoParams)); + CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &m_structVideoParams.nWidth, &m_structVideoParams.nHeigh)); + CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); + + m_guidMajorType = MFMediaType_Video; + m_guidSubType = subType; + + // Guess video size + UINT32 nBufferSize; + if(subType == MFVideoFormat_RGB32) { + nBufferSize = (m_structVideoParams.nWidth * m_structVideoParams.nHeigh << 2); + } + else if(subType == MFVideoFormat_RGB24) { + nBufferSize = (m_structVideoParams.nWidth * m_structVideoParams.nHeigh << 2); + } + else if(subType == MFVideoFormat_NV12 || subType == MFVideoFormat_I420) { + nBufferSize = (m_structVideoParams.nWidth * m_structVideoParams.nHeigh * 3) >> 1; + } + else { + TSK_DEBUG_ERROR("Video subType not supported"); + CHECK_HR(hr = E_NOTIMPL); + } + + // Allocate media buffer + SafeRelease(&m_pMediaBuffer); + CHECK_HR(hr = MFCreateMemoryBuffer(nBufferSize, &m_pMediaBuffer)); + m_nBufferSize = nBufferSize; + { + //FIXME: DeliverSample() stops if no data + BYTE* pBuffer = NULL; + CHECK_HR(hr = m_pMediaBuffer->Lock(&pBuffer, NULL, NULL)); + memset(pBuffer, 0, nBufferSize); + CHECK_HR(hr = m_pMediaBuffer->SetCurrentLength(nBufferSize)); + CHECK_HR(hr = m_pMediaBuffer->Unlock()); + } + + // Retrieve video Frame rate + UINT32 unNumerator, unDenominator; + CHECK_HR(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &unNumerator, &unDenominator)); + m_structVideoParams.nFps = (unNumerator / unDenominator); + + // Retrieve sample duration based on framerate + m_rtCurrentPosition = 0; + CHECK_HR(hr = MFFrameRateToAverageTimePerFrame(m_structVideoParams.nFps, 1, &m_rtDuration)); + } + else { + TSK_DEBUG_ERROR("Only video media type is supported"); + CHECK_HR(hr = E_NOTIMPL); + } bail: - SafeRelease(&pMediaTypeHandler); - SafeRelease(&pMediaType); + SafeRelease(&pMediaTypeHandler); + SafeRelease(&pMediaType); - return hr; + return hr; } // NOTE: Some of these methods hold the stream's critical section @@ -1436,29 +1321,27 @@ bail: HRESULT CMFStreamSource::CreateSample(IMFSample **ppSample) { - *ppSample = NULL; + *ppSample = NULL; HRESULT hr = S_OK; IMFSample *pSample = NULL; - DWORD nCurrentLength = 0; - - CHECK_HR(hr = m_pMediaBuffer->GetCurrentLength(&nCurrentLength)); - - if(nCurrentLength > 0) - { - CHECK_HR(hr = MFCreateSample(&pSample)); - CHECK_HR(hr = pSample->SetSampleTime(m_rtCurrentPosition)); - CHECK_HR(hr = pSample->SetSampleDuration(m_rtDuration)); - m_rtCurrentPosition += m_rtDuration; - CHECK_HR(hr = pSample->AddBuffer(m_pMediaBuffer)); - - if((*ppSample = pSample)) - { - (*ppSample)->AddRef(); - } - } - + DWORD nCurrentLength = 0; + + CHECK_HR(hr = m_pMediaBuffer->GetCurrentLength(&nCurrentLength)); + + if(nCurrentLength > 0) { + CHECK_HR(hr = MFCreateSample(&pSample)); + CHECK_HR(hr = pSample->SetSampleTime(m_rtCurrentPosition)); + CHECK_HR(hr = pSample->SetSampleDuration(m_rtDuration)); + m_rtCurrentPosition += m_rtDuration; + CHECK_HR(hr = pSample->AddBuffer(m_pMediaBuffer)); + + if((*ppSample = pSample)) { + (*ppSample)->AddRef(); + } + } + bail: SafeRelease(&pSample); return hr; @@ -1472,15 +1355,13 @@ HRESULT CMFStreamSource::DeliverSample(IMFSample *pSample) { HRESULT hr = S_OK; - if(pSample) - { - // Send the MEMediaSample event with the new sample. - hr = QueueEventWithIUnknown(this, MEMediaSample, hr, pSample); - } + if(pSample) { + // Send the MEMediaSample event with the new sample. + hr = QueueEventWithIUnknown(this, MEMediaSample, hr, pSample); + } // See if we reached the end of the stream. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = CheckEndOfStream(); // This method sends MEEndOfStream if needed. } @@ -1506,25 +1387,20 @@ HRESULT CMFStreamSource::DeliverQueuedSamples() // If we already reached the end of the stream, send the MEEndStream // event again. - if (m_EOS) - { + if (m_EOS) { hr = QueueEvent(MEEndOfStream, GUID_NULL, S_OK, NULL); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // Deliver any queued samples. - while (!m_sampleQueue.IsEmpty()) - { + while (!m_sampleQueue.IsEmpty()) { hr = m_sampleQueue.Dequeue(&pSample); - if (FAILED(hr)) - { + if (FAILED(hr)) { break; } hr = DeliverSample(pSample); - if (FAILED(hr)) - { + if (FAILED(hr)) { break; } @@ -1536,10 +1412,8 @@ HRESULT CMFStreamSource::DeliverQueuedSamples() // If we reached the end of the stream, send the end-of-presentation event from // the media source. - if (SUCCEEDED(hr)) - { - if (m_EOS) - { + if (SUCCEEDED(hr)) { + if (m_EOS) { hr = m_pSource->QueueEvent(MEEndOfPresentation, GUID_NULL, S_OK, NULL); } } @@ -1578,8 +1452,7 @@ HRESULT CMFStreamSource::Shutdown() Flush(); // Shut down the event queue. - if (m_pEventQueue) - { + if (m_pEventQueue) { m_pEventQueue->Shutdown(); } @@ -1602,37 +1475,37 @@ HRESULT CMFStreamSource::SetPosition(LONGLONG rtNewPosition) { EnterCriticalSection(&m_critSec); - HRESULT hr = S_OK; + HRESULT hr = S_OK; -/* - // Check if the requested position is beyond the end of the stream. - LONGLONG duration = AudioDurationFromBufferSize(m_pRiff->Format(), m_pRiff->Chunk().DataSize()); + /* + // Check if the requested position is beyond the end of the stream. + LONGLONG duration = AudioDurationFromBufferSize(m_pRiff->Format(), m_pRiff->Chunk().DataSize()); - if (rtNewPosition > duration) - { - LeaveCriticalSection(&m_critSec); + if (rtNewPosition > duration) + { + LeaveCriticalSection(&m_critSec); - return MF_E_INVALIDREQUEST; // Start position is past the end of the presentation. - } + return MF_E_INVALIDREQUEST; // Start position is past the end of the presentation. + } - if (m_rtCurrentPosition != rtNewPosition) - { - LONGLONG offset = BufferSizeFromAudioDuration(m_pRiff->Format(), rtNewPosition); + if (m_rtCurrentPosition != rtNewPosition) + { + LONGLONG offset = BufferSizeFromAudioDuration(m_pRiff->Format(), rtNewPosition); - // The chunk size is a DWORD. So if our calculations are correct, there is no - // way that the maximum valid seek position can be larger than a DWORD. - assert(offset <= MAXDWORD); + // The chunk size is a DWORD. So if our calculations are correct, there is no + // way that the maximum valid seek position can be larger than a DWORD. + assert(offset <= MAXDWORD); - hr = m_pRiff->MoveToChunkOffset((DWORD)offset); + hr = m_pRiff->MoveToChunkOffset((DWORD)offset); - if (SUCCEEDED(hr)) - { - m_rtCurrentPosition = rtNewPosition; - m_discontinuity = TRUE; - m_EOS = FALSE; + if (SUCCEEDED(hr)) + { + m_rtCurrentPosition = rtNewPosition; + m_discontinuity = TRUE; + m_EOS = FALSE; + } } - } -*/ + */ LeaveCriticalSection(&m_critSec); return hr; } @@ -1640,18 +1513,18 @@ HRESULT CMFStreamSource::SetPosition(LONGLONG rtNewPosition) HRESULT CMFStreamSource::CheckEndOfStream() { HRESULT hr = S_OK; -/* - if (m_pRiff->BytesRemainingInChunk() < m_pRiff->Format()->nBlockAlign) - { - // The remaining data is smaller than the audio block size. (In theory there shouldn't be - // partial bits of data at the end, so we should reach an even zero bytes, but the file - // might not be authored correctly.) - m_EOS = TRUE; - - // Send the end-of-stream event, - hr = QueueEvent(MEEndOfStream, GUID_NULL, S_OK, NULL); - } - */ + /* + if (m_pRiff->BytesRemainingInChunk() < m_pRiff->Format()->nBlockAlign) + { + // The remaining data is smaller than the audio block size. (In theory there shouldn't be + // partial bits of data at the end, so we should reach an even zero bytes, but the file + // might not be authored correctly.) + m_EOS = TRUE; + + // Send the end-of-stream event, + hr = QueueEvent(MEEndOfStream, GUID_NULL, S_OK, NULL); + } + */ return hr; } @@ -1697,8 +1570,7 @@ LONGLONG AudioDurationFromBufferSize(const WAVEFORMATEX *pWav, DWORD cbAudioData { assert(pWav != NULL); - if (pWav->nAvgBytesPerSec == 0) - { + if (pWav->nAvgBytesPerSec == 0) { return 0; } return (LONGLONG)cbAudioDataSize * 10000000 / pWav->nAvgBytesPerSec; @@ -1711,8 +1583,7 @@ LONGLONG BufferSizeFromAudioDuration(const WAVEFORMATEX *pWav, LONGLONG duration ULONG ulRemainder = (ULONG)(cbSize % pWav->nBlockAlign); // Round up to the next block. - if(ulRemainder) - { + if(ulRemainder) { cbSize += pWav->nBlockAlign - ulRemainder; } diff --git a/plugins/pluginWinMF/internals/mf_custom_src.h b/plugins/pluginWinMF/internals/mf_custom_src.h index f9194c9..15d8b90 100755 --- a/plugins/pluginWinMF/internals/mf_custom_src.h +++ b/plugins/pluginWinMF/internals/mf_custom_src.h @@ -1,20 +1,20 @@ -/* +/* * Copyright (C) Microsoft Corporation. All rights reserved. * Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -50,10 +50,10 @@ class CMFSource : public IMFMediaSource public: static HRESULT CreateInstance(REFIID iid, void **ppSource); - static HRESULT CreateInstanceEx(REFIID iid, void **ppSource, IMFMediaType *pMediaType); + static HRESULT CreateInstanceEx(REFIID iid, void **ppSource, IMFMediaType *pMediaType); - // IMFCustomSource - HRESULT CopyVideoBuffer(UINT32 nWidth, UINT32 nHeight, const void* pBufferPtr, UINT32 nBufferSize); + // IMFCustomSource + HRESULT CopyVideoBuffer(UINT32 nWidth, UINT32 nHeight, const void* pBufferPtr, UINT32 nBufferSize); // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv); @@ -80,8 +80,7 @@ public: private: - enum State - { + enum State { STATE_STOPPED, STATE_PAUSED, STATE_STARTED @@ -92,14 +91,11 @@ private: CMFSource(HRESULT &hr, IMFMediaType *pMediaType); virtual ~CMFSource(); - HRESULT CheckShutdown() const - { - if (m_IsShutdown) - { + HRESULT CheckShutdown() const { + if (m_IsShutdown) { return MF_E_SHUTDOWN; } - else - { + else { return S_OK; } } @@ -110,7 +106,9 @@ private: HRESULT ValidatePresentationDescriptor(IMFPresentationDescriptor *pPD); LONGLONG GetCurrentPosition() const; - State GetState() const { return m_state; } + State GetState() const { + return m_state; + } IMFMediaEventQueue *m_pEventQueue; // Event generator helper IMFPresentationDescriptor *m_pPresentationDescriptor; // Default presentation @@ -122,7 +120,7 @@ private: BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called. State m_state; // Current state (running, stopped, paused) - IMFMediaType *m_pMediaType; // The supported mediaType + IMFMediaType *m_pMediaType; // The supported mediaType }; @@ -131,22 +129,21 @@ class SampleQueue protected: // Nodes in the linked list - struct Node - { + struct Node { Node *prev; Node *next; IMFSample* item; - Node() : prev(NULL), next(NULL) - { + Node() : prev(NULL), next(NULL) { } - Node(IMFSample* item) : prev(NULL), next(NULL) - { + Node(IMFSample* item) : prev(NULL), next(NULL) { this->item = item; } - IMFSample* Item() const { return item; } + IMFSample* Item() const { + return item; + } }; @@ -155,27 +152,22 @@ protected: public: - SampleQueue() - { + SampleQueue() { m_anchor.next = &m_anchor; m_anchor.prev = &m_anchor; } - virtual ~SampleQueue() - { + virtual ~SampleQueue() { Clear(); } - HRESULT Queue(IMFSample* item) - { - if (item == NULL) - { + HRESULT Queue(IMFSample* item) { + if (item == NULL) { return E_POINTER; } Node *pNode = new (std::nothrow) Node(item); - if (pNode == NULL) - { + if (pNode == NULL) { return E_OUTOFMEMORY; } @@ -195,14 +187,11 @@ public: } - HRESULT Dequeue(IMFSample* *ppItem) - { - if (IsEmpty()) - { + HRESULT Dequeue(IMFSample**ppItem) { + if (IsEmpty()) { return E_FAIL; } - if (ppItem == NULL) - { + if (ppItem == NULL) { return E_POINTER; } @@ -220,17 +209,16 @@ public: return S_OK; } - BOOL IsEmpty() const { return m_anchor.next == &m_anchor; } + BOOL IsEmpty() const { + return m_anchor.next == &m_anchor; + } - void Clear() - { + void Clear() { Node *n = m_anchor.next; // Delete the nodes - while (n != &m_anchor) - { - if (n->item) - { + while (n != &m_anchor) { + if (n->item) { n->item->Release(); } @@ -260,8 +248,8 @@ class CMFStreamSource : public IMFMediaStream public: - // IMFCustomSource - HRESULT CopyVideoBuffer(UINT32 nWidth, UINT32 nHeight, const void* pBufferPtr, UINT32 nBufferSize); + // IMFCustomSource + HRESULT CopyVideoBuffer(UINT32 nWidth, UINT32 nHeight, const void* pBufferPtr, UINT32 nBufferSize); // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv); @@ -285,26 +273,25 @@ private: ~CMFStreamSource(); - HRESULT CheckShutdown() const - { - if (m_IsShutdown) - { + HRESULT CheckShutdown() const { + if (m_IsShutdown) { return MF_E_SHUTDOWN; } - else - { + else { return S_OK; } } - HRESULT InitializeParams(); + HRESULT InitializeParams(); HRESULT Shutdown(); HRESULT CreateSample(IMFSample **pSample); HRESULT DeliverSample(IMFSample *pSample); HRESULT DeliverQueuedSamples(); HRESULT Flush(); - LONGLONG GetCurrentPosition() const { return m_rtCurrentPosition; } + LONGLONG GetCurrentPosition() const { + return m_rtCurrentPosition; + } HRESULT SetPosition(LONGLONG rtNewPosition); HRESULT CheckEndOfStream(); @@ -313,7 +300,7 @@ private: CRITICAL_SECTION m_critSec; BOOL m_IsShutdown; // Flag to indicate if source's Shutdown() method was called. LONGLONG m_rtCurrentPosition; // Current position in the stream, in 100-ns units - UINT64 m_rtDuration; // Sample duration, in 100-ns units + UINT64 m_rtDuration; // Sample duration, in 100-ns units BOOL m_discontinuity; // Is the next sample a discontinuity? BOOL m_EOS; // Did we reach the end of the stream? @@ -322,18 +309,17 @@ private: IMFStreamDescriptor *m_pStreamDescriptor; // Stream descriptor for this stream. SampleQueue m_sampleQueue; // Queue for samples while paused. - GUID m_guidMajorType; // major media type (e.g. MFMediaType_Video or MFMediaType_Audio) - GUID m_guidSubType; // Media subtype (e.g. MFVideoFormat_RGB32 or MFVideoFormat_H264) - IMFMediaBuffer *m_pMediaBuffer; // Pointer to the data to deliver - UINT32 m_nBufferSize; // Size of the data to deliver - - struct - { - UINT32 nWidth; - UINT32 nHeigh; - UINT32 nFps; - } - m_structVideoParams; + GUID m_guidMajorType; // major media type (e.g. MFMediaType_Video or MFMediaType_Audio) + GUID m_guidSubType; // Media subtype (e.g. MFVideoFormat_RGB32 or MFVideoFormat_H264) + IMFMediaBuffer *m_pMediaBuffer; // Pointer to the data to deliver + UINT32 m_nBufferSize; // Size of the data to deliver + + struct { + UINT32 nWidth; + UINT32 nHeigh; + UINT32 nFps; + } + m_structVideoParams; }; diff --git a/plugins/pluginWinMF/internals/mf_devices.cxx b/plugins/pluginWinMF/internals/mf_devices.cxx index 22b862e..49005de 100755 --- a/plugins/pluginWinMF/internals/mf_devices.cxx +++ b/plugins/pluginWinMF/internals/mf_devices.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -20,25 +20,25 @@ #include "mf_utils.h" DeviceList::DeviceList() -: m_ppDevices(NULL) -, m_cDevices(0) + : m_ppDevices(NULL) + , m_cDevices(0) { - + } DeviceList::~DeviceList() { - Clear(); + Clear(); } UINT32 DeviceList::Count()const { - return m_cDevices; + return m_cDevices; } void DeviceList::Clear() { - for (UINT32 i = 0; i < m_cDevices; i++) { + for (UINT32 i = 0; i < m_cDevices; i++) { SafeRelease(&m_ppDevices[i]); } CoTaskMemFree(m_ppDevices); @@ -49,7 +49,7 @@ void DeviceList::Clear() HRESULT DeviceList::EnumerateDevices(const GUID& sourceType) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; IMFAttributes *pAttributes = NULL; Clear(); @@ -60,17 +60,15 @@ HRESULT DeviceList::EnumerateDevices(const GUID& sourceType) hr = MFCreateAttributes(&pAttributes, 1); // Ask for source type = video capture devices - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pAttributes->SetGUID( - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, - sourceType - ); + MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, + sourceType + ); } // Enumerate devices. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = MFEnumDeviceSources(pAttributes, &m_ppDevices, &m_cDevices); } @@ -81,8 +79,7 @@ HRESULT DeviceList::EnumerateDevices(const GUID& sourceType) HRESULT DeviceList::GetDeviceAtIndex(UINT32 index, IMFActivate **ppActivate) { - if (index >= Count()) - { + if (index >= Count()) { return E_INVALIDARG; } @@ -94,58 +91,52 @@ HRESULT DeviceList::GetDeviceAtIndex(UINT32 index, IMFActivate **ppActivate) HRESULT DeviceList::GetDeviceBest(IMFActivate **ppActivate, WCHAR *pszName /*= NULL*/) { - UINT32 index = 0; - if(pszName) - { - WCHAR *_pszName = NULL; - BOOL bFound = FALSE; - for(UINT32 i = 0; i < Count() && !bFound; ++i) - { - if((SUCCEEDED(GetDeviceName(i, &_pszName)))) - { - if(wcscmp(_pszName, pszName) == 0) - { - index = i; - bFound = TRUE; - // do not break the loop because we need to free(_pszName) - } - } - if(_pszName) - { - CoTaskMemFree(_pszName), _pszName = NULL; - } - } - } - return GetDeviceAtIndex(index, ppActivate); + UINT32 index = 0; + if(pszName) { + WCHAR *_pszName = NULL; + BOOL bFound = FALSE; + for(UINT32 i = 0; i < Count() && !bFound; ++i) { + if((SUCCEEDED(GetDeviceName(i, &_pszName)))) { + if(wcscmp(_pszName, pszName) == 0) { + index = i; + bFound = TRUE; + // do not break the loop because we need to free(_pszName) + } + } + if(_pszName) { + CoTaskMemFree(_pszName), _pszName = NULL; + } + } + } + return GetDeviceAtIndex(index, ppActivate); } // The caller must free the memory for the string by calling CoTaskMemFree HRESULT DeviceList::GetDeviceName(UINT32 index, WCHAR **ppszName) { - if (index >= Count()) - { + if (index >= Count()) { return E_INVALIDARG; } HRESULT hr = S_OK; hr = m_ppDevices[index]->GetAllocatedString( - MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, - ppszName, - NULL - ); + MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, + ppszName, + NULL + ); return hr; } HRESULT DeviceListAudio::EnumerateDevices() { - // call base class function - return DeviceList::EnumerateDevices(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID); + // call base class function + return DeviceList::EnumerateDevices(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID); } HRESULT DeviceListVideo::EnumerateDevices() { - // call base class function - return DeviceList::EnumerateDevices(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); + // call base class function + return DeviceList::EnumerateDevices(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); } diff --git a/plugins/pluginWinMF/internals/mf_devices.h b/plugins/pluginWinMF/internals/mf_devices.h index 03d010f..3a16a29 100755 --- a/plugins/pluginWinMF/internals/mf_devices.h +++ b/plugins/pluginWinMF/internals/mf_devices.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -46,19 +46,19 @@ public: HRESULT GetDeviceName(UINT32 index, WCHAR **ppszName); protected: - HRESULT EnumerateDevices(const GUID& sourceType); + HRESULT EnumerateDevices(const GUID& sourceType); }; class DeviceListAudio : public DeviceList { public: - HRESULT EnumerateDevices(); + HRESULT EnumerateDevices(); }; class DeviceListVideo : public DeviceList { public: - HRESULT EnumerateDevices(); + HRESULT EnumerateDevices(); }; #endif /* PLUGIN_WIN_MF_DEVICES_H */ diff --git a/plugins/pluginWinMF/internals/mf_display_watcher.cxx b/plugins/pluginWinMF/internals/mf_display_watcher.cxx index 62dbc5f..38f3687 100755 --- a/plugins/pluginWinMF/internals/mf_display_watcher.cxx +++ b/plugins/pluginWinMF/internals/mf_display_watcher.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -24,137 +24,126 @@ #include <assert.h> DisplayWatcher::DisplayWatcher(HWND hWnd, IMFMediaSink* pMediaSink, HRESULT &hr) -: m_pDisplayControl(NULL) -, m_hWnd(hWnd) -, m_pWndProc(NULL) -, m_bStarted(FALSE) -, m_bFullScreen(FALSE) + : m_pDisplayControl(NULL) + , m_hWnd(hWnd) + , m_pWndProc(NULL) + , m_bStarted(FALSE) + , m_bFullScreen(FALSE) { - IMFGetService *pService = NULL; + IMFGetService *pService = NULL; - CHECK_HR(hr = pMediaSink->QueryInterface(__uuidof(IMFGetService), (void**)&pService)); - CHECK_HR(hr = pService->GetService(MR_VIDEO_RENDER_SERVICE, __uuidof(IMFVideoDisplayControl), (void**)&m_pDisplayControl)); - CHECK_HR(hr = m_pDisplayControl->SetAspectRatioMode(MFVideoARMode_PreservePicture)); + CHECK_HR(hr = pMediaSink->QueryInterface(__uuidof(IMFGetService), (void**)&pService)); + CHECK_HR(hr = pService->GetService(MR_VIDEO_RENDER_SERVICE, __uuidof(IMFVideoDisplayControl), (void**)&m_pDisplayControl)); + CHECK_HR(hr = m_pDisplayControl->SetAspectRatioMode(MFVideoARMode_PreservePicture)); bail: - SafeRelease(&pService); + SafeRelease(&pService); } DisplayWatcher::~DisplayWatcher() { - Stop(); + Stop(); - SafeRelease(&m_pDisplayControl); + SafeRelease(&m_pDisplayControl); } HRESULT DisplayWatcher::Start() { - HRESULT hr = S_OK; - HWND hWnd = m_hWnd; // save() - CHECK_HR(hr = Stop()); - - if((m_hWnd = hWnd) && m_pDisplayControl) - { - CHECK_HR(hr = m_pDisplayControl->SetVideoWindow(hWnd)); - - BOOL ret = SetPropA(m_hWnd, "This", this); - assert(ret); - + HRESULT hr = S_OK; + HWND hWnd = m_hWnd; // save() + CHECK_HR(hr = Stop()); + + if((m_hWnd = hWnd) && m_pDisplayControl) { + CHECK_HR(hr = m_pDisplayControl->SetVideoWindow(hWnd)); + + BOOL ret = SetPropA(m_hWnd, "This", this); + assert(ret); + #if _M_X64 - m_pWndProc = (WNDPROC)SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)DisplayWatcher::WndProc); + m_pWndProc = (WNDPROC)SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)DisplayWatcher::WndProc); #else - m_pWndProc = (WNDPROC)SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG)DisplayWatcher::WndProc); + m_pWndProc = (WNDPROC)SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG)DisplayWatcher::WndProc); #endif - UpdatePosition(); // black screen if attached later - } - m_bStarted = TRUE; + UpdatePosition(); // black screen if attached later + } + m_bStarted = TRUE; bail: - return hr; + return hr; } HRESULT DisplayWatcher::SetFullscreen(BOOL bEnabled) { - if(m_pDisplayControl) - { - HRESULT hr = m_pDisplayControl->SetFullscreen(bEnabled); - m_bFullScreen = SUCCEEDED(hr); - return hr; - } - - return E_FAIL; + if(m_pDisplayControl) { + HRESULT hr = m_pDisplayControl->SetFullscreen(bEnabled); + m_bFullScreen = SUCCEEDED(hr); + return hr; + } + + return E_FAIL; } HRESULT DisplayWatcher::SetHwnd(HWND hWnd) { - BOOL bWasStarted = m_bStarted; - Stop(); - m_hWnd = hWnd; - if(bWasStarted) - { - return Start(); - } - return S_OK; + BOOL bWasStarted = m_bStarted; + Stop(); + m_hWnd = hWnd; + if(bWasStarted) { + return Start(); + } + return S_OK; } HRESULT DisplayWatcher::Stop() { - if(m_hWnd && m_pWndProc) - { - // Restore - + if(m_hWnd && m_pWndProc) { + // Restore + #if _M_X64 - SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pWndProc); + SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pWndProc); #else - SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG)m_pWndProc); + SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG)m_pWndProc); #endif - } - m_hWnd = NULL; - m_pWndProc = NULL; - m_bStarted = FALSE; - return S_OK; + } + m_hWnd = NULL; + m_pWndProc = NULL; + m_bStarted = FALSE; + return S_OK; } void DisplayWatcher::UpdatePosition() { - if(m_pDisplayControl && m_hWnd) - { - RECT rcDst = { 0, 0, 0, 0 }; - GetClientRect(m_hWnd, &rcDst); - m_pDisplayControl->SetVideoPosition(NULL, &rcDst); - } + if(m_pDisplayControl && m_hWnd) { + RECT rcDst = { 0, 0, 0, 0 }; + GetClientRect(m_hWnd, &rcDst); + m_pDisplayControl->SetVideoPosition(NULL, &rcDst); + } } LRESULT CALLBACK DisplayWatcher::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch(uMsg) - { - case WM_CREATE: - case WM_SIZE: - case WM_MOVE: - { - DisplayWatcher* This = dynamic_cast<DisplayWatcher*>((DisplayWatcher*)GetPropA(hWnd, "This")); - if(This) - { - This->UpdatePosition(); - } - break; - } - - case WM_CHAR: - case WM_KEYUP: - { - DisplayWatcher* This = dynamic_cast<DisplayWatcher*>((DisplayWatcher*)GetPropA(hWnd, "This")); - if(This) - { - if(This->m_bFullScreen && (wParam == 0x1B || wParam == VK_ESCAPE)) - { - This->SetFullscreen(FALSE); - } - } - - break; - } - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); + switch(uMsg) { + case WM_CREATE: + case WM_SIZE: + case WM_MOVE: { + DisplayWatcher* This = dynamic_cast<DisplayWatcher*>((DisplayWatcher*)GetPropA(hWnd, "This")); + if(This) { + This->UpdatePosition(); + } + break; + } + + case WM_CHAR: + case WM_KEYUP: { + DisplayWatcher* This = dynamic_cast<DisplayWatcher*>((DisplayWatcher*)GetPropA(hWnd, "This")); + if(This) { + if(This->m_bFullScreen && (wParam == 0x1B || wParam == VK_ESCAPE)) { + This->SetFullscreen(FALSE); + } + } + + break; + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); }
\ No newline at end of file diff --git a/plugins/pluginWinMF/internals/mf_display_watcher.h b/plugins/pluginWinMF/internals/mf_display_watcher.h index d41d6a6..127fb35 100755 --- a/plugins/pluginWinMF/internals/mf_display_watcher.h +++ b/plugins/pluginWinMF/internals/mf_display_watcher.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -31,25 +31,25 @@ class DisplayWatcher { public: - DisplayWatcher(HWND hWnd, IMFMediaSink* pMediaSink, HRESULT &hr); - virtual ~DisplayWatcher(); + DisplayWatcher(HWND hWnd, IMFMediaSink* pMediaSink, HRESULT &hr); + virtual ~DisplayWatcher(); public: - HRESULT Start(); - HRESULT SetFullscreen(BOOL bEnabled); - HRESULT SetHwnd(HWND hWnd); - HRESULT Stop(); + HRESULT Start(); + HRESULT SetFullscreen(BOOL bEnabled); + HRESULT SetHwnd(HWND hWnd); + HRESULT Stop(); private: - void UpdatePosition(); - static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + void UpdatePosition(); + static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); private: - IMFVideoDisplayControl *m_pDisplayControl; - HWND m_hWnd; - WNDPROC m_pWndProc; - BOOL m_bStarted; - BOOL m_bFullScreen; + IMFVideoDisplayControl *m_pDisplayControl; + HWND m_hWnd; + WNDPROC m_pWndProc; + BOOL m_bStarted; + BOOL m_bFullScreen; }; #endif /* PLUGIN_WIN_MF_DISPLAY_WATCHER_H */ diff --git a/plugins/pluginWinMF/internals/mf_sample_grabber.cxx b/plugins/pluginWinMF/internals/mf_sample_grabber.cxx index 87aa6af..8d148a3 100755 --- a/plugins/pluginWinMF/internals/mf_sample_grabber.cxx +++ b/plugins/pluginWinMF/internals/mf_sample_grabber.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -28,108 +28,105 @@ // Create a new instance of the object. HRESULT SampleGrabberCB::CreateInstance(const struct tmedia_producer_s* pcWrappedProducer, SampleGrabberCB **ppCB) { - assert(pcWrappedProducer); + assert(pcWrappedProducer); - *ppCB = new (std::nothrow) SampleGrabberCB(pcWrappedProducer); + *ppCB = new (std::nothrow) SampleGrabberCB(pcWrappedProducer); - if (ppCB == NULL) - { - return E_OUTOFMEMORY; - } - return S_OK; + if (ppCB == NULL) { + return E_OUTOFMEMORY; + } + return S_OK; } STDMETHODIMP SampleGrabberCB::QueryInterface(REFIID riid, void** ppv) { - static const QITAB qit[] = - { - QITABENT(SampleGrabberCB, IMFSampleGrabberSinkCallback), - QITABENT(SampleGrabberCB, IMFClockStateSink), - { 0 } - }; - return QISearch(this, qit, riid, ppv); + static const QITAB qit[] = { + QITABENT(SampleGrabberCB, IMFSampleGrabberSinkCallback), + QITABENT(SampleGrabberCB, IMFClockStateSink), + { 0 } + }; + return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) SampleGrabberCB::AddRef() { - return InterlockedIncrement(&m_cRef); + return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) SampleGrabberCB::Release() { - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - { - delete this; - } - return cRef; + ULONG cRef = InterlockedDecrement(&m_cRef); + if (cRef == 0) { + delete this; + } + return cRef; } // IMFClockStateSink methods. -// In these example, the IMFClockStateSink methods do not perform any actions. +// In these example, the IMFClockStateSink methods do not perform any actions. // You can use these methods to track the state of the sample grabber sink. STDMETHODIMP SampleGrabberCB::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) { - TSK_DEBUG_INFO("SampleGrabberCB::OnClockStart(%lld, %lld)", hnsSystemTime, llClockStartOffset); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnClockStart(%lld, %lld)", hnsSystemTime, llClockStartOffset); + return S_OK; } STDMETHODIMP SampleGrabberCB::OnClockStop(MFTIME hnsSystemTime) { - TSK_DEBUG_INFO("SampleGrabberCB::OnClockStop(%lld)", hnsSystemTime); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnClockStop(%lld)", hnsSystemTime); + return S_OK; } STDMETHODIMP SampleGrabberCB::OnClockPause(MFTIME hnsSystemTime) { - TSK_DEBUG_INFO("SampleGrabberCB::OnClockPause(%lld)", hnsSystemTime); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnClockPause(%lld)", hnsSystemTime); + return S_OK; } STDMETHODIMP SampleGrabberCB::OnClockRestart(MFTIME hnsSystemTime) { - TSK_DEBUG_INFO("SampleGrabberCB::OnClockRestart(%lld)", hnsSystemTime); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnClockRestart(%lld)", hnsSystemTime); + return S_OK; } STDMETHODIMP SampleGrabberCB::OnClockSetRate(MFTIME hnsSystemTime, float flRate) { - TSK_DEBUG_INFO("SampleGrabberCB::OnClockSetRate(%lld, %f)", hnsSystemTime, flRate); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnClockSetRate(%lld, %f)", hnsSystemTime, flRate); + return S_OK; } // IMFSampleGrabberSink methods. STDMETHODIMP SampleGrabberCB::OnSetPresentationClock(IMFPresentationClock* pClock) { - TSK_DEBUG_INFO("SampleGrabberCB::OnSetPresentationClock"); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnSetPresentationClock"); + return S_OK; } STDMETHODIMP SampleGrabberCB::OnProcessSample( - REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize) + REFGUID guidMajorMediaType, DWORD dwSampleFlags, + LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, + DWORD dwSampleSize) { - if (m_pWrappedProducer && TMEDIA_PRODUCER(m_pWrappedProducer)->enc_cb.callback) { + if (m_pWrappedProducer && TMEDIA_PRODUCER(m_pWrappedProducer)->enc_cb.callback) { #if 1 - if (m_bMuted) { - // Send zeros. Do not skip sending data to avoid NAT issues and session deconnection. - // Some TelePresence systems disconnect the session when the remote peer stops sending video data. - memset((void*)pSampleBuffer, 0, dwSampleSize); - } + if (m_bMuted) { + // Send zeros. Do not skip sending data to avoid NAT issues and session deconnection. + // Some TelePresence systems disconnect the session when the remote peer stops sending video data. + memset((void*)pSampleBuffer, 0, dwSampleSize); + } #endif - TMEDIA_PRODUCER(m_pWrappedProducer)->enc_cb.callback(TMEDIA_PRODUCER(m_pWrappedProducer)->enc_cb.callback_data, pSampleBuffer, dwSampleSize); - } + TMEDIA_PRODUCER(m_pWrappedProducer)->enc_cb.callback(TMEDIA_PRODUCER(m_pWrappedProducer)->enc_cb.callback_data, pSampleBuffer, dwSampleSize); + } - return S_OK; + return S_OK; } STDMETHODIMP SampleGrabberCB::OnShutdown() { - TSK_DEBUG_INFO("SampleGrabberCB::OnShutdown"); - return S_OK; + TSK_DEBUG_INFO("SampleGrabberCB::OnShutdown"); + return S_OK; }
\ No newline at end of file diff --git a/plugins/pluginWinMF/internals/mf_sample_grabber.h b/plugins/pluginWinMF/internals/mf_sample_grabber.h index 858f3c1..9ea239d 100755 --- a/plugins/pluginWinMF/internals/mf_sample_grabber.h +++ b/plugins/pluginWinMF/internals/mf_sample_grabber.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -31,9 +31,9 @@ // Sample Grabber callback [Declaration] // http://msdn.microsoft.com/en-us/library/windows/desktop/hh184779(v=vs.85).aspx // -class SampleGrabberCB : public IMFSampleGrabberSinkCallback +class SampleGrabberCB : public IMFSampleGrabberSinkCallback { - bool m_bMuted; + bool m_bMuted; long m_cRef; const struct tmedia_producer_s* m_pWrappedProducer; @@ -42,7 +42,9 @@ class SampleGrabberCB : public IMFSampleGrabberSinkCallback public: static HRESULT CreateInstance(const struct tmedia_producer_s* pcWrappedProducer, SampleGrabberCB **ppCB); - void SetMute(bool bMuted) { m_bMuted = bMuted; } + void SetMute(bool bMuted) { + m_bMuted = bMuted; + } // IUnknown methods STDMETHODIMP QueryInterface(REFIID iid, void** ppv); @@ -59,8 +61,8 @@ public: // IMFSampleGrabberSinkCallback methods STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock); STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize); + LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, + DWORD dwSampleSize); STDMETHODIMP OnShutdown(); }; diff --git a/plugins/pluginWinMF/internals/mf_sample_queue.cxx b/plugins/pluginWinMF/internals/mf_sample_queue.cxx index 05c2bc6..32630b8 100755 --- a/plugins/pluginWinMF/internals/mf_sample_queue.cxx +++ b/plugins/pluginWinMF/internals/mf_sample_queue.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -21,39 +21,38 @@ #include <assert.h> MFSampleQueue::MFSampleQueue() -: m_nRefCount(1) -, m_nCount(0) + : m_nRefCount(1) + , m_nCount(0) { - InitializeCriticalSection(&m_critSec); + InitializeCriticalSection(&m_critSec); - m_anchor.next = &m_anchor; - m_anchor.prev = &m_anchor; + m_anchor.next = &m_anchor; + m_anchor.prev = &m_anchor; } MFSampleQueue::~MFSampleQueue() { - assert(m_nRefCount == 0); + assert(m_nRefCount == 0); - Clear(); + Clear(); - DeleteCriticalSection(&m_critSec); + DeleteCriticalSection(&m_critSec); } STDMETHODIMP MFSampleQueue::QueryInterface(REFIID iid, void** ppv) { - return E_NOTIMPL; + return E_NOTIMPL; } STDMETHODIMP_(ULONG) MFSampleQueue::AddRef() { - return InterlockedIncrement(&m_nRefCount); + return InterlockedIncrement(&m_nRefCount); } STDMETHODIMP_(ULONG) MFSampleQueue::Release() { - ULONG uCount = InterlockedDecrement(&m_nRefCount); - if (uCount == 0) - { + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) { delete this; } // For thread safety, return a temporary variable. @@ -62,20 +61,18 @@ STDMETHODIMP_(ULONG) MFSampleQueue::Release() HRESULT MFSampleQueue::Queue(IMFSample* item) { - if (item == NULL) - { + if (item == NULL) { return E_POINTER; } Node *pNode = new (std::nothrow) Node(item); - if (pNode == NULL) - { + if (pNode == NULL) { return E_OUTOFMEMORY; } item->AddRef(); - EnterCriticalSection(&m_critSec); + EnterCriticalSection(&m_critSec); Node *pBefore = m_anchor.prev; @@ -87,25 +84,23 @@ HRESULT MFSampleQueue::Queue(IMFSample* item) pNode->prev = pBefore; pNode->next = pAfter; - m_nCount++; + m_nCount++; - LeaveCriticalSection(&m_critSec); + LeaveCriticalSection(&m_critSec); return S_OK; } -HRESULT MFSampleQueue::Dequeue(IMFSample* *ppItem) +HRESULT MFSampleQueue::Dequeue(IMFSample**ppItem) { - if (ppItem == NULL) - { + if (ppItem == NULL) { return E_POINTER; } - EnterCriticalSection(&m_critSec); + EnterCriticalSection(&m_critSec); - if (IsEmpty()) - { - LeaveCriticalSection(&m_critSec); + if (IsEmpty()) { + LeaveCriticalSection(&m_critSec); return E_FAIL; } @@ -120,24 +115,22 @@ HRESULT MFSampleQueue::Dequeue(IMFSample* *ppItem) *ppItem = pNode->item; delete pNode; - m_nCount--; + m_nCount--; - LeaveCriticalSection(&m_critSec); + LeaveCriticalSection(&m_critSec); return S_OK; } HRESULT MFSampleQueue::Clear() { - EnterCriticalSection(&m_critSec); + EnterCriticalSection(&m_critSec); - Node *n = m_anchor.next; + Node *n = m_anchor.next; // Delete the nodes - while (n != &m_anchor) - { - if (n->item) - { + while (n != &m_anchor) { + if (n->item) { n->item->Release(); } @@ -150,9 +143,9 @@ HRESULT MFSampleQueue::Clear() m_anchor.next = &m_anchor; m_anchor.prev = &m_anchor; - m_nCount = 0; + m_nCount = 0; - LeaveCriticalSection(&m_critSec); + LeaveCriticalSection(&m_critSec); - return S_OK; + return S_OK; } diff --git a/plugins/pluginWinMF/internals/mf_sample_queue.h b/plugins/pluginWinMF/internals/mf_sample_queue.h index b42ecde..b110a06 100755 --- a/plugins/pluginWinMF/internals/mf_sample_queue.h +++ b/plugins/pluginWinMF/internals/mf_sample_queue.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -32,49 +32,52 @@ class MFSampleQueue : public IUnknown protected: // Nodes in the linked list - struct Node - { + struct Node { Node *prev; Node *next; IMFSample* item; - Node() : prev(NULL), next(NULL) - { + Node() : prev(NULL), next(NULL) { } - Node(IMFSample* item) : prev(NULL), next(NULL) - { + Node(IMFSample* item) : prev(NULL), next(NULL) { this->item = item; } - IMFSample* Item() const { return item; } + IMFSample* Item() const { + return item; + } }; protected: Node m_anchor; - long m_nCount; - CRITICAL_SECTION m_critSec; + long m_nCount; + CRITICAL_SECTION m_critSec; private: - long m_nRefCount; + long m_nRefCount; public: MFSampleQueue(); virtual ~MFSampleQueue(); - // IUnknown + // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); HRESULT Queue(IMFSample* item); - HRESULT Dequeue(IMFSample* *ppItem); + HRESULT Dequeue(IMFSample**ppItem); HRESULT Clear(); - inline BOOL IsEmpty() const { return m_anchor.next == &m_anchor; } - inline long Count() { return m_nCount; } + inline BOOL IsEmpty() const { + return m_anchor.next == &m_anchor; + } + inline long Count() { + return m_nCount; + } }; diff --git a/plugins/pluginWinMF/internals/mf_utils.cxx b/plugins/pluginWinMF/internals/mf_utils.cxx index d1f326c..bcb63f1 100755 --- a/plugins/pluginWinMF/internals/mf_utils.cxx +++ b/plugins/pluginWinMF/internals/mf_utils.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -74,35 +74,34 @@ const TOPOID MFUtils::g_ullTopoIdSource = 333; const TOPOID MFUtils::g_ullTopoIdVideoProcessor = 444; // Preferred VideoSubTypes -static const VideoSubTypeGuidPair PreferredVideoSubTypeGuidPairs[] = -{ - { tmedia_chroma_yuv420p, MFVideoFormat_I420 }, - { tmedia_chroma_nv12, MFVideoFormat_NV12 }, - { tmedia_chroma_uyvy422, MFVideoFormat_UYVY }, - { tmedia_chroma_yuyv422, MFVideoFormat_YUY2 }, - /* TODO: Add more YUV formats */ - { tmedia_chroma_rgb565le, MFVideoFormat_RGB565 }, - { tmedia_chroma_bgr24, MFVideoFormat_RGB24 }, - { tmedia_chroma_rgb32, MFVideoFormat_RGB32 }, +static const VideoSubTypeGuidPair PreferredVideoSubTypeGuidPairs[] = { + { tmedia_chroma_yuv420p, MFVideoFormat_I420 }, + { tmedia_chroma_nv12, MFVideoFormat_NV12 }, + { tmedia_chroma_uyvy422, MFVideoFormat_UYVY }, + { tmedia_chroma_yuyv422, MFVideoFormat_YUY2 }, + /* TODO: Add more YUV formats */ + { tmedia_chroma_rgb565le, MFVideoFormat_RGB565 }, + { tmedia_chroma_bgr24, MFVideoFormat_RGB24 }, + { tmedia_chroma_rgb32, MFVideoFormat_RGB32 }, }; static const tsk_size_t PreferredVideoSubTypeGuidPairsCount = sizeof(PreferredVideoSubTypeGuidPairs)/sizeof(PreferredVideoSubTypeGuidPairs[0]); // Video Processor -DEFINE_GUID(CLSID_VideoProcessorMFT, - 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82); +DEFINE_GUID(CLSID_VideoProcessorMFT, + 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82); // {4BE8D3C0-0515-4A37-AD55-E4BAE19AF471} DEFINE_GUID(CLSID_MF_INTEL_H264EncFilter, // Intel Quick Sync Encoder -0x4be8d3c0, 0x0515, 0x4a37, 0xad, 0x55, 0xe4, 0xba, 0xe1, 0x9a, 0xf4, 0x71); + 0x4be8d3c0, 0x0515, 0x4a37, 0xad, 0x55, 0xe4, 0xba, 0xe1, 0x9a, 0xf4, 0x71); // {0855C9AC-BC6F-4371-8954-671CCD4EC16F} DEFINE_GUID(CLSID_MF_INTEL_H264DecFilter, // Intel Quick Sync Decoder -0x0855c9ac, 0xbc6f, 0x4371, 0x89, 0x54, 0x67, 0x1c, 0xcd, 0x4e, 0xc1, 0x6f); + 0x0855c9ac, 0xbc6f, 0x4371, 0x89, 0x54, 0x67, 0x1c, 0xcd, 0x4e, 0xc1, 0x6f); #if WINVER < 0x0602/* From "sdkddkver.h" and defines the SDK version not the host */ // 6ca50344-051a-4ded-9779-a43305165e35 DEFINE_GUID(CLSID_CMSH264EncoderMFT, // MS H.264 encoder -0x6ca50344, 0x051a, 0x4ded, 0x97, 0x79, 0xa4, 0x33, 0x05, 0x16, 0x5e, 0x35); + 0x6ca50344, 0x051a, 0x4ded, 0x97, 0x79, 0xa4, 0x33, 0x05, 0x16, 0x5e, 0x35); #endif /* WINVER */ #define IsWin7_OrLater(dwMajorVersion, dwMinorVersion) ( (dwMajorVersion > 6) || ( (dwMajorVersion == 6) && (dwMinorVersion >= 1) ) ) @@ -111,249 +110,231 @@ DEFINE_GUID(CLSID_CMSH264EncoderMFT, // MS H.264 encoder HRESULT MFUtils::Startup() { - if(!g_bStarted) - { - HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - if(SUCCEEDED(hr) || hr == 0x80010106) // 0x80010106 when called from managed code (e.g. Boghe) - More info: http://support.microsoft.com/kb/824480 - { - hr = MFStartup(MF_VERSION); - } - g_bStarted = SUCCEEDED(hr); - - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - g_dwMajorVersion = osvi.dwMajorVersion; - g_dwMinorVersion = osvi.dwMinorVersion; - - return hr; - } - return S_OK; + if(!g_bStarted) { + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if(SUCCEEDED(hr) || hr == 0x80010106) { // 0x80010106 when called from managed code (e.g. Boghe) - More info: http://support.microsoft.com/kb/824480 + hr = MFStartup(MF_VERSION); + } + g_bStarted = SUCCEEDED(hr); + + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + g_dwMajorVersion = osvi.dwMajorVersion; + g_dwMinorVersion = osvi.dwMinorVersion; + + return hr; + } + return S_OK; } HRESULT MFUtils::Shutdown() { - if(g_bStarted) - { - g_bStarted = false; - return S_OK; - } - return S_OK; + if(g_bStarted) { + g_bStarted = false; + return S_OK; + } + return S_OK; } BOOL MFUtils::IsD3D9Supported() { - if (MFUtils::g_bD3D9Checked) - { - return MFUtils::g_bD3D9Supported; - } - MFUtils::g_bD3D9Checked = TRUE; - HRESULT hr = S_OK; - IDirect3D9* pD3D = NULL; - D3DDISPLAYMODE mode = { 0 }; - D3DPRESENT_PARAMETERS pp = {0}; - IDirect3DDevice9* pDevice = NULL; - - CHECK_HR(hr = MFUtils::Startup()); - - if (!(pD3D = Direct3DCreate9(D3D_SDK_VERSION))) - { + if (MFUtils::g_bD3D9Checked) { + return MFUtils::g_bD3D9Supported; + } + MFUtils::g_bD3D9Checked = TRUE; + HRESULT hr = S_OK; + IDirect3D9* pD3D = NULL; + D3DDISPLAYMODE mode = { 0 }; + D3DPRESENT_PARAMETERS pp = {0}; + IDirect3DDevice9* pDevice = NULL; + + CHECK_HR(hr = MFUtils::Startup()); + + if (!(pD3D = Direct3DCreate9(D3D_SDK_VERSION))) { CHECK_HR(hr = E_OUTOFMEMORY); } hr = pD3D->GetAdapterDisplayMode( - D3DADAPTER_DEFAULT, - &mode - ); - if (FAILED(hr)) - { - goto bail; - } + D3DADAPTER_DEFAULT, + &mode + ); + if (FAILED(hr)) { + goto bail; + } hr = pD3D->CheckDeviceType( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - mode.Format, - D3DFMT_X8R8G8B8, - TRUE // windowed - ); - if (FAILED(hr)) - { - goto bail; - } + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + mode.Format, + D3DFMT_X8R8G8B8, + TRUE // windowed + ); + if (FAILED(hr)) { + goto bail; + } pp.BackBufferFormat = D3DFMT_X8R8G8B8; pp.SwapEffect = D3DSWAPEFFECT_DISCARD; pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - pp.Windowed = TRUE; - pp.hDeviceWindow = GetDesktopWindow(); + pp.Windowed = TRUE; + pp.hDeviceWindow = GetDesktopWindow(); hr = pD3D->CreateDevice( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - pp.hDeviceWindow, - D3DCREATE_HARDWARE_VERTEXPROCESSING, - &pp, - &pDevice - ); - if (FAILED(hr)) - { - goto bail; - } - - // Everythings is OK - MFUtils::g_bD3D9Supported = TRUE; - TSK_DEBUG_INFO("D3D9 supported"); + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pp.hDeviceWindow, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &pp, + &pDevice + ); + if (FAILED(hr)) { + goto bail; + } + + // Everythings is OK + MFUtils::g_bD3D9Supported = TRUE; + TSK_DEBUG_INFO("D3D9 supported"); bail: - if (!MFUtils::g_bD3D9Supported) { - TSK_DEBUG_WARN("D3D9 not supported"); - } - SafeRelease(&pDevice); - SafeRelease(&pD3D); - return MFUtils::g_bD3D9Supported; + if (!MFUtils::g_bD3D9Supported) { + TSK_DEBUG_WARN("D3D9 not supported"); + } + SafeRelease(&pDevice); + SafeRelease(&pD3D); + return MFUtils::g_bD3D9Supported; } BOOL MFUtils::IsLowLatencyH264Supported() { - if(MFUtils::g_bLowLatencyH264Checked) - { - return MFUtils::g_bLowLatencyH264Supported; - } + if(MFUtils::g_bLowLatencyH264Checked) { + return MFUtils::g_bLowLatencyH264Supported; + } #if PLUGIN_MF_DISABLE_CODECS - MFUtils::g_bLowLatencyH264Checked = TRUE; - MFUtils::g_bLowLatencyH264Supported = FALSE; + MFUtils::g_bLowLatencyH264Checked = TRUE; + MFUtils::g_bLowLatencyH264Supported = FALSE; #else - Startup(); - - HRESULT hr = S_OK; - IMFTransform *pEncoderMFT = NULL; - IMFTransform *pDecoderMFT = NULL; - MFCodecVideoH264* pEncoderCodec = NULL; - MFCodecVideoH264* pDecoderCodec = NULL; - - static const BOOL IsEncoderYes = TRUE; - - // Encoder - hr = MFUtils::GetBestCodec(IsEncoderYes, MFMediaType_Video, MFVideoFormat_NV12, MFVideoFormat_H264, &pEncoderMFT); - if(FAILED(hr)) - { - TSK_DEBUG_INFO("No low latency H.264 encoder"); - goto bail; - } - - // Decoder - hr = MFUtils::GetBestCodec(!IsEncoderYes, MFMediaType_Video, MFVideoFormat_H264, MFVideoFormat_NV12, &pDecoderMFT); - if(FAILED(hr)) - { - TSK_DEBUG_INFO("No low latency H.264 decoder"); - goto bail; - } - - // Make sure both encoder and decoder are working well. Check encoding/decoding 1080p@30 would work. - - TSK_DEBUG_INFO("Probing H.264 MFT encoder..."); - pEncoderCodec = MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Encoder, pEncoderMFT); - if(!pEncoderCodec) - { - CHECK_HR(hr = E_FAIL); - } - CHECK_HR(hr = pEncoderCodec->Initialize( - 30, // FPS - 1920, // WIDTH - 1080, // HEIGHT - tmedia_get_video_bandwidth_kbps_2(1920, 1080, 30) * 1024) // BITRATE - ); - CHECK_HR(pEncoderCodec->IsSetSliceMaxSizeInBytesSupported(MFUtils::g_bLowLatencyH264SupportsMaxSliceSize)); - - TSK_DEBUG_INFO("Probing H.264 MFT decoder..."); - pDecoderCodec = MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Decoder, pDecoderMFT); - if(!pDecoderCodec) - { - CHECK_HR(hr = E_FAIL); - } - CHECK_HR(hr = pDecoderCodec->Initialize( - 30, // FPS - 1920, // WIDTH - 1080 // HEIGHT - )); + Startup(); + + HRESULT hr = S_OK; + IMFTransform *pEncoderMFT = NULL; + IMFTransform *pDecoderMFT = NULL; + MFCodecVideoH264* pEncoderCodec = NULL; + MFCodecVideoH264* pDecoderCodec = NULL; + + static const BOOL IsEncoderYes = TRUE; + + // Encoder + hr = MFUtils::GetBestCodec(IsEncoderYes, MFMediaType_Video, MFVideoFormat_NV12, MFVideoFormat_H264, &pEncoderMFT); + if(FAILED(hr)) { + TSK_DEBUG_INFO("No low latency H.264 encoder"); + goto bail; + } + + // Decoder + hr = MFUtils::GetBestCodec(!IsEncoderYes, MFMediaType_Video, MFVideoFormat_H264, MFVideoFormat_NV12, &pDecoderMFT); + if(FAILED(hr)) { + TSK_DEBUG_INFO("No low latency H.264 decoder"); + goto bail; + } + + // Make sure both encoder and decoder are working well. Check encoding/decoding 1080p@30 would work. + + TSK_DEBUG_INFO("Probing H.264 MFT encoder..."); + pEncoderCodec = MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Encoder, pEncoderMFT); + if(!pEncoderCodec) { + CHECK_HR(hr = E_FAIL); + } + CHECK_HR(hr = pEncoderCodec->Initialize( + 30, // FPS + 1920, // WIDTH + 1080, // HEIGHT + tmedia_get_video_bandwidth_kbps_2(1920, 1080, 30) * 1024) // BITRATE + ); + CHECK_HR(pEncoderCodec->IsSetSliceMaxSizeInBytesSupported(MFUtils::g_bLowLatencyH264SupportsMaxSliceSize)); + + TSK_DEBUG_INFO("Probing H.264 MFT decoder..."); + pDecoderCodec = MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Decoder, pDecoderMFT); + if(!pDecoderCodec) { + CHECK_HR(hr = E_FAIL); + } + CHECK_HR(hr = pDecoderCodec->Initialize( + 30, // FPS + 1920, // WIDTH + 1080 // HEIGHT + )); bail: - MFUtils::g_bLowLatencyH264Checked = TRUE; - MFUtils::g_bLowLatencyH264Supported = SUCCEEDED(hr) ? TRUE : FALSE; - SafeRelease(&pEncoderMFT); - SafeRelease(&pEncoderCodec); - SafeRelease(&pDecoderMFT); - SafeRelease(&pDecoderCodec); + MFUtils::g_bLowLatencyH264Checked = TRUE; + MFUtils::g_bLowLatencyH264Supported = SUCCEEDED(hr) ? TRUE : FALSE; + SafeRelease(&pEncoderMFT); + SafeRelease(&pEncoderCodec); + SafeRelease(&pDecoderMFT); + SafeRelease(&pDecoderCodec); #endif /* PLUGIN_MF_DISABLE_CODECS */ - return MFUtils::g_bLowLatencyH264Supported; + return MFUtils::g_bLowLatencyH264Supported; } BOOL MFUtils::IsLowLatencyH264SupportsMaxSliceSize() { - return MFUtils::IsLowLatencyH264Supported() && MFUtils::g_bLowLatencyH264SupportsMaxSliceSize; + return MFUtils::IsLowLatencyH264Supported() && MFUtils::g_bLowLatencyH264SupportsMaxSliceSize; } HRESULT MFUtils::IsAsyncMFT( - IMFTransform *pMFT, // The MFT to check - BOOL* pbIsAsync // Whether the MFT is Async - ) + IMFTransform *pMFT, // The MFT to check + BOOL* pbIsAsync // Whether the MFT is Async +) { - if(!pbIsAsync || !pMFT) - { - return E_POINTER; - } + if(!pbIsAsync || !pMFT) { + return E_POINTER; + } - IMFAttributes *pAttributes = NULL; - UINT32 nIsAsync = 0; - HRESULT hr = S_OK; + IMFAttributes *pAttributes = NULL; + UINT32 nIsAsync = 0; + HRESULT hr = S_OK; hr = pMFT->GetAttributes(&pAttributes); - if(SUCCEEDED(hr)) - { - hr = pAttributes->GetUINT32(MF_TRANSFORM_ASYNC, &nIsAsync); - } - - // Never fails: just say not Async - CHECK_HR(hr = S_OK); + if(SUCCEEDED(hr)) { + hr = pAttributes->GetUINT32(MF_TRANSFORM_ASYNC, &nIsAsync); + } + + // Never fails: just say not Async + CHECK_HR(hr = S_OK); - *pbIsAsync = !!nIsAsync; + *pbIsAsync = !!nIsAsync; bail: - return hr; + return hr; } HRESULT MFUtils::UnlockAsyncMFT( - IMFTransform *pMFT // The MFT to unlock - ) + IMFTransform *pMFT // The MFT to unlock +) { - IMFAttributes *pAttributes = NULL; - UINT32 nValue = 0; - HRESULT hr = S_OK; + IMFAttributes *pAttributes = NULL; + UINT32 nValue = 0; + HRESULT hr = S_OK; hr = pMFT->GetAttributes(&pAttributes); - if(FAILED(hr)) - { - hr = S_OK; - goto bail; - } - - hr = pAttributes->GetUINT32(MF_TRANSFORM_ASYNC, &nValue); - if(FAILED(hr)) - { - hr = S_OK; - goto bail; - } - - if(nValue == TRUE) - { - CHECK_HR(hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE)); - } - + if(FAILED(hr)) { + hr = S_OK; + goto bail; + } + + hr = pAttributes->GetUINT32(MF_TRANSFORM_ASYNC, &nValue); + if(FAILED(hr)) { + hr = S_OK; + goto bail; + } + + if(nValue == TRUE) { + CHECK_HR(hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE)); + } + bail: - SafeRelease(&pAttributes); - return hr; + SafeRelease(&pAttributes); + return hr; } //------------------------------------------------------------------- // CreatePCMAudioType @@ -367,7 +348,7 @@ HRESULT MFUtils::CreatePCMAudioType( UINT32 bitsPerSample, // Bits per sample UINT32 cChannels, // Number of channels IMFMediaType **ppType // Receives a pointer to the media type. - ) +) { HRESULT hr = S_OK; @@ -381,48 +362,39 @@ HRESULT MFUtils::CreatePCMAudioType( hr = MFCreateMediaType(&pType); // Set attributes on the type. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, cChannels); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, sampleRate); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, blockAlign); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, bytesPerSecond); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { // Return the type to the caller. *ppType = pType; (*ppType)->AddRef(); @@ -440,13 +412,13 @@ HRESULT MFUtils::CreatePCMAudioType( // format. //------------------------------------------------------------------- HRESULT MFUtils::CreateVideoType( - const GUID* subType, // video subType - IMFMediaType **ppType, // Receives a pointer to the media type. - UINT32 unWidth, // Video width (0 to ignore) - UINT32 unHeight // Video height (0 to ignore) - ) + const GUID* subType, // video subType + IMFMediaType **ppType, // Receives a pointer to the media type. + UINT32 unWidth, // Video width (0 to ignore) + UINT32 unHeight // Video height (0 to ignore) +) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; IMFMediaType *pType = NULL; @@ -456,17 +428,16 @@ HRESULT MFUtils::CreateVideoType( CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, *subType)); - CHECK_HR(hr = pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); // UnCompressed + CHECK_HR(hr = pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); // UnCompressed - CHECK_HR(hr = pType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE)); // UnCompressed + CHECK_HR(hr = pType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE)); // UnCompressed - CHECK_HR(hr = pType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); + CHECK_HR(hr = pType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); + + if(unWidth > 0 && unHeight > 0) { + CHECK_HR(hr = MFSetAttributeSize(pType, MF_MT_FRAME_SIZE, unWidth, unHeight)); + } - if(unWidth > 0 && unHeight > 0) - { - CHECK_HR(hr = MFSetAttributeSize(pType, MF_MT_FRAME_SIZE, unWidth, unHeight)); - } - *ppType = pType; (*ppType)->AddRef(); @@ -481,7 +452,7 @@ bail: //------------------------------------------------------------------- HRESULT MFUtils::ValidateVideoFormat(IMFMediaType *pmt) { - GUID major_type = GUID_NULL; + GUID major_type = GUID_NULL; GUID subtype = GUID_NULL; MFVideoInterlaceMode interlace = MFVideoInterlace_Unknown; UINT32 val = 0; @@ -492,8 +463,7 @@ HRESULT MFUtils::ValidateVideoFormat(IMFMediaType *pmt) // Major type must be video. CHECK_HR(hr = pmt->GetGUID(MF_MT_MAJOR_TYPE, &major_type)); - if (major_type != MFMediaType_Video) - { + if (major_type != MFMediaType_Video) { CHECK_HR(hr = MF_E_INVALIDMEDIATYPE); } @@ -504,24 +474,20 @@ HRESULT MFUtils::ValidateVideoFormat(IMFMediaType *pmt) #if 0 // Look for the subtype in our list of accepted types. - for (DWORD i = 0; i < g_NumVideoSubtypes; i++) - { - if (subtype == *g_VideoSubtypes[i]) - { + for (DWORD i = 0; i < g_NumVideoSubtypes; i++) { + if (subtype == *g_VideoSubtypes[i]) { bFoundMatchingSubtype = TRUE; break; } } - if (!bFoundMatchingSubtype) - { + if (!bFoundMatchingSubtype) { CHECK_HR(hr = MF_E_INVALIDMEDIATYPE); } #endif // Video must be progressive frames. CHECK_HR(hr = pmt->GetUINT32(MF_MT_INTERLACE_MODE, (UINT32*)&interlace)); - if (interlace != MFVideoInterlace_Progressive) - { + if (interlace != MFVideoInterlace_Progressive) { CHECK_HR(hr = MF_E_INVALIDMEDIATYPE); } @@ -533,9 +499,9 @@ HRESULT MFUtils::ConvertVideoTypeToUncompressedType( IMFMediaType *pType, // Pointer to an encoded video type. const GUID& subtype, // Uncompressed subtype (eg, RGB-32, AYUV) IMFMediaType **ppType // Receives a matching uncompressed video type. - ) +) { - IMFMediaType *pTypeUncomp = NULL; + IMFMediaType *pTypeUncomp = NULL; HRESULT hr = S_OK; GUID majortype = { 0 }; @@ -543,59 +509,51 @@ HRESULT MFUtils::ConvertVideoTypeToUncompressedType( hr = pType->GetMajorType(&majortype); - if (majortype != MFMediaType_Video) - { + if (majortype != MFMediaType_Video) { return MF_E_INVALIDMEDIATYPE; } // Create a new media type and copy over all of the items. // This ensures that extended color information is retained. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = MFCreateMediaType(&pTypeUncomp); } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pType->CopyAllItems(pTypeUncomp); } // Set the subtype. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pTypeUncomp->SetGUID(MF_MT_SUBTYPE, subtype); } // Uncompressed means all samples are independent. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pTypeUncomp->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); } // Fix up PAR if not set on the original type. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = MFGetAttributeRatio( - pTypeUncomp, - MF_MT_PIXEL_ASPECT_RATIO, - (UINT32*)&par.Numerator, - (UINT32*)&par.Denominator - ); + pTypeUncomp, + MF_MT_PIXEL_ASPECT_RATIO, + (UINT32*)&par.Numerator, + (UINT32*)&par.Denominator + ); // Default to square pixels. - if (FAILED(hr)) - { + if (FAILED(hr)) { hr = MFSetAttributeRatio( - pTypeUncomp, - MF_MT_PIXEL_ASPECT_RATIO, - 1, 1 - ); + pTypeUncomp, + MF_MT_PIXEL_ASPECT_RATIO, + 1, 1 + ); } } - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { *ppType = pTypeUncomp; (*ppType)->AddRef(); } @@ -605,21 +563,21 @@ HRESULT MFUtils::ConvertVideoTypeToUncompressedType( } HRESULT MFUtils::CreateMediaSample( - DWORD cbData, // Maximum buffer size - IMFSample **ppSample // Receives the sample + DWORD cbData, // Maximum buffer size + IMFSample **ppSample // Receives the sample ) { - assert(ppSample); + assert(ppSample); - HRESULT hr = S_OK; + HRESULT hr = S_OK; IMFSample *pSample = NULL; IMFMediaBuffer *pBuffer = NULL; - CHECK_HR(hr = MFCreateSample(&pSample)); - CHECK_HR(hr = MFCreateMemoryBuffer(cbData, &pBuffer)); + CHECK_HR(hr = MFCreateSample(&pSample)); + CHECK_HR(hr = MFCreateMemoryBuffer(cbData, &pBuffer)); CHECK_HR(hr = pSample->AddBuffer(pBuffer)); - + *ppSample = pSample; (*ppSample)->AddRef(); @@ -631,222 +589,198 @@ bail: // Gets the best encoder and decoder. Up to the caller to release the returned pointer HRESULT MFUtils::GetBestCodec( - BOOL bEncoder, // Whether we request an encoder or not (TRUE=encoder, FALSE=decoder) - const GUID& mediaType, // The MediaType - const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_NV12) - const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_H264) - IMFTransform **ppMFT // Receives the decoder/encoder transform - ) + BOOL bEncoder, // Whether we request an encoder or not (TRUE=encoder, FALSE=decoder) + const GUID& mediaType, // The MediaType + const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_NV12) + const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_H264) + IMFTransform **ppMFT // Receives the decoder/encoder transform +) { - assert(ppMFT); - assert(mediaType == MFMediaType_Video || mediaType == MFMediaType_Audio); // only audio and video codecs are support for now - - *ppMFT = NULL; - - HRESULT hr = S_OK; - - if(outputFormat == MFVideoFormat_H264 || inputFormat == MFVideoFormat_H264) - { - if(bEncoder) - { - // Force using Intel Quick Sync Encoder - hr = CoCreateInstance(CLSID_MF_INTEL_H264EncFilter, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppMFT)); - if(SUCCEEDED(hr) && *ppMFT) - { - TSK_DEBUG_INFO("Using Intel Quick Sync encoder :)"); - return hr; - } - TSK_DEBUG_INFO("Not using Intel Quick Sync encoder :("); - } - else - { + assert(ppMFT); + assert(mediaType == MFMediaType_Video || mediaType == MFMediaType_Audio); // only audio and video codecs are support for now + + *ppMFT = NULL; + + HRESULT hr = S_OK; + + if(outputFormat == MFVideoFormat_H264 || inputFormat == MFVideoFormat_H264) { + if(bEncoder) { + // Force using Intel Quick Sync Encoder + hr = CoCreateInstance(CLSID_MF_INTEL_H264EncFilter, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppMFT)); + if(SUCCEEDED(hr) && *ppMFT) { + TSK_DEBUG_INFO("Using Intel Quick Sync encoder :)"); + return hr; + } + TSK_DEBUG_INFO("Not using Intel Quick Sync encoder :("); + } + else { #if !PLUGIN_MF_DISABLE_ASYNC_DECODERS // Intel Quick Sync decoder is asynchronous - // Force using Intel Quick Sync Decoder - hr = CoCreateInstance(CLSID_MF_INTEL_H264DecFilter, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppMFT)); + // Force using Intel Quick Sync Decoder + hr = CoCreateInstance(CLSID_MF_INTEL_H264DecFilter, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppMFT)); #endif - if(SUCCEEDED(hr) && *ppMFT) - { - TSK_DEBUG_INFO("Using Intel Quick Sync decoder :)"); - return hr; - } - TSK_DEBUG_INFO("Not using Intel Quick Sync decoder :("); - } - } - - UINT32 count = 0; - BOOL bAsync = FALSE; - GUID guidActivateCLSID = GUID_NULL; - - IMFActivate **ppActivate = NULL; - - MFT_REGISTER_TYPE_INFO infoInput = { mediaType, inputFormat }; - MFT_REGISTER_TYPE_INFO infoOutput = { mediaType, outputFormat }; - - UINT32 unFlags = MFT_ENUM_FLAG_HARDWARE | - MFT_ENUM_FLAG_SYNCMFT | - MFT_ENUM_FLAG_ASYNCMFT | - MFT_ENUM_FLAG_LOCALMFT | - MFT_ENUM_FLAG_TRANSCODE_ONLY | // Otherwise Intel Quick Sync will not be listed - MFT_ENUM_FLAG_SORTANDFILTER; - - hr = MFTEnumEx( - (mediaType == MFMediaType_Video) ? (bEncoder ? MFT_CATEGORY_VIDEO_ENCODER : MFT_CATEGORY_VIDEO_DECODER) : (bEncoder ? MFT_CATEGORY_AUDIO_ENCODER : MFT_CATEGORY_AUDIO_DECODER), - unFlags, - (inputFormat == GUID_NULL) ? NULL : &infoInput, // Input type - (outputFormat == GUID_NULL) ? NULL : &infoOutput, // Output type - &ppActivate, - &count - ); - - for(UINT32 i = 0; i < count; ++i) - { - SafeRelease(ppMFT); - hr = ppActivate[i]->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guidActivateCLSID); - if(FAILED(hr)) - { - continue; - } - - if(bEncoder) - { - // Encoder - if(guidActivateCLSID == CLSID_CMSH264EncoderMFT) // MS H.264 encoder ? - { - if(PLUGIN_MF_DISABLE_MS_H264_ENCODER) - { - // Microsoft H.264 encoder is disabled - TSK_DEBUG_INFO("MS H.264 encoder is disabled...skipping"); - continue; - } - if(!IsWin8_OrLater(g_dwMajorVersion, g_dwMinorVersion)) - { - // Microsoft H.264 encoder doesn't support low latency on Win7. - TSK_DEBUG_INFO("MS H.264 encoder doesn't support low delay on (%ld, %ld)...skipping", g_dwMajorVersion, g_dwMinorVersion); - continue; - } - } - } - else - { - // Decoder - if(guidActivateCLSID == CLSID_CMSH264DecoderMFT) // MS H.264 decoder ? - { - if(!IsWin8_OrLater(g_dwMajorVersion, g_dwMinorVersion)) - { - // Microsoft H.264 decoder doesn't support low latency on Win7. - TSK_DEBUG_INFO("MS H.264 decoder doesn't support low delay on (%ld, %ld)...skipping", g_dwMajorVersion, g_dwMinorVersion); - continue; - } - } - } - - hr = ppActivate[i]->ActivateObject(IID_PPV_ARGS(ppMFT)); - if(SUCCEEDED(hr) && *ppMFT) // For now we just get the first one. FIXME: Give HW encoders/decoders higher priority. - { - if(bEncoder) - { - // Encoder - - } - else - { - // Decoder + if(SUCCEEDED(hr) && *ppMFT) { + TSK_DEBUG_INFO("Using Intel Quick Sync decoder :)"); + return hr; + } + TSK_DEBUG_INFO("Not using Intel Quick Sync decoder :("); + } + } + + UINT32 count = 0; + BOOL bAsync = FALSE; + GUID guidActivateCLSID = GUID_NULL; + + IMFActivate **ppActivate = NULL; + + MFT_REGISTER_TYPE_INFO infoInput = { mediaType, inputFormat }; + MFT_REGISTER_TYPE_INFO infoOutput = { mediaType, outputFormat }; + + UINT32 unFlags = MFT_ENUM_FLAG_HARDWARE | + MFT_ENUM_FLAG_SYNCMFT | + MFT_ENUM_FLAG_ASYNCMFT | + MFT_ENUM_FLAG_LOCALMFT | + MFT_ENUM_FLAG_TRANSCODE_ONLY | // Otherwise Intel Quick Sync will not be listed + MFT_ENUM_FLAG_SORTANDFILTER; + + hr = MFTEnumEx( + (mediaType == MFMediaType_Video) ? (bEncoder ? MFT_CATEGORY_VIDEO_ENCODER : MFT_CATEGORY_VIDEO_DECODER) : (bEncoder ? MFT_CATEGORY_AUDIO_ENCODER : MFT_CATEGORY_AUDIO_DECODER), + unFlags, + (inputFormat == GUID_NULL) ? NULL : &infoInput, // Input type + (outputFormat == GUID_NULL) ? NULL : &infoOutput, // Output type + &ppActivate, + &count + ); + + for(UINT32 i = 0; i < count; ++i) { + SafeRelease(ppMFT); + hr = ppActivate[i]->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guidActivateCLSID); + if(FAILED(hr)) { + continue; + } + + if(bEncoder) { + // Encoder + if(guidActivateCLSID == CLSID_CMSH264EncoderMFT) { // MS H.264 encoder ? + if(PLUGIN_MF_DISABLE_MS_H264_ENCODER) { + // Microsoft H.264 encoder is disabled + TSK_DEBUG_INFO("MS H.264 encoder is disabled...skipping"); + continue; + } + if(!IsWin8_OrLater(g_dwMajorVersion, g_dwMinorVersion)) { + // Microsoft H.264 encoder doesn't support low latency on Win7. + TSK_DEBUG_INFO("MS H.264 encoder doesn't support low delay on (%ld, %ld)...skipping", g_dwMajorVersion, g_dwMinorVersion); + continue; + } + } + } + else { + // Decoder + if(guidActivateCLSID == CLSID_CMSH264DecoderMFT) { // MS H.264 decoder ? + if(!IsWin8_OrLater(g_dwMajorVersion, g_dwMinorVersion)) { + // Microsoft H.264 decoder doesn't support low latency on Win7. + TSK_DEBUG_INFO("MS H.264 decoder doesn't support low delay on (%ld, %ld)...skipping", g_dwMajorVersion, g_dwMinorVersion); + continue; + } + } + } + + hr = ppActivate[i]->ActivateObject(IID_PPV_ARGS(ppMFT)); + if(SUCCEEDED(hr) && *ppMFT) { // For now we just get the first one. FIXME: Give HW encoders/decoders higher priority. + if(bEncoder) { + // Encoder + + } + else { + // Decoder #if PLUGIN_MF_DISABLE_ASYNC_DECODERS - hr = IsAsyncMFT(*ppMFT, &bAsync); - if(bAsync) - { - TSK_DEBUG_INFO("Skipping async decoder because not supported yet"); - continue; // Async decoders not supported yet - } + hr = IsAsyncMFT(*ppMFT, &bAsync); + if(bAsync) { + TSK_DEBUG_INFO("Skipping async decoder because not supported yet"); + continue; // Async decoders not supported yet + } #endif - } - break; - } - } - - for (UINT32 i = 0; i < count; i++) - { - ppActivate[i]->Release(); - } - CoTaskMemFree(ppActivate); - - return *ppMFT ? S_OK : MF_E_NOT_FOUND; + } + break; + } + } + + for (UINT32 i = 0; i < count; i++) { + ppActivate[i]->Release(); + } + CoTaskMemFree(ppActivate); + + return *ppMFT ? S_OK : MF_E_NOT_FOUND; } HRESULT MFUtils::IsVideoProcessorSupported(BOOL *pbSupported) { - HRESULT hr = S_OK; - IMFTransform *pTransform = NULL; - - if(!pbSupported) - { - CHECK_HR(hr = E_POINTER); - } - - hr = CoCreateInstance(CLSID_VideoProcessorMFT, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTransform)); - *pbSupported = SUCCEEDED(hr); - if(FAILED(hr)) - { - hr = S_OK; // not an error - } + HRESULT hr = S_OK; + IMFTransform *pTransform = NULL; + + if(!pbSupported) { + CHECK_HR(hr = E_POINTER); + } + + hr = CoCreateInstance(CLSID_VideoProcessorMFT, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTransform)); + *pbSupported = SUCCEEDED(hr); + if(FAILED(hr)) { + hr = S_OK; // not an error + } bail: - SafeRelease(&pTransform); - return hr; + SafeRelease(&pTransform); + return hr; } HRESULT MFUtils::GetBestVideoProcessor( - const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_I420) - const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_NV12) - IMFTransform **ppProcessor // Receives the video processor - ) + const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_I420) + const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_NV12) + IMFTransform **ppProcessor // Receives the video processor +) { - assert(ppProcessor); - - *ppProcessor = NULL; - - HRESULT hr = S_OK; - UINT32 count = 0; - - IMFActivate **ppActivate = NULL; - - MFT_REGISTER_TYPE_INFO infoInput = { MFMediaType_Video, inputFormat }; - MFT_REGISTER_TYPE_INFO infoOutput = { MFMediaType_Video, outputFormat }; - - UINT32 unFlags = MFT_ENUM_FLAG_HARDWARE | - MFT_ENUM_FLAG_SYNCMFT | - MFT_ENUM_FLAG_LOCALMFT | - MFT_ENUM_FLAG_SORTANDFILTER; - - hr = MFTEnumEx( - MFT_CATEGORY_VIDEO_PROCESSOR, - unFlags, - &infoInput, // Input type - &infoOutput, // Output type - &ppActivate, - &count - ); - - for(UINT32 i = 0; i < count; ++i) - { - hr = ppActivate[i]->ActivateObject(IID_PPV_ARGS(ppProcessor)); - if(SUCCEEDED(hr) && *ppProcessor) - { - break; - } - SafeRelease(ppProcessor); - } - - for (UINT32 i = 0; i < count; i++) - { - ppActivate[i]->Release(); - } - CoTaskMemFree(ppActivate); - - return *ppProcessor ? S_OK : MF_E_NOT_FOUND; + assert(ppProcessor); + + *ppProcessor = NULL; + + HRESULT hr = S_OK; + UINT32 count = 0; + + IMFActivate **ppActivate = NULL; + + MFT_REGISTER_TYPE_INFO infoInput = { MFMediaType_Video, inputFormat }; + MFT_REGISTER_TYPE_INFO infoOutput = { MFMediaType_Video, outputFormat }; + + UINT32 unFlags = MFT_ENUM_FLAG_HARDWARE | + MFT_ENUM_FLAG_SYNCMFT | + MFT_ENUM_FLAG_LOCALMFT | + MFT_ENUM_FLAG_SORTANDFILTER; + + hr = MFTEnumEx( + MFT_CATEGORY_VIDEO_PROCESSOR, + unFlags, + &infoInput, // Input type + &infoOutput, // Output type + &ppActivate, + &count + ); + + for(UINT32 i = 0; i < count; ++i) { + hr = ppActivate[i]->ActivateObject(IID_PPV_ARGS(ppProcessor)); + if(SUCCEEDED(hr) && *ppProcessor) { + break; + } + SafeRelease(ppProcessor); + } + + for (UINT32 i = 0; i < count; i++) { + ppActivate[i]->Release(); + } + CoTaskMemFree(ppActivate); + + return *ppProcessor ? S_OK : MF_E_NOT_FOUND; } // Add an transform node to a topology. @@ -855,26 +789,26 @@ HRESULT MFUtils::AddTransformNode( IMFTransform *pMFT, // MFT. DWORD dwId, // Identifier of the stream sink. IMFTopologyNode **ppNode // Receives the node pointer. - ) +) { - *ppNode = NULL; + *ppNode = NULL; IMFTopologyNode *pNode = NULL; - HRESULT hr = S_OK; - + HRESULT hr = S_OK; + // Create the node. CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &pNode)); // Set the object pointer. CHECK_HR(hr = pNode->SetObject(pMFT)); - CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId)); - CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)); + CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId)); + CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)); // Add the node to the topology. CHECK_HR(hr = pTopology->AddNode(pNode)); // Return the pointer to the caller. *ppNode = pNode; (*ppNode)->AddRef(); - + bail: SafeRelease(&pNode); return hr; @@ -882,13 +816,13 @@ bail: // Sets the IMFStreamSink pointer on an output node. HRESULT MFUtils::BindOutputNode( - IMFTopologyNode *pNode // The Node - ) + IMFTopologyNode *pNode // The Node +) { - assert(pNode); + assert(pNode); - HRESULT hr = S_OK; - IUnknown *pNodeObject = NULL; + HRESULT hr = S_OK; + IUnknown *pNodeObject = NULL; IMFActivate *pActivate = NULL; IMFStreamSink *pStream = NULL; IMFMediaSink *pSink = NULL; @@ -905,44 +839,38 @@ HRESULT MFUtils::BindOutputNode( // First, check if it's an activation object. CHECK_HR(hr = pNodeObject->QueryInterface(IID_PPV_ARGS(&pActivate))); - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { DWORD dwStreamID = 0; - // The object pointer is an activation object. - + // The object pointer is an activation object. + // Try to create the media sink. hr = pActivate->ActivateObject(IID_PPV_ARGS(&pSink)); // Look up the stream ID. (Default to zero.) - if (SUCCEEDED(hr)) - { - dwStreamID = MFGetAttributeUINT32(pNode, MF_TOPONODE_STREAMID, 0); + if (SUCCEEDED(hr)) { + dwStreamID = MFGetAttributeUINT32(pNode, MF_TOPONODE_STREAMID, 0); } // Now try to get or create the stream sink. // Check if the media sink already has a stream sink with the requested ID. - if (SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pSink->GetStreamSinkById(dwStreamID, &pStream); - if (FAILED(hr)) - { + if (FAILED(hr)) { // Try to add a new stream sink. hr = pSink->AddStreamSink(dwStreamID, NULL, &pStream); } } - // Replace the node's object pointer with the stream sink. - if (SUCCEEDED(hr)) - { + // Replace the node's object pointer with the stream sink. + if (SUCCEEDED(hr)) { hr = pNode->SetObject(pStream); } } - else - { + else { // Not an activation object. Is it a stream sink? hr = pNodeObject->QueryInterface(IID_PPV_ARGS(&pStream)); } @@ -957,54 +885,54 @@ bail: // Add an output node to a topology. HRESULT MFUtils::AddOutputNode( - IMFTopology *pTopology, // Topology. - IMFActivate *pActivate, // Media sink activation object. - DWORD dwId, // Identifier of the stream sink. - IMFTopologyNode **ppNode) // Receives the node pointer + IMFTopology *pTopology, // Topology. + IMFActivate *pActivate, // Media sink activation object. + DWORD dwId, // Identifier of the stream sink. + IMFTopologyNode **ppNode) // Receives the node pointer { - IMFTopologyNode *pNode = NULL; + IMFTopologyNode *pNode = NULL; - HRESULT hr = S_OK; - CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode)); - CHECK_HR(hr = pNode->SetObject(pActivate)); - CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId)); - CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)); - CHECK_HR(hr = pTopology->AddNode(pNode)); + HRESULT hr = S_OK; + CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode)); + CHECK_HR(hr = pNode->SetObject(pActivate)); + CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId)); + CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)); + CHECK_HR(hr = pTopology->AddNode(pNode)); - // Return the pointer to the caller. - *ppNode = pNode; - (*ppNode)->AddRef(); + // Return the pointer to the caller. + *ppNode = pNode; + (*ppNode)->AddRef(); bail: - SafeRelease(&pNode); - return hr; + SafeRelease(&pNode); + return hr; } // Add a source node to a topology HRESULT MFUtils::AddSourceNode( - IMFTopology *pTopology, // Topology. - IMFMediaSource *pSource, // Media source. - IMFPresentationDescriptor *pPD, // Presentation descriptor. - IMFStreamDescriptor *pSD, // Stream descriptor. - IMFTopologyNode **ppNode // Receives the node pointer. - ) + IMFTopology *pTopology, // Topology. + IMFMediaSource *pSource, // Media source. + IMFPresentationDescriptor *pPD, // Presentation descriptor. + IMFStreamDescriptor *pSD, // Stream descriptor. + IMFTopologyNode **ppNode // Receives the node pointer. +) { - IMFTopologyNode *pNode = NULL; + IMFTopologyNode *pNode = NULL; - HRESULT hr = S_OK; - CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode)); - CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource)); - CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD)); - CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD)); - CHECK_HR(hr = pTopology->AddNode(pNode)); + HRESULT hr = S_OK; + CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode)); + CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource)); + CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD)); + CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD)); + CHECK_HR(hr = pTopology->AddNode(pNode)); - // Return the pointer to the caller. - *ppNode = pNode; - (*ppNode)->AddRef(); + // Return the pointer to the caller. + *ppNode = pNode; + (*ppNode)->AddRef(); bail: - SafeRelease(&pNode); - return hr; + SafeRelease(&pNode); + return hr; } // Create the topology @@ -1013,386 +941,345 @@ bail: // \-> (SinkPreview) // HRESULT MFUtils::CreateTopology( - IMFMediaSource *pSource, // Media source - IMFTransform *pTransform, // Transform filter (e.g. encoder or decoder) to insert between the source and Sink. NULL is valid. - IMFActivate *pSinkActivateMain, // Main sink (e.g. sample grabber or EVR). - IMFActivate *pSinkActivatePreview, // Preview sink. Optional. Could be NULL. - IMFMediaType *pIputTypeMain, // Main sink input MediaType - IMFTopology **ppTopo // Receives the newly created topology - ) + IMFMediaSource *pSource, // Media source + IMFTransform *pTransform, // Transform filter (e.g. encoder or decoder) to insert between the source and Sink. NULL is valid. + IMFActivate *pSinkActivateMain, // Main sink (e.g. sample grabber or EVR). + IMFActivate *pSinkActivatePreview, // Preview sink. Optional. Could be NULL. + IMFMediaType *pIputTypeMain, // Main sink input MediaType + IMFTopology **ppTopo // Receives the newly created topology +) { - IMFTopology *pTopology = NULL; - IMFPresentationDescriptor *pPD = NULL; - IMFStreamDescriptor *pSD = NULL; - IMFMediaTypeHandler *pHandler = NULL; - IMFTopologyNode *pNodeSource = NULL; - IMFTopologyNode *pNodeSinkMain = NULL; - IMFTopologyNode *pNodeSinkPreview = NULL; - IMFTopologyNode *pNodeTransform = NULL; - IMFTopologyNode *pNodeTee = NULL; - IMFMediaType *pMediaType = NULL; + IMFTopology *pTopology = NULL; + IMFPresentationDescriptor *pPD = NULL; + IMFStreamDescriptor *pSD = NULL; + IMFMediaTypeHandler *pHandler = NULL; + IMFTopologyNode *pNodeSource = NULL; + IMFTopologyNode *pNodeSinkMain = NULL; + IMFTopologyNode *pNodeSinkPreview = NULL; + IMFTopologyNode *pNodeTransform = NULL; + IMFTopologyNode *pNodeTee = NULL; + IMFMediaType *pMediaType = NULL; IMFTransform *pVideoProcessor = NULL; IMFTopologyNode *pNodeVideoProcessor = NULL; - IMFTransform *pConvFrameRate = NULL; - IMFTransform *pConvSize = NULL; - IMFTransform *pConvColor = NULL; - IMFTopologyNode *pNodeConvFrameRate = NULL; - IMFTopologyNode *pNodeConvSize = NULL; - IMFTopologyNode *pNodeConvColor = NULL; - IMFMediaType *pTransformInputType = NULL; - IMFMediaType *pSinkMainInputType = NULL; - const IMFTopologyNode *pcNodeBeforeSinkMain = NULL; - - HRESULT hr = S_OK; - DWORD cStreams = 0; - BOOL bSourceFound = FALSE; - BOOL bSupportedSize = FALSE; - BOOL bSupportedFps = FALSE; - BOOL bSupportedFormat = FALSE; - BOOL bVideoProcessorSupported = FALSE; - GUID inputMajorType, inputSubType; - - CHECK_HR(hr = IsVideoProcessorSupported(&bVideoProcessorSupported)); - CHECK_HR(hr = pIputTypeMain->GetMajorType(&inputMajorType)); - - CHECK_HR(hr = MFCreateTopology(&pTopology)); - CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); - CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); - - for (DWORD i = 0; i < cStreams; i++) - { - BOOL fSelected = FALSE; - GUID majorType; - - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); - CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); - CHECK_HR(hr = pHandler->GetMajorType(&majorType)); - - if (majorType == inputMajorType && fSelected) - { - CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pNodeSource)); - CHECK_HR(hr = pNodeSource->SetTopoNodeID(MFUtils::g_ullTopoIdSource)); - CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivateMain, 0, &pNodeSinkMain)); - CHECK_HR(hr = pNodeSinkMain->SetTopoNodeID(MFUtils::g_ullTopoIdSinkMain)); - CHECK_HR(hr = MFUtils::BindOutputNode(pNodeSinkMain)); // To avoid MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED - - // - // Create preview - // - - if(pSinkActivatePreview) - { - CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivatePreview, 0, &pNodeSinkPreview)); - CHECK_HR(hr = pNodeSinkPreview->SetTopoNodeID(MFUtils::g_ullTopoIdSinkPreview)); - CHECK_HR(hr = MFUtils::BindOutputNode(pNodeSinkPreview)); - - CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &pNodeTee)); - CHECK_HR(hr = pTopology->AddNode(pNodeTee)); - } - - // - // Create converters - // - - if(majorType == MFMediaType_Video) - { - // Even when size matches the topology could add a resizer which doesn't keep ratio when resizing while video processor does. - if(!bVideoProcessorSupported) - { - hr = IsSupported( - pPD, - i, - pIputTypeMain, - &bSupportedSize, - &bSupportedFps, - &bSupportedFormat); - } - - CHECK_HR(hr = pIputTypeMain->GetGUID(MF_MT_SUBTYPE, &inputSubType)); - - if(!bSupportedSize || !bSupportedFps || !bSupportedFormat) - { - // Use video processor single MFT or 3 different MFTs - if(!pVideoProcessor) - { - hr = CoCreateInstance(CLSID_VideoProcessorMFT, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pVideoProcessor)); - } - if(!pVideoProcessor) - { - // Video Resizer DSP(http://msdn.microsoft.com/en-us/library/windows/desktop/ff819491(v=vs.85).aspx) supports I420 only - if(!bSupportedSize && !pConvSize && inputSubType == MFVideoFormat_I420) - { - hr = CoCreateInstance(CLSID_CResizerDMO, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConvSize)); - } - // Frame Rate Converter DSP(http://msdn.microsoft.com/en-us/library/windows/desktop/ff819100(v=vs.85).aspx) supports neither NV12 nor I420 - /*if(!bSupportedFps && !pConvFrameRate) - { - hr = CoCreateInstance(CLSID_CFrameRateConvertDmo, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConvFrameRate)); - }*/ - // Color Converter DSP (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819079(v=vs.85).aspx) supports both NV12 and I420 - if(!bSupportedFormat && !pConvColor) - { - hr = CoCreateInstance(CLSID_CColorConvertDMO, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConvColor)); - } - } - } - else - { - // MediaType supported - CHECK_HR(hr = pHandler->SetCurrentMediaType(pIputTypeMain)); - } - - if(pVideoProcessor && !pNodeVideoProcessor) - { - CHECK_HR(hr = AddTransformNode(pTopology, pVideoProcessor, 0, &pNodeVideoProcessor)); - CHECK_HR(hr = pNodeVideoProcessor->SetTopoNodeID(MFUtils::g_ullTopoIdVideoProcessor)); - } - if(pConvColor && !pNodeConvColor) - { - CHECK_HR(hr = AddTransformNode(pTopology, pConvColor, 0, &pNodeConvColor)); - } - if(pConvFrameRate && !pNodeConvFrameRate) - { - CHECK_HR(hr = AddTransformNode(pTopology, pConvFrameRate, 0, &pNodeConvFrameRate)); - } - if(pConvSize && !pNodeConvSize) - { - CHECK_HR(hr = AddTransformNode(pTopology, pConvSize, 0, &pNodeConvSize)); - } - } // if(majorType == MFMediaType_Video) - - - // - // Set media type - // - - if(pTransform) - { - CHECK_HR(hr = AddTransformNode(pTopology, pTransform, 0, &pNodeTransform)); - hr = pTransform->GetInputCurrentType(0, &pTransformInputType); - if(FAILED(hr)) - { - pTransformInputType = pIputTypeMain; - pTransformInputType->AddRef(); - hr = S_OK; - } - if(pVideoProcessor) - { - CHECK_HR(hr = pVideoProcessor->SetOutputType(0, pTransformInputType, 0)); - } - else - { - if(pConvColor) - { - /*CHECK_HR*/(hr = pConvColor->SetOutputType(0, pTransformInputType, 0)); - } - if(pConvFrameRate) - { - /*CHECK_HR*/(hr = pConvFrameRate->SetOutputType(0, pTransformInputType, 0)); - } - if(pConvSize) - { - // Transform requires NV12 - //Video Resizer DSP(http://msdn.microsoft.com/en-us/library/windows/desktop/ff819491(v=vs.85).aspx) doesn't support NV12 - //*CHECK_HR*/(hr = pConvSize->SetOutputType(0, pTransformInputType, 0)); - } - } - } - else - { - hr = pNodeSinkMain->GetInputPrefType(0, &pSinkMainInputType); - if(FAILED(hr)) - { - pSinkMainInputType = pIputTypeMain; - pSinkMainInputType->AddRef(); - hr = S_OK; - } - if(SUCCEEDED(hr)) - { - if(pVideoProcessor) - { - CHECK_HR(hr = pVideoProcessor->SetOutputType(0, pSinkMainInputType, 0)); - } - else - { - //!\ MUST NOT SET OUTPUT TYPE - if(pConvColor) - { - //*CHECK_HR*/(hr = pConvColor->SetOutputType(0, pSinkMainInputType, 0)); - } - if(pConvFrameRate) - { - //*CHECK_HR*/(hr = pConvFrameRate->SetOutputType(0, pSinkMainInputType, 0)); - } - if(pConvSize) - { - //*CHECK_HR*/(hr = pConvSize->SetOutputType(0, pSinkMainInputType, 0)); - } - } - } - } - - // - // Connect - // - - if(pNodeTee) - { - // Connect(Source -> Tee) - CHECK_HR(hr = pNodeSource->ConnectOutput(0, pNodeTee, 0)); - - // Connect(Tee -> SinkPreview) - CHECK_HR(hr = pNodeTee->ConnectOutput(1, pNodeSinkPreview, 0)); - - // Connect(Tee ->(Processors) - if(pVideoProcessor) - { - CHECK_HR(hr = pNodeTee->ConnectOutput(0, pNodeVideoProcessor, 0)); - pcNodeBeforeSinkMain = pNodeVideoProcessor; - } - else if(pNodeConvFrameRate || pNodeConvSize || pNodeConvColor) - { - CHECK_HR(hr = ConnectConverters( - pNodeTee, - 0, - pNodeConvFrameRate, - pNodeConvColor, - pNodeConvSize - )); - pcNodeBeforeSinkMain = pNodeConvSize ? pNodeConvSize : (pNodeConvColor ? pNodeConvColor : pNodeConvFrameRate); - } - else - { - pcNodeBeforeSinkMain = pNodeTee; - } - } - else - { - // Connect(Source -> (Processors)) - if(pVideoProcessor) - { - CHECK_HR(hr = pNodeSource->ConnectOutput(0, pNodeVideoProcessor, 0)); - pcNodeBeforeSinkMain = pNodeVideoProcessor; - } - else if(pNodeConvFrameRate || pNodeConvFrameRate || pNodeConvColor) - { - CHECK_HR(hr = ConnectConverters( - pNodeSource, - 0, - pNodeConvFrameRate, - pNodeConvSize, - pNodeConvColor - )); - pcNodeBeforeSinkMain = pNodeConvSize ? pNodeConvSize : (pNodeConvColor ? pNodeConvColor : pNodeConvFrameRate); - } - else - { - pcNodeBeforeSinkMain = pNodeSource; - } - } - - - if(pNodeTransform) - { - // Connect(X->Transform) - CHECK_HR(hr = ((IMFTopologyNode *)pcNodeBeforeSinkMain)->ConnectOutput(0, pNodeTransform, 0)); - pcNodeBeforeSinkMain = pNodeTransform; - } - - // Connect(X -> SinkMain) - CHECK_HR(hr = ((IMFTopologyNode *)pcNodeBeforeSinkMain)->ConnectOutput(0, pNodeSinkMain, 0)); - - bSourceFound = TRUE; - break; - } - else - { - CHECK_HR(hr = pPD->DeselectStream(i)); - } - SafeRelease(&pSD); - SafeRelease(&pHandler); - } - - *ppTopo = pTopology; - (*ppTopo)->AddRef(); + IMFTransform *pConvFrameRate = NULL; + IMFTransform *pConvSize = NULL; + IMFTransform *pConvColor = NULL; + IMFTopologyNode *pNodeConvFrameRate = NULL; + IMFTopologyNode *pNodeConvSize = NULL; + IMFTopologyNode *pNodeConvColor = NULL; + IMFMediaType *pTransformInputType = NULL; + IMFMediaType *pSinkMainInputType = NULL; + const IMFTopologyNode *pcNodeBeforeSinkMain = NULL; + + HRESULT hr = S_OK; + DWORD cStreams = 0; + BOOL bSourceFound = FALSE; + BOOL bSupportedSize = FALSE; + BOOL bSupportedFps = FALSE; + BOOL bSupportedFormat = FALSE; + BOOL bVideoProcessorSupported = FALSE; + GUID inputMajorType, inputSubType; + + CHECK_HR(hr = IsVideoProcessorSupported(&bVideoProcessorSupported)); + CHECK_HR(hr = pIputTypeMain->GetMajorType(&inputMajorType)); + + CHECK_HR(hr = MFCreateTopology(&pTopology)); + CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); + CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); + + for (DWORD i = 0; i < cStreams; i++) { + BOOL fSelected = FALSE; + GUID majorType; + + CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); + CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); + CHECK_HR(hr = pHandler->GetMajorType(&majorType)); + + if (majorType == inputMajorType && fSelected) { + CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pNodeSource)); + CHECK_HR(hr = pNodeSource->SetTopoNodeID(MFUtils::g_ullTopoIdSource)); + CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivateMain, 0, &pNodeSinkMain)); + CHECK_HR(hr = pNodeSinkMain->SetTopoNodeID(MFUtils::g_ullTopoIdSinkMain)); + CHECK_HR(hr = MFUtils::BindOutputNode(pNodeSinkMain)); // To avoid MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED + + // + // Create preview + // + + if(pSinkActivatePreview) { + CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivatePreview, 0, &pNodeSinkPreview)); + CHECK_HR(hr = pNodeSinkPreview->SetTopoNodeID(MFUtils::g_ullTopoIdSinkPreview)); + CHECK_HR(hr = MFUtils::BindOutputNode(pNodeSinkPreview)); + + CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &pNodeTee)); + CHECK_HR(hr = pTopology->AddNode(pNodeTee)); + } + + // + // Create converters + // + + if(majorType == MFMediaType_Video) { + // Even when size matches the topology could add a resizer which doesn't keep ratio when resizing while video processor does. + if(!bVideoProcessorSupported) { + hr = IsSupported( + pPD, + i, + pIputTypeMain, + &bSupportedSize, + &bSupportedFps, + &bSupportedFormat); + } + + CHECK_HR(hr = pIputTypeMain->GetGUID(MF_MT_SUBTYPE, &inputSubType)); + + if(!bSupportedSize || !bSupportedFps || !bSupportedFormat) { + // Use video processor single MFT or 3 different MFTs + if(!pVideoProcessor) { + hr = CoCreateInstance(CLSID_VideoProcessorMFT, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pVideoProcessor)); + } + if(!pVideoProcessor) { + // Video Resizer DSP(http://msdn.microsoft.com/en-us/library/windows/desktop/ff819491(v=vs.85).aspx) supports I420 only + if(!bSupportedSize && !pConvSize && inputSubType == MFVideoFormat_I420) { + hr = CoCreateInstance(CLSID_CResizerDMO, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConvSize)); + } + // Frame Rate Converter DSP(http://msdn.microsoft.com/en-us/library/windows/desktop/ff819100(v=vs.85).aspx) supports neither NV12 nor I420 + /*if(!bSupportedFps && !pConvFrameRate) + { + hr = CoCreateInstance(CLSID_CFrameRateConvertDmo, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConvFrameRate)); + }*/ + // Color Converter DSP (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819079(v=vs.85).aspx) supports both NV12 and I420 + if(!bSupportedFormat && !pConvColor) { + hr = CoCreateInstance(CLSID_CColorConvertDMO, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConvColor)); + } + } + } + else { + // MediaType supported + CHECK_HR(hr = pHandler->SetCurrentMediaType(pIputTypeMain)); + } + + if(pVideoProcessor && !pNodeVideoProcessor) { + CHECK_HR(hr = AddTransformNode(pTopology, pVideoProcessor, 0, &pNodeVideoProcessor)); + CHECK_HR(hr = pNodeVideoProcessor->SetTopoNodeID(MFUtils::g_ullTopoIdVideoProcessor)); + } + if(pConvColor && !pNodeConvColor) { + CHECK_HR(hr = AddTransformNode(pTopology, pConvColor, 0, &pNodeConvColor)); + } + if(pConvFrameRate && !pNodeConvFrameRate) { + CHECK_HR(hr = AddTransformNode(pTopology, pConvFrameRate, 0, &pNodeConvFrameRate)); + } + if(pConvSize && !pNodeConvSize) { + CHECK_HR(hr = AddTransformNode(pTopology, pConvSize, 0, &pNodeConvSize)); + } + } // if(majorType == MFMediaType_Video) + + + // + // Set media type + // + + if(pTransform) { + CHECK_HR(hr = AddTransformNode(pTopology, pTransform, 0, &pNodeTransform)); + hr = pTransform->GetInputCurrentType(0, &pTransformInputType); + if(FAILED(hr)) { + pTransformInputType = pIputTypeMain; + pTransformInputType->AddRef(); + hr = S_OK; + } + if(pVideoProcessor) { + CHECK_HR(hr = pVideoProcessor->SetOutputType(0, pTransformInputType, 0)); + } + else { + if(pConvColor) { + /*CHECK_HR*/(hr = pConvColor->SetOutputType(0, pTransformInputType, 0)); + } + if(pConvFrameRate) { + /*CHECK_HR*/(hr = pConvFrameRate->SetOutputType(0, pTransformInputType, 0)); + } + if(pConvSize) { + // Transform requires NV12 + //Video Resizer DSP(http://msdn.microsoft.com/en-us/library/windows/desktop/ff819491(v=vs.85).aspx) doesn't support NV12 + //*CHECK_HR*/(hr = pConvSize->SetOutputType(0, pTransformInputType, 0)); + } + } + } + else { + hr = pNodeSinkMain->GetInputPrefType(0, &pSinkMainInputType); + if(FAILED(hr)) { + pSinkMainInputType = pIputTypeMain; + pSinkMainInputType->AddRef(); + hr = S_OK; + } + if(SUCCEEDED(hr)) { + if(pVideoProcessor) { + CHECK_HR(hr = pVideoProcessor->SetOutputType(0, pSinkMainInputType, 0)); + } + else { + //!\ MUST NOT SET OUTPUT TYPE + if(pConvColor) { + //*CHECK_HR*/(hr = pConvColor->SetOutputType(0, pSinkMainInputType, 0)); + } + if(pConvFrameRate) { + //*CHECK_HR*/(hr = pConvFrameRate->SetOutputType(0, pSinkMainInputType, 0)); + } + if(pConvSize) { + //*CHECK_HR*/(hr = pConvSize->SetOutputType(0, pSinkMainInputType, 0)); + } + } + } + } + + // + // Connect + // + + if(pNodeTee) { + // Connect(Source -> Tee) + CHECK_HR(hr = pNodeSource->ConnectOutput(0, pNodeTee, 0)); + + // Connect(Tee -> SinkPreview) + CHECK_HR(hr = pNodeTee->ConnectOutput(1, pNodeSinkPreview, 0)); + + // Connect(Tee ->(Processors) + if(pVideoProcessor) { + CHECK_HR(hr = pNodeTee->ConnectOutput(0, pNodeVideoProcessor, 0)); + pcNodeBeforeSinkMain = pNodeVideoProcessor; + } + else if(pNodeConvFrameRate || pNodeConvSize || pNodeConvColor) { + CHECK_HR(hr = ConnectConverters( + pNodeTee, + 0, + pNodeConvFrameRate, + pNodeConvColor, + pNodeConvSize + )); + pcNodeBeforeSinkMain = pNodeConvSize ? pNodeConvSize : (pNodeConvColor ? pNodeConvColor : pNodeConvFrameRate); + } + else { + pcNodeBeforeSinkMain = pNodeTee; + } + } + else { + // Connect(Source -> (Processors)) + if(pVideoProcessor) { + CHECK_HR(hr = pNodeSource->ConnectOutput(0, pNodeVideoProcessor, 0)); + pcNodeBeforeSinkMain = pNodeVideoProcessor; + } + else if(pNodeConvFrameRate || pNodeConvFrameRate || pNodeConvColor) { + CHECK_HR(hr = ConnectConverters( + pNodeSource, + 0, + pNodeConvFrameRate, + pNodeConvSize, + pNodeConvColor + )); + pcNodeBeforeSinkMain = pNodeConvSize ? pNodeConvSize : (pNodeConvColor ? pNodeConvColor : pNodeConvFrameRate); + } + else { + pcNodeBeforeSinkMain = pNodeSource; + } + } + + + if(pNodeTransform) { + // Connect(X->Transform) + CHECK_HR(hr = ((IMFTopologyNode *)pcNodeBeforeSinkMain)->ConnectOutput(0, pNodeTransform, 0)); + pcNodeBeforeSinkMain = pNodeTransform; + } + + // Connect(X -> SinkMain) + CHECK_HR(hr = ((IMFTopologyNode *)pcNodeBeforeSinkMain)->ConnectOutput(0, pNodeSinkMain, 0)); + + bSourceFound = TRUE; + break; + } + else { + CHECK_HR(hr = pPD->DeselectStream(i)); + } + SafeRelease(&pSD); + SafeRelease(&pHandler); + } + + *ppTopo = pTopology; + (*ppTopo)->AddRef(); bail: - SafeRelease(&pTopology); - SafeRelease(&pNodeSource); - SafeRelease(&pNodeSinkMain); - SafeRelease(&pNodeSinkPreview); - SafeRelease(&pNodeTransform); - SafeRelease(&pNodeTee); - SafeRelease(&pPD); - SafeRelease(&pSD); - SafeRelease(&pHandler); - SafeRelease(&pMediaType); - SafeRelease(&pTransformInputType); - SafeRelease(&pSinkMainInputType); - - SafeRelease(&pVideoProcessor); + SafeRelease(&pTopology); + SafeRelease(&pNodeSource); + SafeRelease(&pNodeSinkMain); + SafeRelease(&pNodeSinkPreview); + SafeRelease(&pNodeTransform); + SafeRelease(&pNodeTee); + SafeRelease(&pPD); + SafeRelease(&pSD); + SafeRelease(&pHandler); + SafeRelease(&pMediaType); + SafeRelease(&pTransformInputType); + SafeRelease(&pSinkMainInputType); + + SafeRelease(&pVideoProcessor); SafeRelease(&pNodeVideoProcessor); - SafeRelease(&pConvFrameRate); - SafeRelease(&pConvSize); - SafeRelease(&pConvColor); - SafeRelease(&pNodeConvFrameRate); - SafeRelease(&pNodeConvSize); - SafeRelease(&pNodeConvColor); - - if(!bSourceFound) - { - TSK_DEBUG_ERROR("No source node found"); - return E_NOT_SET; - } - - return hr; + SafeRelease(&pConvFrameRate); + SafeRelease(&pConvSize); + SafeRelease(&pConvColor); + SafeRelease(&pNodeConvFrameRate); + SafeRelease(&pNodeConvSize); + SafeRelease(&pNodeConvColor); + + if(!bSourceFound) { + TSK_DEBUG_ERROR("No source node found"); + return E_NOT_SET; + } + + return hr; } // Creates a fully loaded topology from the input partial topology. HRESULT MFUtils::ResolveTopology( - IMFTopology *pInputTopo, // A pointer to the IMFTopology interface of the partial topology to be resolved. - IMFTopology **ppOutputTopo, // Receives a pointer to the IMFTopology interface of the completed topology. The caller must release the interface. - IMFTopology *pCurrentTopo /*= NULL*/ // A pointer to the IMFTopology interface of the previous full topology. The topology loader can re-use objects from this topology in the new topology. This parameter can be NULL. - ) + IMFTopology *pInputTopo, // A pointer to the IMFTopology interface of the partial topology to be resolved. + IMFTopology **ppOutputTopo, // Receives a pointer to the IMFTopology interface of the completed topology. The caller must release the interface. + IMFTopology *pCurrentTopo /*= NULL*/ // A pointer to the IMFTopology interface of the previous full topology. The topology loader can re-use objects from this topology in the new topology. This parameter can be NULL. +) { - assert(ppOutputTopo && pInputTopo); - - HRESULT hr = S_OK; - IMFTopoLoader* pTopoLoader = NULL; - - *ppOutputTopo = NULL; - - CHECK_HR(hr = MFCreateTopoLoader(&pTopoLoader)); - CHECK_HR(hr = pTopoLoader->Load(pInputTopo, ppOutputTopo, pCurrentTopo)); - + assert(ppOutputTopo && pInputTopo); + + HRESULT hr = S_OK; + IMFTopoLoader* pTopoLoader = NULL; + + *ppOutputTopo = NULL; + + CHECK_HR(hr = MFCreateTopoLoader(&pTopoLoader)); + CHECK_HR(hr = pTopoLoader->Load(pInputTopo, ppOutputTopo, pCurrentTopo)); + bail: - SafeRelease(&pTopoLoader); - return hr; + SafeRelease(&pTopoLoader); + return hr; } HRESULT MFUtils::FindNodeObject( - IMFTopology *pInputTopo, // The Topology containing the node to find - TOPOID qwTopoNodeID, //The identifier for the node - void** ppObject // Receives the Object - ) + IMFTopology *pInputTopo, // The Topology containing the node to find + TOPOID qwTopoNodeID, //The identifier for the node + void** ppObject // Receives the Object +) { - assert(pInputTopo && ppObject); + assert(pInputTopo && ppObject); - *ppObject = NULL; + *ppObject = NULL; - IMFTopologyNode *pNode = NULL; - HRESULT hr = S_OK; + IMFTopologyNode *pNode = NULL; + HRESULT hr = S_OK; - CHECK_HR(hr = pInputTopo->GetNodeByID(qwTopoNodeID, &pNode)); - CHECK_HR(hr = pNode->GetObject((IUnknown**)ppObject)); + CHECK_HR(hr = pInputTopo->GetNodeByID(qwTopoNodeID, &pNode)); + CHECK_HR(hr = pNode->GetObject((IUnknown**)ppObject)); bail: - SafeRelease(&pNode); - return hr; + SafeRelease(&pNode); + return hr; } // Create an activation object for a renderer, based on the stream media type. @@ -1402,7 +1289,7 @@ HRESULT MFUtils::CreateMediaSinkActivate( IMFActivate **ppActivate ) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; IMFMediaTypeHandler *pHandler = NULL; IMFActivate *pActivate = NULL; @@ -1411,29 +1298,25 @@ HRESULT MFUtils::CreateMediaSinkActivate( // Get the major media type. GUID guidMajorType; CHECK_HR(hr = pHandler->GetMajorType(&guidMajorType)); - + // Create an IMFActivate object for the renderer, based on the media type. - if (MFMediaType_Audio == guidMajorType) - { + if (MFMediaType_Audio == guidMajorType) { // Create the audio renderer. CHECK_HR(hr = MFCreateAudioRendererActivate(&pActivate)); } - else if (MFMediaType_Video == guidMajorType) - { + else if (MFMediaType_Video == guidMajorType) { // Create the video renderer. CHECK_HR(hr = MFCreateVideoRendererActivate(hVideoWindow, &pActivate)); } - else - { - // Unknown stream type. + else { + // Unknown stream type. hr = E_FAIL; // Optionally, you could deselect this stream instead of failing. } - if (FAILED(hr)) - { + if (FAILED(hr)) { goto bail; } - + // Return IMFActivate pointer to caller. *ppActivate = pActivate; (*ppActivate)->AddRef(); @@ -1447,92 +1330,87 @@ bail: // Set source output media type HRESULT MFUtils::SetMediaType( IMFMediaSource *pSource, // Media source. - IMFMediaType* pMediaType // Media Type. - ) + IMFMediaType* pMediaType // Media Type. +) { - assert(pSource && pMediaType); - - IMFPresentationDescriptor *pPD = NULL; - IMFStreamDescriptor *pSD = NULL; - IMFMediaTypeHandler *pHandler = NULL; - - HRESULT hr = S_OK; - DWORD cStreams = 0; - GUID inputMajorType; - - CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); - CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); - CHECK_HR(hr = pMediaType->GetMajorType(&inputMajorType)); - - for (DWORD i = 0; i < cStreams; i++) - { - BOOL fSelected = FALSE; - GUID majorType; - - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); - CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); - CHECK_HR(hr = pHandler->GetMajorType(&majorType)); - - if (majorType == inputMajorType && fSelected) - { - CHECK_HR(hr = pHandler->SetCurrentMediaType(pMediaType)); - } - else - { - CHECK_HR(hr = pPD->DeselectStream(i)); - } - SafeRelease(&pSD); - SafeRelease(&pHandler); - } + assert(pSource && pMediaType); + + IMFPresentationDescriptor *pPD = NULL; + IMFStreamDescriptor *pSD = NULL; + IMFMediaTypeHandler *pHandler = NULL; + + HRESULT hr = S_OK; + DWORD cStreams = 0; + GUID inputMajorType; + + CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); + CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); + CHECK_HR(hr = pMediaType->GetMajorType(&inputMajorType)); + + for (DWORD i = 0; i < cStreams; i++) { + BOOL fSelected = FALSE; + GUID majorType; + + CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); + CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); + CHECK_HR(hr = pHandler->GetMajorType(&majorType)); + + if (majorType == inputMajorType && fSelected) { + CHECK_HR(hr = pHandler->SetCurrentMediaType(pMediaType)); + } + else { + CHECK_HR(hr = pPD->DeselectStream(i)); + } + SafeRelease(&pSD); + SafeRelease(&pHandler); + } bail: - SafeRelease(&pPD); - SafeRelease(&pSD); - SafeRelease(&pHandler); + SafeRelease(&pPD); + SafeRelease(&pSD); + SafeRelease(&pHandler); - return hr; + return hr; } HRESULT MFUtils::SetVideoWindow( IMFTopology *pTopology, // Topology. IMFMediaSource *pSource, // Media source. HWND hVideoWnd // Window for video playback. - ) +) { - HRESULT hr = S_OK; - IMFStreamDescriptor *pSD = NULL; - IMFPresentationDescriptor *pPD = NULL; + HRESULT hr = S_OK; + IMFStreamDescriptor *pSD = NULL; + IMFPresentationDescriptor *pPD = NULL; IMFActivate *pSinkActivate = NULL; IMFTopologyNode *pSourceNode = NULL; IMFTopologyNode *pOutputNode = NULL; - DWORD cStreams = 0, iStream; - - CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); - CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); - - for(iStream = 0; iStream < cStreams; ++iStream) - { - BOOL fSelected = FALSE; - - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD)); - - if (fSelected) - { - // Create the media sink activation object. - CHECK_HR(hr = CreateMediaSinkActivate(pSD, hVideoWnd, &pSinkActivate)); - // Add a source node for this stream. - CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pSourceNode)); - // Create the output node for the renderer. - CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode)); - // Connect the source node to the output node. - CHECK_HR(hr = pSourceNode->ConnectOutput(0, pOutputNode, 0)); - } - // else: If not selected, don't add the branch. - } + DWORD cStreams = 0, iStream; + + CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); + CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); + + for(iStream = 0; iStream < cStreams; ++iStream) { + BOOL fSelected = FALSE; + + CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD)); + + if (fSelected) { + // Create the media sink activation object. + CHECK_HR(hr = CreateMediaSinkActivate(pSD, hVideoWnd, &pSinkActivate)); + // Add a source node for this stream. + CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pSourceNode)); + // Create the output node for the renderer. + CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode)); + // Connect the source node to the output node. + CHECK_HR(hr = pSourceNode->ConnectOutput(0, pOutputNode, 0)); + } + // else: If not selected, don't add the branch. + } bail: - SafeRelease(&pPD); + SafeRelease(&pPD); SafeRelease(&pSD); SafeRelease(&pSinkActivate); SafeRelease(&pSourceNode); @@ -1542,407 +1420,374 @@ bail: // Run the session HRESULT MFUtils::RunSession( - IMFMediaSession *pSession, // Session to run - IMFTopology *pTopology // The toppology - ) + IMFMediaSession *pSession, // Session to run + IMFTopology *pTopology // The toppology +) { - assert(pSession && pTopology); - - IMFMediaEvent *pEvent = NULL; - - PROPVARIANT var; - PropVariantInit(&var); - - MediaEventType met; - HRESULT hrStatus = S_OK; - HRESULT hr = S_OK; - CHECK_HR(hr = pSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pTopology)); // MFSESSION_SETTOPOLOGY_IMMEDIATE required to update (reload) topology when media type change - CHECK_HR(hr = pSession->Start(&GUID_NULL, &var)); - - // Check first event - hr = pSession->GetEvent(MF_EVENT_FLAG_NO_WAIT, &pEvent); - if(hr == MF_E_NO_EVENTS_AVAILABLE || hr == MF_E_MULTIPLE_SUBSCRIBERS){ // MF_E_MULTIPLE_SUBSCRIBERS means already listening - hr = S_OK; - goto bail; - } - if(pEvent) { - CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); - } - else { - hrStatus = hr; - } - if (FAILED(hrStatus)) - { - CHECK_HR(hr = pEvent->GetType(&met)); - TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met); - hr = hrStatus; - goto bail; - } + assert(pSession && pTopology); + + IMFMediaEvent *pEvent = NULL; + + PROPVARIANT var; + PropVariantInit(&var); + + MediaEventType met; + HRESULT hrStatus = S_OK; + HRESULT hr = S_OK; + CHECK_HR(hr = pSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pTopology)); // MFSESSION_SETTOPOLOGY_IMMEDIATE required to update (reload) topology when media type change + CHECK_HR(hr = pSession->Start(&GUID_NULL, &var)); + + // Check first event + hr = pSession->GetEvent(MF_EVENT_FLAG_NO_WAIT, &pEvent); + if(hr == MF_E_NO_EVENTS_AVAILABLE || hr == MF_E_MULTIPLE_SUBSCRIBERS) { // MF_E_MULTIPLE_SUBSCRIBERS means already listening + hr = S_OK; + goto bail; + } + if(pEvent) { + CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); + } + else { + hrStatus = hr; + } + if (FAILED(hrStatus)) { + CHECK_HR(hr = pEvent->GetType(&met)); + TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met); + hr = hrStatus; + goto bail; + } bail: - SafeRelease(&pEvent); - return hr; + SafeRelease(&pEvent); + return hr; } // Stop session HRESULT MFUtils::ShutdownSession( - IMFMediaSession *pSession, // The Session - IMFMediaSource *pSource // Source to shutdown (optional) - ) + IMFMediaSession *pSession, // The Session + IMFMediaSource *pSource // Source to shutdown (optional) +) { - // MUST be source then session - if(pSource){ - pSource->Stop(); - pSource->Shutdown(); - } - if(pSession){ - pSession->Shutdown(); - } - return S_OK; + // MUST be source then session + if(pSource) { + pSource->Stop(); + pSource->Shutdown(); + } + if(pSession) { + pSession->Shutdown(); + } + return S_OK; } // Pause session HRESULT MFUtils::PauseSession( - IMFMediaSession *pSession, // The session - IMFMediaSource *pSource // Source to pause (optional) - ) + IMFMediaSession *pSession, // The session + IMFMediaSource *pSource // Source to pause (optional) +) { - if(!pSession){ - return E_INVALIDARG; - } - if(pSource){ - pSource->Pause(); - } - return pSession->Pause(); + if(!pSession) { + return E_INVALIDARG; + } + if(pSource) { + pSource->Pause(); + } + return pSession->Pause(); } // Returns -1 if none is supported INT MFUtils::GetSupportedSubTypeIndex( - IMFMediaSource *pSource, // The source - const GUID& mediaType, // The MediaType - const VideoSubTypeGuidPair* subTypes, UINT subTypesCount // List of preferred subtypes (in ascending order) - ) + IMFMediaSource *pSource, // The source + const GUID& mediaType, // The MediaType + const VideoSubTypeGuidPair* subTypes, UINT subTypesCount // List of preferred subtypes (in ascending order) +) { - assert(pSource); - - IMFPresentationDescriptor *pPD = NULL; - IMFStreamDescriptor *pSD = NULL; - IMFMediaTypeHandler *pHandler = NULL; - IMFMediaType *pMediaType = NULL; - - INT nIndex = -1; - HRESULT hr = S_OK; - DWORD cStreams = 0, cMediaTypesCount; - GUID majorType, subType; - BOOL fSelected; - - CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); - CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); - - for (UINT subTypesIndex = 0; subTypesIndex < subTypesCount && nIndex == -1; ++subTypesIndex) - { - for (DWORD cStreamIndex = 0; cStreamIndex < cStreams && nIndex == -1; ++cStreamIndex) - { - fSelected = FALSE; - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(cStreamIndex, &fSelected, &pSD)); - if(fSelected) - { - CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); - CHECK_HR(hr = pHandler->GetMajorType(&majorType)); - if(majorType == mediaType) - { - CHECK_HR(hr = pHandler->GetMediaTypeCount(&cMediaTypesCount)); - for(DWORD cMediaTypesIndex = 0; cMediaTypesIndex < cMediaTypesCount && nIndex == -1; ++cMediaTypesIndex) - { - CHECK_HR(hr = pHandler->GetMediaTypeByIndex(cMediaTypesIndex, &pMediaType)); - CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); - if (subTypes[subTypesIndex].fourcc == subType) - { - nIndex = subTypesIndex; - break; - } - SafeRelease(&pMediaType); - } - } - } - - SafeRelease(&pSD); - SafeRelease(&pHandler); - } - } + assert(pSource); + + IMFPresentationDescriptor *pPD = NULL; + IMFStreamDescriptor *pSD = NULL; + IMFMediaTypeHandler *pHandler = NULL; + IMFMediaType *pMediaType = NULL; + + INT nIndex = -1; + HRESULT hr = S_OK; + DWORD cStreams = 0, cMediaTypesCount; + GUID majorType, subType; + BOOL fSelected; + + CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); + CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); + + for (UINT subTypesIndex = 0; subTypesIndex < subTypesCount && nIndex == -1; ++subTypesIndex) { + for (DWORD cStreamIndex = 0; cStreamIndex < cStreams && nIndex == -1; ++cStreamIndex) { + fSelected = FALSE; + CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(cStreamIndex, &fSelected, &pSD)); + if(fSelected) { + CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); + CHECK_HR(hr = pHandler->GetMajorType(&majorType)); + if(majorType == mediaType) { + CHECK_HR(hr = pHandler->GetMediaTypeCount(&cMediaTypesCount)); + for(DWORD cMediaTypesIndex = 0; cMediaTypesIndex < cMediaTypesCount && nIndex == -1; ++cMediaTypesIndex) { + CHECK_HR(hr = pHandler->GetMediaTypeByIndex(cMediaTypesIndex, &pMediaType)); + CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); + if (subTypes[subTypesIndex].fourcc == subType) { + nIndex = subTypesIndex; + break; + } + SafeRelease(&pMediaType); + } + } + } + + SafeRelease(&pSD); + SafeRelease(&pHandler); + } + } bail: - SafeRelease(&pMediaType); - SafeRelease(&pPD); - SafeRelease(&pSD); - SafeRelease(&pHandler); + SafeRelease(&pMediaType); + SafeRelease(&pPD); + SafeRelease(&pSD); + SafeRelease(&pHandler); - return nIndex; + return nIndex; } HRESULT MFUtils::IsSupported( - IMFPresentationDescriptor *pPD, - DWORD cStreamIndex, - UINT32 nWidth, - UINT32 nHeight, - UINT32 nFps, - const GUID& guidFormat, - BOOL* pbSupportedSize, - BOOL* pbSupportedFps, - BOOL* pbSupportedFormat - ) + IMFPresentationDescriptor *pPD, + DWORD cStreamIndex, + UINT32 nWidth, + UINT32 nHeight, + UINT32 nFps, + const GUID& guidFormat, + BOOL* pbSupportedSize, + BOOL* pbSupportedFps, + BOOL* pbSupportedFormat +) { - HRESULT hr = S_OK; - - BOOL fSelected = FALSE; - IMFStreamDescriptor *pSD = NULL; - IMFMediaTypeHandler *pHandler = NULL; - IMFMediaType *pMediaType = NULL; - UINT32 _nWidth = 0, _nHeight = 0, numeratorFps = 0, denominatorFps = 0; - GUID subType; - DWORD cMediaTypesCount; - - if(!pPD || !pbSupportedSize || !pbSupportedFps || !pbSupportedFormat) - { - CHECK_HR(hr = E_POINTER); - } - - *pbSupportedSize = FALSE; - *pbSupportedFps = FALSE; - *pbSupportedFormat = FALSE; - - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(cStreamIndex, &fSelected, &pSD)); - if(fSelected) - { - CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); - CHECK_HR(hr = pHandler->GetMediaTypeCount(&cMediaTypesCount)); - for(DWORD cMediaTypesIndex = 0; cMediaTypesIndex < cMediaTypesCount; ++cMediaTypesIndex) - { - CHECK_HR(hr = pHandler->GetMediaTypeByIndex(cMediaTypesIndex, &pMediaType)); - CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &_nWidth, &_nHeight)); - CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); - if(FAILED(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &numeratorFps, &denominatorFps))) - { - numeratorFps = 30; - denominatorFps = 1; - } - - // all must match for the same stream - if(_nWidth == nWidth && _nHeight == nHeight && subType == guidFormat && (numeratorFps/denominatorFps) == nFps) - { - *pbSupportedSize = TRUE; - *pbSupportedFormat = TRUE; - *pbSupportedFps = TRUE; - break; - } - - SafeRelease(&pMediaType); - } - SafeRelease(&pHandler); - } - + HRESULT hr = S_OK; + + BOOL fSelected = FALSE; + IMFStreamDescriptor *pSD = NULL; + IMFMediaTypeHandler *pHandler = NULL; + IMFMediaType *pMediaType = NULL; + UINT32 _nWidth = 0, _nHeight = 0, numeratorFps = 0, denominatorFps = 0; + GUID subType; + DWORD cMediaTypesCount; + + if(!pPD || !pbSupportedSize || !pbSupportedFps || !pbSupportedFormat) { + CHECK_HR(hr = E_POINTER); + } + + *pbSupportedSize = FALSE; + *pbSupportedFps = FALSE; + *pbSupportedFormat = FALSE; + + CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(cStreamIndex, &fSelected, &pSD)); + if(fSelected) { + CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); + CHECK_HR(hr = pHandler->GetMediaTypeCount(&cMediaTypesCount)); + for(DWORD cMediaTypesIndex = 0; cMediaTypesIndex < cMediaTypesCount; ++cMediaTypesIndex) { + CHECK_HR(hr = pHandler->GetMediaTypeByIndex(cMediaTypesIndex, &pMediaType)); + CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &_nWidth, &_nHeight)); + CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); + if(FAILED(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &numeratorFps, &denominatorFps))) { + numeratorFps = 30; + denominatorFps = 1; + } + + // all must match for the same stream + if(_nWidth == nWidth && _nHeight == nHeight && subType == guidFormat && (numeratorFps/denominatorFps) == nFps) { + *pbSupportedSize = TRUE; + *pbSupportedFormat = TRUE; + *pbSupportedFps = TRUE; + break; + } + + SafeRelease(&pMediaType); + } + SafeRelease(&pHandler); + } + bail: - SafeRelease(&pSD); - SafeRelease(&pHandler); - SafeRelease(&pMediaType); - - return hr; + SafeRelease(&pSD); + SafeRelease(&pHandler); + SafeRelease(&pMediaType); + + return hr; } HRESULT MFUtils::IsSupported( - IMFPresentationDescriptor *pPD, - DWORD cStreamIndex, - IMFMediaType* pMediaType, - BOOL* pbSupportedSize, - BOOL* pbSupportedFps, - BOOL* pbSupportedFormat - ) + IMFPresentationDescriptor *pPD, + DWORD cStreamIndex, + IMFMediaType* pMediaType, + BOOL* pbSupportedSize, + BOOL* pbSupportedFps, + BOOL* pbSupportedFormat +) { - HRESULT hr = S_OK; - - UINT32 nWidth = 0, nHeight = 0, nFps = 0, numeratorFps = 30, denominatorFps = 1; - GUID subType; - - if(!pPD || !pMediaType || !pbSupportedSize || !pbSupportedFps || !pbSupportedFormat) - { - CHECK_HR(hr = E_POINTER); - } - - CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &nWidth, &nHeight)); - CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); - if(FAILED(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &numeratorFps, &denominatorFps))) - { - numeratorFps = 30; - denominatorFps = 1; - } - - CHECK_HR(hr = IsSupported( - pPD, - cStreamIndex, - nWidth, - nHeight, - (numeratorFps / denominatorFps), - subType, - pbSupportedSize, - pbSupportedFps, - pbSupportedFormat - )); + HRESULT hr = S_OK; + + UINT32 nWidth = 0, nHeight = 0, nFps = 0, numeratorFps = 30, denominatorFps = 1; + GUID subType; + + if(!pPD || !pMediaType || !pbSupportedSize || !pbSupportedFps || !pbSupportedFormat) { + CHECK_HR(hr = E_POINTER); + } + + CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &nWidth, &nHeight)); + CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); + if(FAILED(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &numeratorFps, &denominatorFps))) { + numeratorFps = 30; + denominatorFps = 1; + } + + CHECK_HR(hr = IsSupported( + pPD, + cStreamIndex, + nWidth, + nHeight, + (numeratorFps / denominatorFps), + subType, + pbSupportedSize, + pbSupportedFps, + pbSupportedFormat + )); bail: - return hr; + return hr; } HRESULT MFUtils::IsSupportedByInput( - IMFPresentationDescriptor *pPD, - DWORD cStreamIndex, - IMFTopologyNode *pNode, - BOOL* pbSupportedSize, - BOOL* pbSupportedFps, - BOOL* pbSupportedFormat - ) + IMFPresentationDescriptor *pPD, + DWORD cStreamIndex, + IMFTopologyNode *pNode, + BOOL* pbSupportedSize, + BOOL* pbSupportedFps, + BOOL* pbSupportedFormat +) { - HRESULT hr = S_OK; - - IMFMediaType *pMediaType = NULL; - IUnknown* pObject = NULL; - IMFActivate *pActivate = NULL; - IMFMediaSink *pMediaSink = NULL; - IMFTransform *pTransform = NULL; - IMFStreamSink *pStreamSink = NULL; - IMFMediaTypeHandler *pHandler = NULL; - - if(!pPD || !pNode || !pbSupportedSize || !pbSupportedFps || !pbSupportedFormat) - { - CHECK_HR(hr = E_POINTER); - } - - CHECK_HR(hr = pNode->GetObject(&pObject)); - hr = pObject->QueryInterface(IID_PPV_ARGS(&pActivate)); - if(SUCCEEDED(hr)) - { - SafeRelease(&pObject); - hr = pActivate->ActivateObject(IID_IMFMediaSink, (void**)&pObject); - if(FAILED(hr)) - { - hr = pActivate->ActivateObject(IID_IMFTransform, (void**)&pObject); - } - } - - if(!pObject) - { - CHECK_HR(hr = E_NOINTERFACE); - } - - hr = pObject->QueryInterface(IID_PPV_ARGS(&pMediaSink)); - if(FAILED(hr)) - { - hr = pObject->QueryInterface(IID_PPV_ARGS(&pTransform)); - } - - - - if(pMediaSink) - { - CHECK_HR(hr = pMediaSink->GetStreamSinkByIndex(0, &pStreamSink)); - CHECK_HR(hr = pStreamSink->GetMediaTypeHandler(&pHandler)); - CHECK_HR(hr = pHandler->GetCurrentMediaType(&pMediaType)); - - } - else if(pTransform) - { - CHECK_HR(hr = pTransform->GetInputCurrentType(0, &pMediaType)); - } - else - { - CHECK_HR(hr = pNode->GetInputPrefType(0, &pMediaType)); - } - - CHECK_HR(hr = IsSupported( - pPD, - cStreamIndex, - pMediaType, - pbSupportedSize, - pbSupportedFps, - pbSupportedFormat - )); + HRESULT hr = S_OK; + + IMFMediaType *pMediaType = NULL; + IUnknown* pObject = NULL; + IMFActivate *pActivate = NULL; + IMFMediaSink *pMediaSink = NULL; + IMFTransform *pTransform = NULL; + IMFStreamSink *pStreamSink = NULL; + IMFMediaTypeHandler *pHandler = NULL; + + if(!pPD || !pNode || !pbSupportedSize || !pbSupportedFps || !pbSupportedFormat) { + CHECK_HR(hr = E_POINTER); + } + + CHECK_HR(hr = pNode->GetObject(&pObject)); + hr = pObject->QueryInterface(IID_PPV_ARGS(&pActivate)); + if(SUCCEEDED(hr)) { + SafeRelease(&pObject); + hr = pActivate->ActivateObject(IID_IMFMediaSink, (void**)&pObject); + if(FAILED(hr)) { + hr = pActivate->ActivateObject(IID_IMFTransform, (void**)&pObject); + } + } + + if(!pObject) { + CHECK_HR(hr = E_NOINTERFACE); + } + + hr = pObject->QueryInterface(IID_PPV_ARGS(&pMediaSink)); + if(FAILED(hr)) { + hr = pObject->QueryInterface(IID_PPV_ARGS(&pTransform)); + } + + + + if(pMediaSink) { + CHECK_HR(hr = pMediaSink->GetStreamSinkByIndex(0, &pStreamSink)); + CHECK_HR(hr = pStreamSink->GetMediaTypeHandler(&pHandler)); + CHECK_HR(hr = pHandler->GetCurrentMediaType(&pMediaType)); + + } + else if(pTransform) { + CHECK_HR(hr = pTransform->GetInputCurrentType(0, &pMediaType)); + } + else { + CHECK_HR(hr = pNode->GetInputPrefType(0, &pMediaType)); + } + + CHECK_HR(hr = IsSupported( + pPD, + cStreamIndex, + pMediaType, + pbSupportedSize, + pbSupportedFps, + pbSupportedFormat + )); bail: - SafeRelease(&pObject); - SafeRelease(&pActivate); - SafeRelease(&pMediaType); - SafeRelease(&pStreamSink); - SafeRelease(&pHandler); - return hr; + SafeRelease(&pObject); + SafeRelease(&pActivate); + SafeRelease(&pMediaType); + SafeRelease(&pStreamSink); + SafeRelease(&pHandler); + return hr; } HRESULT MFUtils::ConnectConverters( - IMFTopologyNode *pNode, - DWORD dwOutputIndex, - IMFTopologyNode *pNodeConvFrameRate, - IMFTopologyNode *pNodeConvColor, - IMFTopologyNode *pNodeConvSize - ) + IMFTopologyNode *pNode, + DWORD dwOutputIndex, + IMFTopologyNode *pNodeConvFrameRate, + IMFTopologyNode *pNodeConvColor, + IMFTopologyNode *pNodeConvSize +) { - HRESULT hr = S_OK; - - if(!pNode) - { - CHECK_HR(hr = E_POINTER); - } - - if(pNodeConvFrameRate) - { - CHECK_HR(hr = pNode->ConnectOutput(dwOutputIndex, pNodeConvFrameRate, 0)); - if(pNodeConvSize) - { - CHECK_HR(hr = pNodeConvFrameRate->ConnectOutput(0, pNodeConvSize, 0)); - if(pNodeConvColor) - { - CHECK_HR(hr = pNodeConvSize->ConnectOutput(0, pNodeConvColor, 0)); - } - } - else - { - if(pNodeConvColor) - { - CHECK_HR(hr = pNodeConvFrameRate->ConnectOutput(0, pNodeConvColor, 0)); - } - } - } - else - { - if(pNodeConvSize) - { - CHECK_HR(hr = pNode->ConnectOutput(dwOutputIndex, pNodeConvSize, 0)); - if(pNodeConvColor) - { - CHECK_HR(hr = pNodeConvSize->ConnectOutput(0, pNodeConvColor, 0)); - } - } - else - { - if(pNodeConvColor) - { - CHECK_HR(hr = pNode->ConnectOutput(dwOutputIndex, pNodeConvColor, 0)); - } - } - } + HRESULT hr = S_OK; + + if(!pNode) { + CHECK_HR(hr = E_POINTER); + } + + if(pNodeConvFrameRate) { + CHECK_HR(hr = pNode->ConnectOutput(dwOutputIndex, pNodeConvFrameRate, 0)); + if(pNodeConvSize) { + CHECK_HR(hr = pNodeConvFrameRate->ConnectOutput(0, pNodeConvSize, 0)); + if(pNodeConvColor) { + CHECK_HR(hr = pNodeConvSize->ConnectOutput(0, pNodeConvColor, 0)); + } + } + else { + if(pNodeConvColor) { + CHECK_HR(hr = pNodeConvFrameRate->ConnectOutput(0, pNodeConvColor, 0)); + } + } + } + else { + if(pNodeConvSize) { + CHECK_HR(hr = pNode->ConnectOutput(dwOutputIndex, pNodeConvSize, 0)); + if(pNodeConvColor) { + CHECK_HR(hr = pNodeConvSize->ConnectOutput(0, pNodeConvColor, 0)); + } + } + else { + if(pNodeConvColor) { + CHECK_HR(hr = pNode->ConnectOutput(dwOutputIndex, pNodeConvColor, 0)); + } + } + } bail: - return hr; + return hr; } // This function should be called only if VideoProcessor is not supported HRESULT MFUtils::GetBestFormat( - IMFMediaSource *pSource, - const GUID *pSubType, - UINT32 nWidth, - UINT32 nHeight, - UINT32 nFps, - UINT32 *pnWidth, - UINT32 *pnHeight, - UINT32 *pnFps, - const VideoSubTypeGuidPair **ppSubTypeGuidPair - ) + IMFMediaSource *pSource, + const GUID *pSubType, + UINT32 nWidth, + UINT32 nHeight, + UINT32 nFps, + UINT32 *pnWidth, + UINT32 *pnHeight, + UINT32 *pnFps, + const VideoSubTypeGuidPair **ppSubTypeGuidPair +) { #define _FindPairByGuid(_guid, _index) { \ @@ -1954,151 +1799,146 @@ HRESULT MFUtils::GetBestFormat( } \ } #if 0 - *pnWidth = 640; - *pnHeight = 480; - *pnFps = 30; - return S_OK; -#else - HRESULT hr = S_OK; - IMFPresentationDescriptor *pPD = NULL; - IMFStreamDescriptor *pSD = NULL; - IMFMediaTypeHandler *pHandler = NULL; - IMFMediaType *pMediaType = NULL; - DWORD cStreams = 0, cMediaTypesCount; - GUID majorType, subType, _BestSubType; - BOOL bFound = FALSE, fSelected; - UINT32 _nWidth, _nHeight, numeratorFps, denominatorFps, _nFps, _nScore, _nBestScore; - int PreferredVideoSubTypeGuidPairIndex; - static const UINT32 kSubTypeMismatchPad = _UI32_MAX >> 4; - static const UINT32 kFpsMismatchPad = _UI32_MAX >> 2; - - if (!ppSubTypeGuidPair || !pSubType) { - CHECK_HR(hr = E_INVALIDARG); - } - _FindPairByGuid(*pSubType, PreferredVideoSubTypeGuidPairIndex); - if (PreferredVideoSubTypeGuidPairIndex == -1) { - CHECK_HR(hr = E_INVALIDARG); - } - *ppSubTypeGuidPair = &PreferredVideoSubTypeGuidPairs[PreferredVideoSubTypeGuidPairIndex]; - - _nBestScore = _UI32_MAX; - CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); - CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); - - - for (DWORD i = 0; i < cStreams; i++) - { - fSelected = FALSE; - - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); - - if (fSelected) - { - CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); - - CHECK_HR(hr = pHandler->GetMajorType(&majorType)); - - if(majorType == MFMediaType_Video) - { - CHECK_HR(hr = pHandler->GetMediaTypeCount(&cMediaTypesCount)); - - for(DWORD cMediaTypesIndex = 0; cMediaTypesIndex < cMediaTypesCount; ++cMediaTypesIndex) - { - CHECK_HR(hr = pHandler->GetMediaTypeByIndex(cMediaTypesIndex, &pMediaType)); - - CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); - // if(subType == *pSubType) - { - CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &_nWidth, &_nHeight)); - CHECK_HR(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &numeratorFps, &denominatorFps)); - _nFps = (numeratorFps / denominatorFps); - - if (subType == *pSubType) { - _nScore = 0; - } - else { - _FindPairByGuid(subType, PreferredVideoSubTypeGuidPairIndex); - if (PreferredVideoSubTypeGuidPairIndex == -1) { - _nScore = kSubTypeMismatchPad; // Not a must but important: If(!VideoProcess) then CLSID_CColorConvertDMO - } - else { - _nScore = kSubTypeMismatchPad >> (PreferredVideoSubTypeGuidPairsCount - PreferredVideoSubTypeGuidPairIndex); - } - } - _nScore += abs((int)(_nWidth - nWidth)); // Not a must: If(!VideoProcess) then CLSID_CResizerDMO - _nScore += abs((int)(_nHeight - nHeight)); // Not a must: If(!VideoProcess) then CLSID_CResizerDMO - _nScore += (_nFps == nFps) ? 0 : kFpsMismatchPad; // Fps is a must because without video processor no alternative exist (CLSID_CFrameRateConvertDmo doesn't support I420) - - if (_nScore <= _nBestScore || !bFound) - { - *pnWidth = _nWidth; - *pnHeight = _nHeight; - *pnFps = _nFps; - bFound = TRUE; - _BestSubType = subType; - _nBestScore = _nScore; - } - } - - SafeRelease(&pMediaType); - } - } - } - - SafeRelease(&pHandler); - SafeRelease(&pSD); - } + *pnWidth = 640; + *pnHeight = 480; + *pnFps = 30; + return S_OK; +#else + HRESULT hr = S_OK; + IMFPresentationDescriptor *pPD = NULL; + IMFStreamDescriptor *pSD = NULL; + IMFMediaTypeHandler *pHandler = NULL; + IMFMediaType *pMediaType = NULL; + DWORD cStreams = 0, cMediaTypesCount; + GUID majorType, subType, _BestSubType; + BOOL bFound = FALSE, fSelected; + UINT32 _nWidth, _nHeight, numeratorFps, denominatorFps, _nFps, _nScore, _nBestScore; + int PreferredVideoSubTypeGuidPairIndex; + static const UINT32 kSubTypeMismatchPad = _UI32_MAX >> 4; + static const UINT32 kFpsMismatchPad = _UI32_MAX >> 2; + + if (!ppSubTypeGuidPair || !pSubType) { + CHECK_HR(hr = E_INVALIDARG); + } + _FindPairByGuid(*pSubType, PreferredVideoSubTypeGuidPairIndex); + if (PreferredVideoSubTypeGuidPairIndex == -1) { + CHECK_HR(hr = E_INVALIDARG); + } + *ppSubTypeGuidPair = &PreferredVideoSubTypeGuidPairs[PreferredVideoSubTypeGuidPairIndex]; + + _nBestScore = _UI32_MAX; + CHECK_HR(hr = pSource->CreatePresentationDescriptor(&pPD)); + CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); + + + for (DWORD i = 0; i < cStreams; i++) { + fSelected = FALSE; + + CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &pSD)); + + if (fSelected) { + CHECK_HR(hr = pSD->GetMediaTypeHandler(&pHandler)); + + CHECK_HR(hr = pHandler->GetMajorType(&majorType)); + + if(majorType == MFMediaType_Video) { + CHECK_HR(hr = pHandler->GetMediaTypeCount(&cMediaTypesCount)); + + for(DWORD cMediaTypesIndex = 0; cMediaTypesIndex < cMediaTypesCount; ++cMediaTypesIndex) { + CHECK_HR(hr = pHandler->GetMediaTypeByIndex(cMediaTypesIndex, &pMediaType)); + + CHECK_HR(hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &subType)); + // if(subType == *pSubType) + { + CHECK_HR(hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &_nWidth, &_nHeight)); + CHECK_HR(hr = MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, &numeratorFps, &denominatorFps)); + _nFps = (numeratorFps / denominatorFps); + + if (subType == *pSubType) { + _nScore = 0; + } + else { + _FindPairByGuid(subType, PreferredVideoSubTypeGuidPairIndex); + if (PreferredVideoSubTypeGuidPairIndex == -1) { + _nScore = kSubTypeMismatchPad; // Not a must but important: If(!VideoProcess) then CLSID_CColorConvertDMO + } + else { + _nScore = kSubTypeMismatchPad >> (PreferredVideoSubTypeGuidPairsCount - PreferredVideoSubTypeGuidPairIndex); + } + } + _nScore += abs((int)(_nWidth - nWidth)); // Not a must: If(!VideoProcess) then CLSID_CResizerDMO + _nScore += abs((int)(_nHeight - nHeight)); // Not a must: If(!VideoProcess) then CLSID_CResizerDMO + _nScore += (_nFps == nFps) ? 0 : kFpsMismatchPad; // Fps is a must because without video processor no alternative exist (CLSID_CFrameRateConvertDmo doesn't support I420) + + if (_nScore <= _nBestScore || !bFound) { + *pnWidth = _nWidth; + *pnHeight = _nHeight; + *pnFps = _nFps; + bFound = TRUE; + _BestSubType = subType; + _nBestScore = _nScore; + } + } + + SafeRelease(&pMediaType); + } + } + } + + SafeRelease(&pHandler); + SafeRelease(&pSD); + } bail: - SafeRelease(&pPD); - SafeRelease(&pSD); - SafeRelease(&pHandler); - SafeRelease(&pMediaType); - - _FindPairByGuid(_BestSubType, PreferredVideoSubTypeGuidPairIndex); - if (PreferredVideoSubTypeGuidPairIndex != -1) { - *ppSubTypeGuidPair = &PreferredVideoSubTypeGuidPairs[PreferredVideoSubTypeGuidPairIndex]; - } - else /*if (_nBestScore > kSubTypeMismatchPad)*/ { - *pnWidth = 640; - *pnHeight = 480; - *pnFps = 30; - TSK_DEBUG_WARN("Failed to math subtype...using VGA@30fps"); - } - - return SUCCEEDED(hr) ? (bFound ? S_OK : E_NOT_SET): hr; + SafeRelease(&pPD); + SafeRelease(&pSD); + SafeRelease(&pHandler); + SafeRelease(&pMediaType); + + _FindPairByGuid(_BestSubType, PreferredVideoSubTypeGuidPairIndex); + if (PreferredVideoSubTypeGuidPairIndex != -1) { + *ppSubTypeGuidPair = &PreferredVideoSubTypeGuidPairs[PreferredVideoSubTypeGuidPairIndex]; + } + else { /*if (_nBestScore > kSubTypeMismatchPad)*/ + *pnWidth = 640; + *pnHeight = 480; + *pnFps = 30; + TSK_DEBUG_WARN("Failed to math subtype...using VGA@30fps"); + } + + return SUCCEEDED(hr) ? (bFound ? S_OK : E_NOT_SET): hr; #endif } HWND MFUtils::GetConsoleHwnd(void) { - #define MY_BUFSIZE 1024 // Buffer size for console window titles. - HWND hwndFound; // This is what is returned to the caller. - TCHAR pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated - // WindowTitle. - TCHAR pszOldWindowTitle[MY_BUFSIZE]; // Contains original - // WindowTitle. +#define MY_BUFSIZE 1024 // Buffer size for console window titles. + HWND hwndFound; // This is what is returned to the caller. + TCHAR pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated + // WindowTitle. + TCHAR pszOldWindowTitle[MY_BUFSIZE]; // Contains original + // WindowTitle. - // Fetch current window title. - GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); + // Fetch current window title. + GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); - // Format a "unique" NewWindowTitle. - wsprintf(pszNewWindowTitle,TEXT("%d/%d"), - GetTickCount(), - GetCurrentProcessId()); + // Format a "unique" NewWindowTitle. + wsprintf(pszNewWindowTitle,TEXT("%d/%d"), + GetTickCount(), + GetCurrentProcessId()); - // Change current window title. - SetConsoleTitle(pszNewWindowTitle); + // Change current window title. + SetConsoleTitle(pszNewWindowTitle); - // Ensure window title has been updated. - Sleep(40); + // Ensure window title has been updated. + Sleep(40); - // Look for NewWindowTitle. - hwndFound=FindWindow(NULL, pszNewWindowTitle); + // Look for NewWindowTitle. + hwndFound=FindWindow(NULL, pszNewWindowTitle); - // Restore original window title. - SetConsoleTitle(pszOldWindowTitle); + // Restore original window title. + SetConsoleTitle(pszOldWindowTitle); - return(hwndFound); + return(hwndFound); } diff --git a/plugins/pluginWinMF/internals/mf_utils.h b/plugins/pluginWinMF/internals/mf_utils.h index 0819597..1225b3b 100755 --- a/plugins/pluginWinMF/internals/mf_utils.h +++ b/plugins/pluginWinMF/internals/mf_utils.h @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -35,14 +35,13 @@ (*ppT)->Release(); \ *ppT = NULL; \ } \ -} +} #undef CHECK_HR // In CHECK_HR(x) When (x) is a function it will be executed twice when used in "TSK_DEBUG_ERROR(x)" and "If(x)" #define CHECK_HR(x) { HRESULT __hr__ = (x); if (FAILED(__hr__)) { TSK_DEBUG_ERROR("Operation Failed (%08x)", __hr__); goto bail; } } -typedef struct VideoSubTypeGuidPair -{ +typedef struct VideoSubTypeGuidPair { enum tmedia_chroma_e chroma; const GUID& fourcc; } @@ -52,209 +51,207 @@ class MFUtils { public: -static HRESULT Startup(); -static HRESULT Shutdown(); + static HRESULT Startup(); + static HRESULT Shutdown(); -static BOOL IsD3D9Supported(); -static BOOL IsLowLatencyH264Supported(); -static BOOL IsLowLatencyH264SupportsMaxSliceSize(); + static BOOL IsD3D9Supported(); + static BOOL IsLowLatencyH264Supported(); + static BOOL IsLowLatencyH264SupportsMaxSliceSize(); -static HRESULT IsAsyncMFT( - IMFTransform *pMFT, // The MFT to check - BOOL* pbIsAsync // Whether the MFT is Async - ); -static HRESULT UnlockAsyncMFT( - IMFTransform *pMFT // The MFT to unlock - ); + static HRESULT IsAsyncMFT( + IMFTransform *pMFT, // The MFT to check + BOOL* pbIsAsync // Whether the MFT is Async + ); + static HRESULT UnlockAsyncMFT( + IMFTransform *pMFT // The MFT to unlock + ); -static HRESULT CreatePCMAudioType( - UINT32 sampleRate, // Samples per second - UINT32 bitsPerSample, // Bits per sample - UINT32 cChannels, // Number of channels - IMFMediaType **ppType // Receives a pointer to the media type. + static HRESULT CreatePCMAudioType( + UINT32 sampleRate, // Samples per second + UINT32 bitsPerSample, // Bits per sample + UINT32 cChannels, // Number of channels + IMFMediaType **ppType // Receives a pointer to the media type. + ); + static HRESULT CreateVideoType( + const GUID* subType, // video subType + IMFMediaType **ppType, // Receives a pointer to the media type. + UINT32 unWidth = 0, // Video width (0 to ignore) + UINT32 unHeight = 0 // Video height (0 to ignore) + ); + static HRESULT ConvertVideoTypeToUncompressedType( + IMFMediaType *pType, // Pointer to an encoded video type. + const GUID& subtype, // Uncompressed subtype (eg, RGB-32, AYUV) + IMFMediaType **ppType // Receives a matching uncompressed video type. + ); + static HRESULT CreateMediaSample( + DWORD cbData, // Maximum buffer size + IMFSample **ppSample // Receives the sample + ); + static HRESULT ValidateVideoFormat( + IMFMediaType *pmt + ); + static HRESULT IsVideoProcessorSupported(BOOL *pbSupported); + static HRESULT GetBestVideoProcessor( + const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_I420) + const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_NV12) + IMFTransform **ppProcessor // Receives the video processor + ); + static HRESULT GetBestCodec( + BOOL bEncoder, // Whether we request an encoder or not (TRUE=encoder, FALSE=decoder) + const GUID& mediaType, // The MediaType + const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_NV12) + const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_H264) + IMFTransform **ppMFT // Receives the decoder/encoder transform + ); + static HRESULT BindOutputNode( + IMFTopologyNode *pNode // The Node + ); + static HRESULT AddOutputNode( + IMFTopology *pTopology, // Topology. + IMFActivate *pActivate, // Media sink activation object. + DWORD dwId, // Identifier of the stream sink. + IMFTopologyNode **ppNode // Receives the node pointer. + ); + static HRESULT AddTransformNode( + IMFTopology *pTopology, // Topology. + IMFTransform *pMFT, // MFT. + DWORD dwId, // Identifier of the stream sink. + IMFTopologyNode **ppNode // Receives the node pointer. + ); + static HRESULT AddSourceNode( + IMFTopology *pTopology, // Topology. + IMFMediaSource *pSource, // Media source. + IMFPresentationDescriptor *pPD, // Presentation descriptor. + IMFStreamDescriptor *pSD, // Stream descriptor. + IMFTopologyNode **ppNode // Receives the node pointer. ); -static HRESULT CreateVideoType( - const GUID* subType, // video subType - IMFMediaType **ppType, // Receives a pointer to the media type. - UINT32 unWidth = 0, // Video width (0 to ignore) - UINT32 unHeight = 0 // Video height (0 to ignore) - ); -static HRESULT ConvertVideoTypeToUncompressedType( - IMFMediaType *pType, // Pointer to an encoded video type. - const GUID& subtype, // Uncompressed subtype (eg, RGB-32, AYUV) - IMFMediaType **ppType // Receives a matching uncompressed video type. + static HRESULT CreateTopology( + IMFMediaSource *pSource, // Media source + IMFTransform *pTransform, // Transform filter (e.g. encoder or decoder) to insert between the source and Sink. NULL is valid. + IMFActivate *pSinkActivateMain, // Main sink (e.g. sample grabber or EVR). + IMFActivate *pSinkActivatePreview, // Preview sink. Optional. Could be NULL. + IMFMediaType *pIputTypeMain, // Main sink input MediaType + IMFTopology **ppTopo // Receives the newly created topology + ); + static HRESULT ResolveTopology( + IMFTopology *pInputTopo, // A pointer to the IMFTopology interface of the partial topology to be resolved. + IMFTopology **ppOutputTopo, // Receives a pointer to the IMFTopology interface of the completed topology. The caller must release the interface. + IMFTopology *pCurrentTopo = NULL // A pointer to the IMFTopology interface of the previous full topology. The topology loader can re-use objects from this topology in the new topology. This parameter can be NULL. + ); + static HRESULT FindNodeObject( + IMFTopology *pInputTopo, // The Topology containing the node to find + TOPOID qwTopoNodeID, //The identifier for the node + void** ppObject // Receives the Object + ); + static HRESULT CreateMediaSinkActivate( + IMFStreamDescriptor *pSourceSD, // Pointer to the stream descriptor. + HWND hVideoWindow, // Handle to the video clipping window. + IMFActivate **ppActivate + ); + static HRESULT SetMediaType( + IMFMediaSource *pSource, // Media source. + IMFMediaType* pMediaType // Media Type. + ); + static HRESULT SetVideoWindow( + IMFTopology *pTopology, // Topology. + IMFMediaSource *pSource, // Media source. + HWND hVideoWnd // Window for video playback. + ); + static HRESULT RunSession( + IMFMediaSession *pSession, // Session to run + IMFTopology *pTopology // The toppology + ); + static HRESULT ShutdownSession( + IMFMediaSession *pSession, // The Session + IMFMediaSource *pSource = NULL // Source to shutdown (optional) + ); + static HRESULT PauseSession( + IMFMediaSession *pSession, // The session + IMFMediaSource *pSource = NULL// Source to pause (optional) + ); + static INT GetSupportedSubTypeIndex( + IMFMediaSource *pSource, // The source + const GUID& mediaType, // The MediaType + const VideoSubTypeGuidPair* subTypes, UINT subTypesCount // List of preferred subtypes (in ascending order) + ); + static HRESULT IsSupported( + IMFPresentationDescriptor *pPD, + DWORD cStreamIndex, + UINT32 nWidth, + UINT32 nHeight, + UINT32 nFps, + const GUID& guidFormat, + BOOL* pbSupportedSize, + BOOL* pbSupportedFps, + BOOL* pbSupportedFormat + ); + static HRESULT IsSupported( + IMFPresentationDescriptor *pPD, + DWORD cStreamIndex, + IMFMediaType* pMediaType, + BOOL* pbSupportedSize, + BOOL* pbSupportedFps, + BOOL* pbSupportedFormat + ); + static HRESULT IsSupportedByInput( + IMFPresentationDescriptor *pPD, + DWORD cStreamIndex, + IMFTopologyNode *pNode, + BOOL* pbSupportedSize, + BOOL* pbSupportedFps, + BOOL* pbSupportedFormat + ); + static HRESULT ConnectConverters( + IMFTopologyNode *pNode, + DWORD dwOutputIndex, + IMFTopologyNode *pNodeConvFrameRate, + IMFTopologyNode *pNodeConvColor, + IMFTopologyNode *pNodeConvSize + ); + static HRESULT GetBestFormat( + IMFMediaSource *pSource, + const GUID *pSubType, + UINT32 nWidth, + UINT32 nHeight, + UINT32 nFps, + UINT32 *pnWidth, + UINT32 *pnHeight, + UINT32 *pnFps, + const VideoSubTypeGuidPair **pSubTypeGuidPair ); -static HRESULT CreateMediaSample( - DWORD cbData, // Maximum buffer size - IMFSample **ppSample // Receives the sample - ); -static HRESULT ValidateVideoFormat( - IMFMediaType *pmt - ); -static HRESULT IsVideoProcessorSupported(BOOL *pbSupported); -static HRESULT GetBestVideoProcessor( - const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_I420) - const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_NV12) - IMFTransform **ppProcessor // Receives the video processor - ); -static HRESULT GetBestCodec( - BOOL bEncoder, // Whether we request an encoder or not (TRUE=encoder, FALSE=decoder) - const GUID& mediaType, // The MediaType - const GUID& inputFormat, // The input MediaFormat (e.g. MFVideoFormat_NV12) - const GUID& outputFormat, // The output MediaFormat (e.g. MFVideoFormat_H264) - IMFTransform **ppMFT // Receives the decoder/encoder transform - ); -static HRESULT BindOutputNode( - IMFTopologyNode *pNode // The Node - ); -static HRESULT AddOutputNode( - IMFTopology *pTopology, // Topology. - IMFActivate *pActivate, // Media sink activation object. - DWORD dwId, // Identifier of the stream sink. - IMFTopologyNode **ppNode // Receives the node pointer. - ); -static HRESULT AddTransformNode( - IMFTopology *pTopology, // Topology. - IMFTransform *pMFT, // MFT. - DWORD dwId, // Identifier of the stream sink. - IMFTopologyNode **ppNode // Receives the node pointer. - ); -static HRESULT AddSourceNode( - IMFTopology *pTopology, // Topology. - IMFMediaSource *pSource, // Media source. - IMFPresentationDescriptor *pPD, // Presentation descriptor. - IMFStreamDescriptor *pSD, // Stream descriptor. - IMFTopologyNode **ppNode // Receives the node pointer. - ); -static HRESULT CreateTopology( - IMFMediaSource *pSource, // Media source - IMFTransform *pTransform, // Transform filter (e.g. encoder or decoder) to insert between the source and Sink. NULL is valid. - IMFActivate *pSinkActivateMain, // Main sink (e.g. sample grabber or EVR). - IMFActivate *pSinkActivatePreview, // Preview sink. Optional. Could be NULL. - IMFMediaType *pIputTypeMain, // Main sink input MediaType - IMFTopology **ppTopo // Receives the newly created topology - ); -static HRESULT ResolveTopology( - IMFTopology *pInputTopo, // A pointer to the IMFTopology interface of the partial topology to be resolved. - IMFTopology **ppOutputTopo, // Receives a pointer to the IMFTopology interface of the completed topology. The caller must release the interface. - IMFTopology *pCurrentTopo = NULL // A pointer to the IMFTopology interface of the previous full topology. The topology loader can re-use objects from this topology in the new topology. This parameter can be NULL. - ); -static HRESULT FindNodeObject( - IMFTopology *pInputTopo, // The Topology containing the node to find - TOPOID qwTopoNodeID, //The identifier for the node - void** ppObject // Receives the Object - ); -static HRESULT CreateMediaSinkActivate( - IMFStreamDescriptor *pSourceSD, // Pointer to the stream descriptor. - HWND hVideoWindow, // Handle to the video clipping window. - IMFActivate **ppActivate -); -static HRESULT SetMediaType( - IMFMediaSource *pSource, // Media source. - IMFMediaType* pMediaType // Media Type. - ); -static HRESULT SetVideoWindow( - IMFTopology *pTopology, // Topology. - IMFMediaSource *pSource, // Media source. - HWND hVideoWnd // Window for video playback. - ); -static HRESULT RunSession( - IMFMediaSession *pSession, // Session to run - IMFTopology *pTopology // The toppology - ); -static HRESULT ShutdownSession( - IMFMediaSession *pSession, // The Session - IMFMediaSource *pSource = NULL // Source to shutdown (optional) - ); -static HRESULT PauseSession( - IMFMediaSession *pSession, // The session - IMFMediaSource *pSource = NULL// Source to pause (optional) - ); -static INT GetSupportedSubTypeIndex( - IMFMediaSource *pSource, // The source - const GUID& mediaType, // The MediaType - const VideoSubTypeGuidPair* subTypes, UINT subTypesCount // List of preferred subtypes (in ascending order) - ); -static HRESULT IsSupported( - IMFPresentationDescriptor *pPD, - DWORD cStreamIndex, - UINT32 nWidth, - UINT32 nHeight, - UINT32 nFps, - const GUID& guidFormat, - BOOL* pbSupportedSize, - BOOL* pbSupportedFps, - BOOL* pbSupportedFormat - ); -static HRESULT IsSupported( - IMFPresentationDescriptor *pPD, - DWORD cStreamIndex, - IMFMediaType* pMediaType, - BOOL* pbSupportedSize, - BOOL* pbSupportedFps, - BOOL* pbSupportedFormat - ); -static HRESULT IsSupportedByInput( - IMFPresentationDescriptor *pPD, - DWORD cStreamIndex, - IMFTopologyNode *pNode, - BOOL* pbSupportedSize, - BOOL* pbSupportedFps, - BOOL* pbSupportedFormat - ); -static HRESULT ConnectConverters( - IMFTopologyNode *pNode, - DWORD dwOutputIndex, - IMFTopologyNode *pNodeConvFrameRate, - IMFTopologyNode *pNodeConvColor, - IMFTopologyNode *pNodeConvSize - ); -static HRESULT GetBestFormat( - IMFMediaSource *pSource, - const GUID *pSubType, - UINT32 nWidth, - UINT32 nHeight, - UINT32 nFps, - UINT32 *pnWidth, - UINT32 *pnHeight, - UINT32 *pnFps, - const VideoSubTypeGuidPair **pSubTypeGuidPair - ); -static HWND GetConsoleHwnd(void); + static HWND GetConsoleHwnd(void); -template <class Q> -static HRESULT GetTopoNodeObject(IMFTopologyNode *pNode, Q **ppObject) -{ - IUnknown *pUnk = NULL; // zero output + template <class Q> + static HRESULT GetTopoNodeObject(IMFTopologyNode *pNode, Q **ppObject) { + IUnknown *pUnk = NULL; // zero output - HRESULT hr = pNode->GetObject(&pUnk); - if (SUCCEEDED(hr)) - { - pUnk->QueryInterface(IID_PPV_ARGS(ppObject)); - pUnk->Release(); + HRESULT hr = pNode->GetObject(&pUnk); + if (SUCCEEDED(hr)) { + pUnk->QueryInterface(IID_PPV_ARGS(ppObject)); + pUnk->Release(); + } + return hr; } - return hr; -} private: - static BOOL g_bStarted; + static BOOL g_bStarted; - static DWORD g_dwMajorVersion; - static DWORD g_dwMinorVersion; + static DWORD g_dwMajorVersion; + static DWORD g_dwMinorVersion; - static BOOL g_bLowLatencyH264Checked; - static BOOL g_bLowLatencyH264Supported; - static BOOL g_bLowLatencyH264SupportsMaxSliceSize; + static BOOL g_bLowLatencyH264Checked; + static BOOL g_bLowLatencyH264Supported; + static BOOL g_bLowLatencyH264SupportsMaxSliceSize; - static BOOL g_bD3D9Checked; - static BOOL g_bD3D9Supported; + static BOOL g_bD3D9Checked; + static BOOL g_bD3D9Supported; public: - static const TOPOID g_ullTopoIdSinkMain; - static const TOPOID g_ullTopoIdSinkPreview; - static const TOPOID g_ullTopoIdSource; - static const TOPOID g_ullTopoIdVideoProcessor; + static const TOPOID g_ullTopoIdSinkMain; + static const TOPOID g_ullTopoIdSinkPreview; + static const TOPOID g_ullTopoIdSource; + static const TOPOID g_ullTopoIdVideoProcessor; }; #endif /* PLUGIN_WIN_MF_UTILS_H */ |