This source file includes following definitions.
- clamp
- m_pAttributes
- RuntimeClassInitialize
- SetProperties
- GetStreamLimits
- GetStreamCount
- GetStreamIDs
- GetInputStreamInfo
- GetOutputStreamInfo
- GetAttributes
- GetInputStreamAttributes
- GetOutputStreamAttributes
- DeleteInputStream
- AddInputStreams
- GetInputAvailableType
- GetOutputAvailableType
- SetInputType
- SetOutputType
- GetInputCurrentType
- GetOutputCurrentType
- GetInputStatus
- GetOutputStatus
- SetOutputBounds
- ProcessEvent
- ProcessMessage
- ProcessInput
- ProcessOutput
- OnGetPartialType
- OnCheckInputType
- OnCheckOutputType
- OnCheckMediaType
- OnSetInputType
- OnSetOutputType
- BeginStreaming
- EndStreaming
- OnProcessOutput
- OnFlush
- UpdateFormatInfo
- GetDefaultStride
#include "OcvTransform.h"
#include "bufferlock.h"
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\features2d\features2d.hpp>
using namespace Microsoft::WRL;
const GUID g_MediaSubtypes[] =
{
MFVideoFormat_NV12
};
HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride);
template <typename T>
inline T clamp(const T& val, const T& minVal, const T& maxVal)
{
return (val < minVal ? minVal : (val > maxVal ? maxVal : val));
}
OcvImageManipulations::OcvImageManipulations() :
m_pSample(NULL), m_pInputType(NULL), m_pOutputType(NULL),
m_imageWidthInPixels(0), m_imageHeightInPixels(0), m_cbImageSize(0),
m_TransformType(Preview), m_bStreamingInitialized(false),
m_pAttributes(NULL)
{
InitializeCriticalSectionEx(&m_critSec, 3000, 0);
}
OcvImageManipulations::~OcvImageManipulations()
{
SafeRelease(&m_pInputType);
SafeRelease(&m_pOutputType);
SafeRelease(&m_pSample);
SafeRelease(&m_pAttributes);
DeleteCriticalSection(&m_critSec);
}
STDMETHODIMP OcvImageManipulations::RuntimeClassInitialize()
{
return MFCreateAttributes(&m_pAttributes, 3);
}
HRESULT OcvImageManipulations::SetProperties(ABI::Windows::Foundation::Collections::IPropertySet *pConfiguration)
{
HRESULT hr = S_OK;
if (!pConfiguration)
return hr;
HSTRING key;
WindowsCreateString(L"{698649BE-8EAE-4551-A4CB-3EC98FBD3D86}", 38, &key);
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> spSetting;
pConfiguration->QueryInterface(IID_PPV_ARGS(&spSetting));
boolean found;
spSetting->HasKey(key, &found);
if (found)
{
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IPropertyValue> spPropVal;
Microsoft::WRL::ComPtr<IInspectable> spInsp;
spSetting->Lookup(key, spInsp.ReleaseAndGetAddressOf());
hr = spInsp.As(&spPropVal);
if (hr != S_OK)
{
return hr;
}
INT32 effect;
hr = spPropVal->GetInt32(&effect);
if (hr != S_OK)
{
return hr;
}
if ((effect >= 0) && (effect < InvalidEffect))
{
m_TransformType = (ProcessingType)effect;
}
}
return hr;
}
HRESULT OcvImageManipulations::GetStreamLimits(
DWORD *pdwInputMinimum,
DWORD *pdwInputMaximum,
DWORD *pdwOutputMinimum,
DWORD *pdwOutputMaximum
)
{
if ((pdwInputMinimum == NULL) ||
(pdwInputMaximum == NULL) ||
(pdwOutputMinimum == NULL) ||
(pdwOutputMaximum == NULL))
{
return E_POINTER;
}
*pdwInputMinimum = 1;
*pdwInputMaximum = 1;
*pdwOutputMinimum = 1;
*pdwOutputMaximum = 1;
return S_OK;
}
HRESULT OcvImageManipulations::GetStreamCount(
DWORD *pcInputStreams,
DWORD *pcOutputStreams
)
{
if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
{
return E_POINTER;
}
*pcInputStreams = 1;
*pcOutputStreams = 1;
return S_OK;
}
HRESULT OcvImageManipulations::GetStreamIDs(
DWORD dwInputIDArraySize,
DWORD *pdwInputIDs,
DWORD dwOutputIDArraySize,
DWORD *pdwOutputIDs
)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::GetInputStreamInfo(
DWORD dwInputStreamID,
MFT_INPUT_STREAM_INFO * pStreamInfo
)
{
if (pStreamInfo == NULL)
{
return E_POINTER;
}
EnterCriticalSection(&m_critSec);
if (!IsValidInputStream(dwInputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
pStreamInfo->hnsMaxLatency = 0;
pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
if (m_pInputType == NULL)
{
pStreamInfo->cbSize = 0;
}
else
{
pStreamInfo->cbSize = m_cbImageSize;
}
pStreamInfo->cbMaxLookahead = 0;
pStreamInfo->cbAlignment = 0;
LeaveCriticalSection(&m_critSec);
return S_OK;
}
HRESULT OcvImageManipulations::GetOutputStreamInfo(
DWORD dwOutputStreamID,
MFT_OUTPUT_STREAM_INFO * pStreamInfo
)
{
if (pStreamInfo == NULL)
{
return E_POINTER;
}
EnterCriticalSection(&m_critSec);
if (!IsValidOutputStream(dwOutputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
pStreamInfo->dwFlags =
MFT_OUTPUT_STREAM_WHOLE_SAMPLES |
MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE ;
if (m_pOutputType == NULL)
{
pStreamInfo->cbSize = 0;
}
else
{
pStreamInfo->cbSize = m_cbImageSize;
}
pStreamInfo->cbAlignment = 0;
LeaveCriticalSection(&m_critSec);
return S_OK;
}
HRESULT OcvImageManipulations::GetAttributes(IMFAttributes** ppAttributes)
{
if (ppAttributes == NULL)
{
return E_POINTER;
}
EnterCriticalSection(&m_critSec);
*ppAttributes = m_pAttributes;
(*ppAttributes)->AddRef();
LeaveCriticalSection(&m_critSec);
return S_OK;
}
HRESULT OcvImageManipulations::GetInputStreamAttributes(
DWORD dwInputStreamID,
IMFAttributes **ppAttributes
)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::GetOutputStreamAttributes(
DWORD dwOutputStreamID,
IMFAttributes **ppAttributes
)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::DeleteInputStream(DWORD dwStreamID)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::AddInputStreams(
DWORD cStreams,
DWORD *adwStreamIDs
)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::GetInputAvailableType(
DWORD dwInputStreamID,
DWORD dwTypeIndex,
IMFMediaType **ppType
)
{
if (ppType == NULL)
{
return E_INVALIDARG;
}
EnterCriticalSection(&m_critSec);
if (!IsValidInputStream(dwInputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
HRESULT hr = S_OK;
if (m_pOutputType == NULL)
{
hr = OnGetPartialType(dwTypeIndex, ppType);
}
else if (dwTypeIndex > 0)
{
hr = MF_E_NO_MORE_TYPES;
}
else
{
*ppType = m_pOutputType;
(*ppType)->AddRef();
}
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::GetOutputAvailableType(
DWORD dwOutputStreamID,
DWORD dwTypeIndex,
IMFMediaType **ppType
)
{
if (ppType == NULL)
{
return E_INVALIDARG;
}
EnterCriticalSection(&m_critSec);
if (!IsValidOutputStream(dwOutputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
HRESULT hr = S_OK;
if (m_pInputType == NULL)
{
hr = OnGetPartialType(dwTypeIndex, ppType);
}
else if (dwTypeIndex > 0)
{
hr = MF_E_NO_MORE_TYPES;
}
else
{
*ppType = m_pInputType;
(*ppType)->AddRef();
}
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::SetInputType(
DWORD dwInputStreamID,
IMFMediaType *pType,
DWORD dwFlags
)
{
if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
{
return E_INVALIDARG;
}
EnterCriticalSection(&m_critSec);
if (!IsValidInputStream(dwInputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
HRESULT hr = S_OK;
BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
if (HasPendingOutput())
{
hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
goto done;
}
if (pType)
{
hr = OnCheckInputType(pType);
if (FAILED(hr))
{
goto done;
}
}
if (bReallySet)
{
OnSetInputType(pType);
hr = EndStreaming();
}
done:
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::SetOutputType(
DWORD dwOutputStreamID,
IMFMediaType *pType,
DWORD dwFlags
)
{
if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
{
return E_INVALIDARG;
}
EnterCriticalSection(&m_critSec);
if (!IsValidOutputStream(dwOutputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
HRESULT hr = S_OK;
BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
if (HasPendingOutput())
{
hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
goto done;
}
if (pType)
{
hr = OnCheckOutputType(pType);
if (FAILED(hr))
{
goto done;
}
}
if (bReallySet)
{
OnSetOutputType(pType);
hr = EndStreaming();
}
done:
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::GetInputCurrentType(
DWORD dwInputStreamID,
IMFMediaType **ppType
)
{
if (ppType == NULL)
{
return E_POINTER;
}
HRESULT hr = S_OK;
EnterCriticalSection(&m_critSec);
if (!IsValidInputStream(dwInputStreamID))
{
hr = MF_E_INVALIDSTREAMNUMBER;
}
else if (!m_pInputType)
{
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
}
else
{
*ppType = m_pInputType;
(*ppType)->AddRef();
}
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::GetOutputCurrentType(
DWORD dwOutputStreamID,
IMFMediaType **ppType
)
{
if (ppType == NULL)
{
return E_POINTER;
}
HRESULT hr = S_OK;
EnterCriticalSection(&m_critSec);
if (!IsValidOutputStream(dwOutputStreamID))
{
hr = MF_E_INVALIDSTREAMNUMBER;
}
else if (!m_pOutputType)
{
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
}
else
{
*ppType = m_pOutputType;
(*ppType)->AddRef();
}
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::GetInputStatus(
DWORD dwInputStreamID,
DWORD *pdwFlags
)
{
if (pdwFlags == NULL)
{
return E_POINTER;
}
EnterCriticalSection(&m_critSec);
if (!IsValidInputStream(dwInputStreamID))
{
LeaveCriticalSection(&m_critSec);
return MF_E_INVALIDSTREAMNUMBER;
}
if (m_pSample == NULL)
{
*pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
}
else
{
*pdwFlags = 0;
}
LeaveCriticalSection(&m_critSec);
return S_OK;
}
HRESULT OcvImageManipulations::GetOutputStatus(DWORD *pdwFlags)
{
if (pdwFlags == NULL)
{
return E_POINTER;
}
EnterCriticalSection(&m_critSec);
if (m_pSample != NULL)
{
*pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
}
else
{
*pdwFlags = 0;
}
LeaveCriticalSection(&m_critSec);
return S_OK;
}
HRESULT OcvImageManipulations::SetOutputBounds(
LONGLONG hnsLowerBound,
LONGLONG hnsUpperBound
)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::ProcessEvent(
DWORD dwInputStreamID,
IMFMediaEvent *pEvent
)
{
return E_NOTIMPL;
}
HRESULT OcvImageManipulations::ProcessMessage(
MFT_MESSAGE_TYPE eMessage,
ULONG_PTR ulParam
)
{
EnterCriticalSection(&m_critSec);
HRESULT hr = S_OK;
switch (eMessage)
{
case MFT_MESSAGE_COMMAND_FLUSH:
hr = OnFlush();
break;
case MFT_MESSAGE_COMMAND_DRAIN:
break;
case MFT_MESSAGE_SET_D3D_MANAGER:
hr = E_NOTIMPL;
break;
case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
hr = BeginStreaming();
break;
case MFT_MESSAGE_NOTIFY_END_STREAMING:
hr = EndStreaming();
break;
case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
break;
case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
break;
}
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::ProcessInput(
DWORD dwInputStreamID,
IMFSample *pSample,
DWORD dwFlags
)
{
if (pSample == NULL)
{
return E_POINTER;
}
if (dwFlags != 0)
{
return E_INVALIDARG;
}
HRESULT hr = S_OK;
EnterCriticalSection(&m_critSec);
if (!IsValidInputStream(dwInputStreamID))
{
hr = MF_E_INVALIDSTREAMNUMBER;
goto done;
}
if (!m_pInputType || !m_pOutputType)
{
hr = MF_E_NOTACCEPTING;
goto done;
}
if (m_pSample != NULL)
{
hr = MF_E_NOTACCEPTING;
goto done;
}
hr = BeginStreaming();
if (FAILED(hr))
{
goto done;
}
m_pSample = pSample;
pSample->AddRef();
done:
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::ProcessOutput(
DWORD dwFlags,
DWORD cOutputBufferCount,
MFT_OUTPUT_DATA_BUFFER *pOutputSamples,
DWORD *pdwStatus
)
{
if (dwFlags != 0)
{
return E_INVALIDARG;
}
if (pOutputSamples == NULL || pdwStatus == NULL)
{
return E_POINTER;
}
if (cOutputBufferCount != 1)
{
return E_INVALIDARG;
}
if (pOutputSamples[0].pSample == NULL)
{
return E_INVALIDARG;
}
HRESULT hr = S_OK;
IMFMediaBuffer *pInput = NULL;
IMFMediaBuffer *pOutput = NULL;
EnterCriticalSection(&m_critSec);
if (m_pSample == NULL)
{
hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
goto done;
}
hr = BeginStreaming();
if (FAILED(hr))
{
goto done;
}
hr = m_pSample->ConvertToContiguousBuffer(&pInput);
if (FAILED(hr))
{
goto done;
}
hr = pOutputSamples[0].pSample->ConvertToContiguousBuffer(&pOutput);
if (FAILED(hr))
{
goto done;
}
hr = OnProcessOutput(pInput, pOutput);
if (FAILED(hr))
{
goto done;
}
pOutputSamples[0].dwStatus = 0;
*pdwStatus = 0;
LONGLONG hnsDuration = 0;
LONGLONG hnsTime = 0;
if (SUCCEEDED(m_pSample->GetSampleDuration(&hnsDuration)))
{
hr = pOutputSamples[0].pSample->SetSampleDuration(hnsDuration);
if (FAILED(hr))
{
goto done;
}
}
if (SUCCEEDED(m_pSample->GetSampleTime(&hnsTime)))
{
hr = pOutputSamples[0].pSample->SetSampleTime(hnsTime);
}
done:
SafeRelease(&m_pSample);
SafeRelease(&pInput);
SafeRelease(&pOutput);
LeaveCriticalSection(&m_critSec);
return hr;
}
HRESULT OcvImageManipulations::OnGetPartialType(DWORD dwTypeIndex, IMFMediaType **ppmt)
{
if (dwTypeIndex >= ARRAYSIZE(g_MediaSubtypes))
{
return MF_E_NO_MORE_TYPES;
}
IMFMediaType *pmt = NULL;
HRESULT hr = MFCreateMediaType(&pmt);
if (FAILED(hr))
{
goto done;
}
hr = pmt->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
if (FAILED(hr))
{
goto done;
}
hr = pmt->SetGUID(MF_MT_SUBTYPE, g_MediaSubtypes[dwTypeIndex]);
if (FAILED(hr))
{
goto done;
}
*ppmt = pmt;
(*ppmt)->AddRef();
done:
SafeRelease(&pmt);
return hr;
}
HRESULT OcvImageManipulations::OnCheckInputType(IMFMediaType *pmt)
{
assert(pmt != NULL);
HRESULT hr = S_OK;
if (m_pOutputType != NULL)
{
DWORD flags = 0;
hr = pmt->IsEqual(m_pOutputType, &flags);
if (hr != S_OK)
{
hr = MF_E_INVALIDMEDIATYPE;
}
}
else
{
hr = OnCheckMediaType(pmt);
}
return hr;
}
HRESULT OcvImageManipulations::OnCheckOutputType(IMFMediaType *pmt)
{
assert(pmt != NULL);
HRESULT hr = S_OK;
if (m_pInputType != NULL)
{
DWORD flags = 0;
hr = pmt->IsEqual(m_pInputType, &flags);
if (hr != S_OK)
{
hr = MF_E_INVALIDMEDIATYPE;
}
}
else
{
hr = OnCheckMediaType(pmt);
}
return hr;
}
HRESULT OcvImageManipulations::OnCheckMediaType(IMFMediaType *pmt)
{
BOOL bFoundMatchingSubtype = FALSE;
GUID major_type;
HRESULT hr = pmt->GetGUID(MF_MT_MAJOR_TYPE, &major_type);
if (FAILED(hr))
{
goto done;
}
if (major_type != MFMediaType_Video)
{
hr = MF_E_INVALIDMEDIATYPE;
goto done;
}
GUID subtype;
hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
if (FAILED(hr))
{
goto done;
}
for (DWORD i = 0; i < ARRAYSIZE(g_MediaSubtypes); i++)
{
if (subtype == g_MediaSubtypes[i])
{
bFoundMatchingSubtype = TRUE;
break;
}
}
if (!bFoundMatchingSubtype)
{
hr = MF_E_INVALIDMEDIATYPE;
goto done;
}
UINT32 interlace = MFGetAttributeUINT32(pmt, MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
if (interlace == MFVideoInterlace_FieldSingleUpper || interlace == MFVideoInterlace_FieldSingleLower)
{
hr = MF_E_INVALIDMEDIATYPE;
}
done:
return hr;
}
void OcvImageManipulations::OnSetInputType(IMFMediaType *pmt)
{
SafeRelease(&m_pInputType);
m_pInputType = pmt;
if (m_pInputType)
{
m_pInputType->AddRef();
}
UpdateFormatInfo();
}
void OcvImageManipulations::OnSetOutputType(IMFMediaType *pmt)
{
SafeRelease(&m_pOutputType);
m_pOutputType = pmt;
if (m_pOutputType)
{
m_pOutputType->AddRef();
}
}
HRESULT OcvImageManipulations::BeginStreaming()
{
HRESULT hr = S_OK;
if (!m_bStreamingInitialized)
{
m_bStreamingInitialized = true;
hr = S_OK;
}
return hr;
}
HRESULT OcvImageManipulations::EndStreaming()
{
m_bStreamingInitialized = false;
return S_OK;
}
HRESULT OcvImageManipulations::OnProcessOutput(IMFMediaBuffer *pIn, IMFMediaBuffer *pOut)
{
BYTE *pDest = NULL;
LONG lDestStride = 0;
BYTE *pSrc = NULL;
LONG lSrcStride = 0;
VideoBufferLock inputLock(pIn);
VideoBufferLock outputLock(pOut);
LONG lDefaultStride = 0;
HRESULT hr = GetDefaultStride(m_pInputType, &lDefaultStride);
if (FAILED(hr))
{
return hr;
}
hr = inputLock.LockBuffer(lDefaultStride, m_imageHeightInPixels, &pSrc, &lSrcStride);
if (FAILED(hr))
{
return hr;
}
hr = outputLock.LockBuffer(lDefaultStride, m_imageHeightInPixels, &pDest, &lDestStride);
if (FAILED(hr))
{
return hr;
}
cv::Mat InputFrame(m_imageHeightInPixels + m_imageHeightInPixels/2, m_imageWidthInPixels, CV_8UC1, pSrc, lSrcStride);
cv::Mat InputGreyScale(InputFrame, cv::Range(0, m_imageHeightInPixels), cv::Range(0, m_imageWidthInPixels));
cv::Mat OutputFrame(m_imageHeightInPixels + m_imageHeightInPixels/2, m_imageWidthInPixels, CV_8UC1, pDest, lDestStride);
switch (m_TransformType)
{
case Preview:
{
InputFrame.copyTo(OutputFrame);
} break;
case GrayScale:
{
OutputFrame.setTo(cv::Scalar(128));
cv::Mat OutputGreyScale(OutputFrame, cv::Range(0, m_imageHeightInPixels), cv::Range(0, m_imageWidthInPixels));
InputGreyScale.copyTo(OutputGreyScale);
} break;
case Canny:
{
OutputFrame.setTo(cv::Scalar(128));
cv::Mat OutputGreyScale(OutputFrame, cv::Range(0, m_imageHeightInPixels), cv::Range(0, m_imageWidthInPixels));
cv::Canny(InputGreyScale, OutputGreyScale, 80, 90);
} break;
case Sobel:
{
OutputFrame.setTo(cv::Scalar(128));
cv::Mat OutputGreyScale(OutputFrame, cv::Range(0, m_imageHeightInPixels), cv::Range(0, m_imageWidthInPixels));
cv::Sobel(InputGreyScale, OutputGreyScale, CV_8U, 1, 1);
} break;
case Histogram:
{
const int mHistSizeNum = 25;
const int channels[3][1] = {{0}, {1}, {2}};
const int mHistSize[] = {25};
const float baseRabge[] = {0.f,256.f};
const float* ranges[] = {baseRabge};
const cv::Scalar mColorsY[] = { cv::Scalar(76), cv::Scalar(149), cv::Scalar(29) };
const cv::Scalar mColorsUV[] = { cv::Scalar(84, 255), cv::Scalar(43, 21), cv::Scalar(255, 107) };
cv::Mat OutputY(m_imageHeightInPixels, m_imageWidthInPixels, CV_8UC1, pDest, lDestStride);
cv::Mat OutputUV(m_imageHeightInPixels/2, m_imageWidthInPixels/2,
CV_8UC2, pDest+m_imageHeightInPixels*lDestStride, lDestStride);
cv::Mat BgrFrame;
InputFrame.copyTo(OutputFrame);
cv::cvtColor(InputFrame, BgrFrame, cv::COLOR_YUV420sp2BGR);
int thikness = (int) (BgrFrame.cols / (mHistSizeNum + 10) / 5);
if(thikness > 5) thikness = 5;
int offset = (int) ((BgrFrame.cols - (5*mHistSizeNum + 4*10)*thikness)/2);
for (int c=0; c<3; c++)
{
cv::Mat hist;
cv::calcHist(&BgrFrame, 1, channels[c], cv::Mat(), hist, 1, mHistSize, ranges);
cv::normalize(hist, hist, BgrFrame.rows/2, 0, cv::NORM_INF);
for(int h=0; h<mHistSizeNum; h++) {
cv::Point mP1, mP2;
mP1.x = mP2.x = offset + (c * (mHistSizeNum + 10) + h) * thikness;
mP1.y = BgrFrame.rows-1;
mP2.y = mP1.y - 2 - (int)hist.at<float>(h);
cv::line(OutputY, mP1, mP2, mColorsY[c], thikness);
mP1.x /= 2;
mP1.y /= 2;
mP2.x /= 2;
mP2.y /= 2;
cv::line(OutputUV, mP1, mP2, mColorsUV[c], thikness/2);
}
}
} break;
default:
break;
}
hr = pOut->SetCurrentLength(m_cbImageSize);
return hr;
}
HRESULT OcvImageManipulations::OnFlush()
{
SafeRelease(&m_pSample);
return S_OK;
}
HRESULT OcvImageManipulations::UpdateFormatInfo()
{
HRESULT hr = S_OK;
GUID subtype = GUID_NULL;
m_imageWidthInPixels = 0;
m_imageHeightInPixels = 0;
m_cbImageSize = 0;
if (m_pInputType != NULL)
{
hr = m_pInputType->GetGUID(MF_MT_SUBTYPE, &subtype);
if (FAILED(hr))
{
goto done;
}
if (subtype != MFVideoFormat_NV12)
{
hr = E_UNEXPECTED;
goto done;
}
hr = MFGetAttributeSize(m_pInputType, MF_MT_FRAME_SIZE, &m_imageWidthInPixels, &m_imageHeightInPixels);
if (FAILED(hr))
{
goto done;
}
m_cbImageSize = (m_imageHeightInPixels + m_imageHeightInPixels/2)*m_imageWidthInPixels;
}
done:
return hr;
}
HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride)
{
LONG lStride = 0;
HRESULT hr = pType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&lStride);
if (FAILED(hr))
{
GUID subtype = GUID_NULL;
UINT32 width = 0;
UINT32 height = 0;
hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype);
if (SUCCEEDED(hr))
{
hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height);
}
if (SUCCEEDED(hr))
{
if (subtype == MFVideoFormat_NV12)
{
lStride = width;
}
else if (subtype == MFVideoFormat_YUY2 || subtype == MFVideoFormat_UYVY)
{
lStride = ((width * 2) + 3) & ~3;
}
else
{
hr = E_INVALIDARG;
}
}
if (SUCCEEDED(hr))
{
(void)pType->SetUINT32(MF_MT_DEFAULT_STRIDE, UINT32(lStride));
}
}
if (SUCCEEDED(hr))
{
*plStride = lStride;
}
return hr;
}