我正在努力将捕获库从DirectShow转换为MediaFoundation。捕获库似乎运行良好但我在运行Windows 8 32位的平板电脑上遇到集成网络摄像头的问题。
在枚举捕获格式时(如Media Foundation documentation中所述),我获得了以下支持的相机格式:
然后我使用以下函数设置捕获格式,在本例中是索引5处的格式,如示例中所述:
hr = pHandler->SetCurrentMediaType(pType);
执行此功能时没有错误。因此,摄像机应配置为在YUY2中捕获,分辨率为640 * 480。
在onReadSample callback中,我应该收到一个带有大小缓冲区的样本:
640 * 480 * sizeof(unsigned char) * 2 = 614400 //YUY2 is encoded on 2 bytes
但是,我得到了一个大小为169344的缓冲区示例。下面是回调函数的一部分。
HRESULT SourceReader::OnReadSample(
HRESULT hrStatus,
DWORD dwStreamIndex,
DWORD dwStreamFlags,
LONGLONG llTimeStamp,
IMFSample *pSample // Can be NULL
)
{
EnterCriticalSection(&m_critsec);
if (pSample)
{
DWORD expectedBufferSize = 640*480*1*2; // = 614400 (hard code for the example)
IMFMediaBuffer* buffer = NULL;
hr = pSample->ConvertToContiguousBuffer(&buffer);
if (FAILED(hr))
{
//...
goto done;
}
DWORD byteLength = 0;
BYTE* pixels = NULL;
hr = buffer->Lock(&pixels, NULL, &byteLength);
//byteLength is 169344 instead of 614400
if (byteLength > 0 && byteLength == expectedBufferSize)
{
//do someting with the image, but never comes here because byteLength is wrong
}
//...
为什么我得到大小为169344的样本?
提前致谢
感谢Mgetz的回答。
我检查了媒体类型的MF_MT_INTERLACE_MODE的值,看来视频流包含渐进帧。 MF_MT_INTERLACE_MODE的值返回MFVideoInterlace_Progressive。
hr = pHandler->SetCurrentMediaType(m_pType);
if(FAILED(hr)){
//
}
else
{
//get info about interlacing
UINT32 interlaceFormat = MFVideoInterlace_Unknown;
m_pType->GetUINT32(MF_MT_INTERLACE_MODE, &interlaceFormat);
//...
因此视频流不是隔行扫描的。我在onReadSample中再次检查了MFSampleExtension_Interlaced的值,以查看样本是否是隔行扫描,并且看起来样本是隔行扫描的。
if (pSample && m_bCapture)
{
//check if interlaced
UINT32 isSampleInterlaced = 0;
pSample->GetUINT32(MFSampleExtension_Interlaced, &isSampleInterlaced);
if(isSampleInterlaced)
{
//enters here
}
流如何可能是渐进的并且样本是交错的?我也在onReadSample回调中仔细检查了MF_MT_INTERLACE_MODE的值,它仍然给出了值MFT_INPUT_STREAM_WHOLE_SAMPLES。
关于你的第一个建议,我没有办法强制输入流上的标志MFT_INPUT_STREAM_WHOLE_SAMPLES。
提前致谢
我仍然面临这个问题,现在我正在调查可用的不同流。
根据文档,每个媒体源都提供了一个表示描述符,我们可以从中获取可用的流。要获取表示描述符,我们必须调用:
HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
然后我使用IMFPresentationDescriptor :: GetStreamDescriptorCount函数请求可用的流:
DWORD nbrStream;
pPD->GetStreamDescriptorCount(&nbrStream);
在运行Windows 8的ACER平板电脑上的正面网络摄像头上请求此信息时,我得到了三个流可用。我循环遍历这些流,请求他们的MediaTypeHandler并检查MajorType。这三个流具有主要类型:MFMediaType_Video,因此所有流都是视频流。列出不同流上可用的媒体类型时,我得到所有流支持640x480的捕获。 (某些流有更多可用的媒体类型)。
我测试过选择每个不同的流和适当的格式类型(框架没有返回任何错误),但我仍然没有在回调函数中收到正确的样本......
有关此问题的进展建议吗?
终于找到了问题:我必须使用SourceReader-> SetCurrentMediaType(..)直接在源阅读器上设置媒体类型。这就行了!
感谢您的帮助!
答案 0 :(得分:1)
在不知道输入媒体类型描述符是什么的情况下,我们很大程度上只能推测,但最可能的答案就是你说你可以处理流,即使输入流上没有设置MFT_INPUT_STREAM_WHOLE_SAMPLES
。
下一个最可能的原因是interlacing,在这种情况下,每个帧都是完整的,但不是你假设的全分辨率。无论您在接受之前验证整个媒体类型描述符。
答案 1 :(得分:1)
终于找到了问题:我必须使用SourceReader-> SetCurrentMediaType(..)直接在源阅读器上设置媒体类型。这就行了!
感谢您的帮助!