diff options
| author | j-leungyy <[email protected]> | 2021-05-25 09:06:09 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-05-25 09:06:09 -0700 |
| commit | 4fe5787f122fdfc45253b45f9fad3983f53d86df (patch) | |
| tree | a11e06f8951d4b7b847f6f5a708f86df87d637db /general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp | |
| parent | 53afd12aadb8aff15097f1546d4f80c6074e0bdc (diff) | |
update simplemediasource sample (#614)
* update simplemediasource wrl to winrtcpp COM, add mediatype NV12 (SimpleFrameGenerator), fix Mediatype missing attribute (bitrate), add IMFActivate, IMFSampleAllocator interface and implementation, update hardcode arg with named variables, cleanup sample for StreamIndex and StreamId, add sample KSControl
* address PR-it1 comments
* address comment from PR-it2, replace manual define of IKSControl by ksproxy.h
* remove unuse header
* address comment from PR
* fix sdk to latest, add driversign algorithm
* remove nudget, use submodule
Diffstat (limited to 'general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp')
| -rw-r--r-- | general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp b/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp new file mode 100644 index 00000000..6adafb44 --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp @@ -0,0 +1,146 @@ +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +#include "pch.h" + +HRESULT SimpleFrameGenerator::Initialize(_In_ IMFMediaType* pMediaType) +{ + RETURN_HR_IF_NULL(E_INVALIDARG, pMediaType); + + RETURN_IF_FAILED(pMediaType->GetGUID(MF_MT_SUBTYPE, &m_subType)); + if (m_subType != MFVideoFormat_RGB32 && m_subType != MFVideoFormat_NV12) + { + RETURN_HR_MSG(MF_E_UNSUPPORTED_FORMAT, "Unsupported format: %s", winrt::to_hstring(m_subType).data()); + } + MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &m_width, &m_height); + + return S_OK; +} + +/*: + Writes to a buffer representing a 2D image. + Writes a different constant to each line based on row number and current time. + Assumes top down image, no negative stride and pBuf points to the begnning of the buffer of length len. + Param: + pBuf - pointer to beginning of buffer + pitch - line length in bytes + len - length of buffer in bytes +*/ +HRESULT SimpleFrameGenerator::CreateFrame( + _Inout_updates_bytes_(len) BYTE* pBuf, + _In_ DWORD len, + _In_ LONG pitch, + _In_ ULONG rgbMask) +{ + if (m_subType == MFVideoFormat_RGB32) + { + DEBUG_MSG(L"RGB32 frames %s\n", winrt::to_hstring(MFVideoFormat_RGB32).data()); + + RETURN_IF_FAILED(_CreateRGB32Frame(pBuf, len, pitch, m_width, m_height, rgbMask)); + } + else if(m_subType == MFVideoFormat_NV12) + { + DEBUG_MSG(L"NV12 frames %s \n", winrt::to_hstring(MFVideoFormat_NV12).data()); + + DWORD frameBuffLen = m_width * m_height * 4; + wil::unique_cotaskmem_ptr<BYTE[]> spBuff = wil::make_unique_cotaskmem_nothrow<BYTE[]>(frameBuffLen); + RETURN_IF_NULL_ALLOC(spBuff.get()); + + RETURN_IF_FAILED(_CreateRGB32Frame(spBuff.get(), frameBuffLen, m_width * 4, m_width, m_height, rgbMask)); + RETURN_IF_FAILED(RGB32ToNV12Frame(spBuff.get(), frameBuffLen, m_width * 4, m_width, m_height, pBuf, len, pitch)); + } + else + { + return MF_E_UNSUPPORTED_FORMAT; + } + + return S_OK; +} + +////////////////////////////////////////////////// +// private + +HRESULT SimpleFrameGenerator::_CreateRGB32Frame( + _Inout_updates_bytes_(len) BYTE* pBuf, + _In_ DWORD len, + _In_ LONG pitch, + _In_ DWORD width, + _In_ DWORD height, + _In_ ULONG rgbMask ) +{ + RETURN_HR_IF_NULL(E_INVALIDARG, pBuf); + + LONGLONG curSysTimeInS = MFGetSystemTime() / (MFTIME)10000000; + int offset = curSysTimeInS % height; + + for (unsigned int r = 0; r < height; r++) + { + uint32_t* p = (uint32_t*)(pBuf + (r * pitch)); + for (unsigned int c = 0; c < width; c++) + { + BYTE gray = (BYTE)r + offset; + *p = ((uint32_t)gray << 16 | (uint32_t)gray << 8 | (uint32_t)gray) & rgbMask; + p++; + } + } + + return S_OK; +} + +////////////////////////////////////////////////// +// pixelFormatConverter + +void SimpleFrameGenerator::RGB24ToYUY2(int R, int G, int B, BYTE* pY, BYTE* pU, BYTE* pV) +{ + *pY = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; + *pU = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128; + *pV = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128; +} + +void SimpleFrameGenerator::RGB24ToY(int R, int G, int B, BYTE* pY) +{ + *pY = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; +} + +void SimpleFrameGenerator::RGB32ToNV12(BYTE RGB1[8], BYTE RGB2[8], BYTE* pY1, BYTE* pY2, BYTE* pUV) +{ + RGB24ToYUY2(RGB1[2], RGB1[1], RGB1[0], pY1, pUV, pUV + 1); + RGB24ToY(RGB1[6], RGB1[5], RGB1[4], pY1 + 1); + RGB24ToYUY2(RGB2[2], RGB2[1], RGB2[0], pY2, pUV, pUV + 1); + RGB24ToY(RGB2[6], RGB2[5], RGB2[4], pY2 + 1); +}; + +////////////////////////////////////////////////// +// FrameFormatConverter + +HRESULT SimpleFrameGenerator::RGB32ToNV12Frame(_Inout_updates_bytes_(len) BYTE* pbBuff, ULONG cbBuff, long stride, UINT width, UINT height, BYTE* pbBuffOut, ULONG cbBuffOut, long strideOut) +{ + do + { + RETURN_HR_IF(E_UNEXPECTED, width * 4 * height > cbBuff); + RETURN_HR_IF(E_UNEXPECTED, width * 1.5 * height > cbBuffOut); + RETURN_HR_IF_NULL(E_INVALIDARG, pbBuff); + + RETURN_HR_IF_NULL(E_INVALIDARG, pbBuffOut); + for (DWORD h = 0; h < height - 1; h += 2) + { + BYTE* pRGB1 = h * stride + pbBuff; + BYTE* pRGB2 = (h + 1) * stride + pbBuff; + BYTE* pY1 = h * strideOut + pbBuffOut; + BYTE* pY2 = (h + 1) * strideOut + pbBuffOut; + BYTE* pUV = (h / 2 + height) * strideOut + pbBuffOut; + + for (DWORD w = 0; w < width; w += 2) + { + RGB32ToNV12(pRGB1, pRGB2, pY1, pY2, pUV); + pRGB1 += 8; + pRGB2 += 8; + pY1 += 2; + pY2 += 2; + pUV += 2; + } + } + } while (FALSE); + + return S_OK; +} |
