NV12 至 RGB32,带Microsoft媒体基础
NV12 to RGB32 with Microsoft Media Foundation
我正在尝试通过媒体预览获得一些相机预览,我在YT上发现它正在工作。我已经枚举了我的设备。我可以通过相机进行预览,但我的数据格式是NV12。我需要 RGB32 格式的数据。这是包含有关设备信息的类。
class Media : public IMFSourceReaderCallback
{
CRITICAL_SECTION criticalSection;
long referenceCount;
WCHAR *wSymbolicLink;
UINT32 cchSymbolicLink;
IMFSourceReader* sourceReader;
public:
LONG stride;
int bytesPerPixel;
GUID videoFormat;
UINT height;
UINT width;
WCHAR deviceNameString[2048];
BYTE* rawData;
HRESULT CreateCaptureDevice();
HRESULT SetSourceReader(IMFActivate *device);
HRESULT IsMediaTypeSupported(IMFMediaType* type);
HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride);
HRESULT Close();
Media();
~Media();
// the class must implement the methods from IUnknown
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// the class must implement the methods from IMFSourceReaderCallback
STDMETHODIMP OnReadSample(HRESULT status, DWORD streamIndex, DWORD streamFlags, LONGLONG timeStamp, IMFSample *sample);
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *);
STDMETHODIMP OnFlush(DWORD);
};
这是创建设备的方法:
HRESULT Media::CreateCaptureDevice()
{
HRESULT hr = S_OK;
//this is important!!
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);//COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
UINT32 count = 0;
IMFAttributes *attributes = NULL;
IMFActivate **devices = NULL;
if (FAILED(hr)) { CLEAN_ATTRIBUTES() }
// Create an attribute store to specify enumeration parameters.
hr = MFCreateAttributes(&attributes, 1);
if (FAILED(hr)) { CLEAN_ATTRIBUTES() }
//The attribute to be requested is devices that can capture video
hr = attributes->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
);
if (FAILED(hr)) { CLEAN_ATTRIBUTES() }
//Enummerate the video capture devices
hr = MFEnumDeviceSources(attributes, &devices, &count);
if (FAILED(hr)) { CLEAN_ATTRIBUTES() }
//if there are any available devices
if (count > 0)
{
/*If you actually need to select one of the available devices
this is the place to do it. For this example the first device
is selected
*/
//Get a source reader from the first available device
SetSourceReader(devices[0]);
WCHAR *nameString = NULL;
// Get the human-friendly name of the device
UINT32 cchName;
hr = devices[0]->GetAllocatedString(
MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
&nameString, &cchName);
if (SUCCEEDED(hr))
{
//allocate a byte buffer for the raw pixel data
bytesPerPixel = abs(stride) / width;
rawData = new BYTE[width*height * bytesPerPixel];
wcscpy(deviceNameString,nameString);
}
CoTaskMemFree(nameString);
}
//clean
CLEAN_ATTRIBUTES()
}
这是设置设备的方法:
HRESULT Media::SetSourceReader(IMFActivate *device)
{
HRESULT hr = S_OK;
IMFMediaSource *source = NULL;
IMFAttributes *attributes = NULL;
IMFMediaType *mediaType = NULL;
EnterCriticalSection(&criticalSection);
hr = device->ActivateObject(__uuidof(IMFMediaSource), (void**)&source);
//get symbolic link for the device
if(SUCCEEDED(hr))
hr = device->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &wSymbolicLink, &cchSymbolicLink);
//Allocate attributes
if (SUCCEEDED(hr))
hr = MFCreateAttributes(&attributes, 2);
//get attributes
if (SUCCEEDED(hr))
hr = attributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, TRUE);
// Set the callback pointer.
if (SUCCEEDED(hr))
hr = attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK,this);
//Create the source reader
if (SUCCEEDED(hr))
hr = MFCreateSourceReaderFromMediaSource(source,attributes,&sourceReader);
// Try to find a suitable output type.
if (SUCCEEDED(hr))
{
for (DWORD i = 0; ; i++)
{
hr = sourceReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,i,&mediaType);
if (FAILED(hr)) { break; }
hr = IsMediaTypeSupported(mediaType);
if (FAILED(hr)) { break; }
//Get width and height
MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height);
if (mediaType)
{ mediaType->Release(); mediaType = NULL; }
if (SUCCEEDED(hr))// Found an output type.
break;
}
}
if (SUCCEEDED(hr))
{
// Ask for the first sample.
hr = sourceReader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL,NULL,NULL);
}
if (FAILED(hr))
{
if (source)
{
source->Shutdown();
}
Close();
}
if (source) { source->Release(); source = NULL; }
if (attributes) { attributes->Release(); attributes = NULL; }
if (mediaType) { mediaType->Release(); mediaType = NULL; }
LeaveCriticalSection(&criticalSection);
return hr;
}
视频处理器 MFT 可以处理颜色转换。 它的设置和使用相当简单,因为它是一个同步转换。 有关详细信息和示例,请参阅此链接。
通常,当 yuv (nv12( 到 rgb (rgb32( 时:
字节* p_rgb_Data = (((高度/2( + 高度( * 宽度( * 3;//无字母
编辑
我的回答不正确,您想要相机的 rgb 格式,对吧?
您必须从 SourceReader 枚举 MediaType:
enumerating_output_formats
HRESULT EnumerateTypesForStream(IMFSourceReader *pReader, DWORD wStreamIndex){
HRESULT hr = S_OK;
DWORD dwMediaTypeIndex = 0;
while (SUCCEEDED(hr))
{
IMFMediaType *pType = NULL;
hr = pReader->GetNativeMediaType(dwStreamIndex, dwMediaTypeIndex, &pType);
if (hr == MF_E_NO_MORE_TYPES)
{
hr = S_OK;
break;
}
else if (SUCCEEDED(hr))
{
// Examine the media type. (Not shown.)
pType->Release();
}
++dwMediaTypeIndex;
}
return hr;
}
当媒体类型为 RGB 时,设置媒体类型:
setting_output_formats
hr = pReader->SetCurrentMediaType(dwStreamIndex, pMediaType);
编辑。。。
是的,从 :
字节* p_rgb_Data = (((高度/2( + 高度( * 宽度( * 3;//无字母
-> 应该是字节* p_rgb_Size = (((高度/2( + 高度( * 宽度( * 3;//没有字母
我错过了转换。像这样:
BYTE GetR(const int bY, int const bU){
int iR = bY + (int)(1.402f * bU);
iR = iR > 255 ? 255 : iR < 0 ? 0 : iR;
return iR;
}
BYTE GetG(const int bY, const int bU, const int bV({
int iG = bY - (int)(0.344f * bV + 0.714f * bU);
iG = iG > 255 ? 255 : iG < 0 ? 0 : iG;
return iG;
}
BYTE GetB(const int bY, const int bV({
int iB = bY + (int)(1.772f * bV);
iB = iB > 255 ? 255 : iB < 0 ? 0 : iB;
return iB;
}
如果您想在NV12缓冲区和RGB缓冲区之间进行完整的转换,请询问。
相关文章:
- 当Microsoft文档仅包含 C# 示例时,如何查找 C++ 包含文件名
- 带有 CKKS 的 Microsoft 密封中的矢量点积
- 如何添加预防措施以绕过未注册Microsoft.ACE.OLEDB.12.0?
- 与其他编译器相比,相同的代码在工作室Microsoft提供不同的输出
- 使用 Outlook 2016 Microsoft Store 连接到 Outlook COM
- 如何在 SEAL 3.1 中使用 CRT 批处理技术Microsoft?
- 使用 CMake,Microsoft MPI 和 Visual Studio 2017 找不到 mpi.h
- 如何在视觉c ++项目中添加箭头键作为修饰键Microsoft
- 为什么Microsoft在新代码中使用结构而不是类?
- Microsoft C++ 用于图形 API 的 Rest SDK
- Microsoft ODBC 无法创建有效的句柄
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- 使用IMFSourceReader(Microsoft媒体基金会)进行音频流传输
- C++ VS 错误:<实验/文件系统>提供 std::experimental::文件系统的标头已被Microsoft弃用,将被删除
- 寻求提高Microsoft密封库计算效率的方法
- Microsoft Visual Studio 2019交叉编译CMake库 - 有效,但存在SEG错误
- Microsoft NTLM (v2) 中的时间戳使用
- C++正则表达式失败(GCC vs Microsoft 编译器)
- NV12 至 RGB32,带Microsoft媒体基础
- 媒体基金会Microsoft相当于Directshow的自定义视频过滤器吗?