Windows Media Foundation读取摄像头数据

发布时间 2023-11-14 16:47:35作者: microsun

可以读取数据,设置分辨率

如果我们期望的数据格式与摄像头的数据格式不同,就需要设置 MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING 

否则不需要

以下是代码:
int ReadCameraData(UINT32 width, UINT32 height)
{
IMFAttributes* attributes = NULL;
IMFActivate** devices = NULL;
IMFActivate* deviceUsing = NULL;
IMFMediaType* mediaType = NULL;
IMFAttributes* attr = nullptr;
IMFMediaSource* deviceSource;
IMFSourceReader* reader;
UINT32 count = 0;

auto hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
goto failed_stop;
}
hr = MFCreateAttributes(&attributes, 1);
if (FAILED(hr)) {
goto failed_stop;
}
hr = attributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if (FAILED(hr)) {
goto failed_stop;
}
hr = MFEnumDeviceSources(attributes, &devices, &count);
if (FAILED(hr)) {
goto failed_stop;
}
if (count < 1) {
hr = -1;
goto failed_stop;
}
deviceUsing = devices[0];

hr = MFCreateDeviceSource(deviceUsing, &deviceSource);
if (FAILED(hr)) {
goto failed_stop;
}
hr = MFCreateAttributes(&attr, 1); {
if (FAILED(hr)) {
attr = nullptr;
}
else {
hr = attr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, 1);
}
}
hr = MFCreateSourceReaderFromMediaSource(deviceSource, attr, &reader);
if (FAILED(hr)) {
goto failed_stop;
}
hr = reader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &mediaType);
if (FAILED(hr)) {
}
hr = MFSetAttributeSize(mediaType, MF_MT_FRAME_SIZE, width, height);
hr = mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2);

PROPVARIANT var;
hr = mediaType->GetItem(MF_MT_FRAME_RATE_RANGE_MAX, &var);
if (!FAILED(hr)) {
hr = mediaType->SetItem(MF_MT_FRAME_RATE, var);
}
hr = reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, mediaType);
if (FAILED(hr)) {
goto failed_stop;
}
while (1) {
DWORD index = 0;
DWORD flag = 0;
IMFSample* sample;
LONGLONG timestamp;

hr = reader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &index, &flag, &timestamp, &sample);
if (sample) {
IMFMediaBuffer* buffer = NULL;
sample->ConvertToContiguousBuffer(&buffer);
if (buffer) {
BYTE* channelBuf;
DWORD channelLen;
buffer->Lock(&channelBuf, NULL, &channelLen);

buffer->Release();
}
sample->Release();
}
}

failed_stop:
if (attr)
attr->Release();
for (UINT32 i = 0; i < count; i++) {
devices[i]->Release();
}
mediaType->Release();
return hr;
}