Media Foundation onReadSample返回的样本大小错误
Media Foundation onReadSample wrong size of returned sample
我正在将捕获库从DirectShow转换为MediaFoundation。捕获库似乎运行得很好,但我在运行Windows 8 32位的平板电脑上遇到了集成网络摄像头的问题。
在枚举捕获格式时(如Media Foundation文档中所述),我得到了以下支持的相机格式:
- 0:MFVideoFormat_NV12,分辨率:448x252,帧速率:30000x1001
- 1:MFVideoFormat_YUY2,分辨率:448x252,帧速率:30000x1001
- 2:MFVideoFormat_NV12,分辨率:640x360,帧速率:30000x1001
- 3:MFVideoFormat_YUY2,分辨率:640x360,帧速率:30000x1001
- 4:MFVideoFormat_NV12,分辨率:640x480,帧速率:30000x1001
- 5:MFVideoFormat_YUY2,分辨率:640x480,帧速率:30000x1001
然后,我使用以下函数设置捕获格式,在本例中为索引5处的捕获格式,如示例中所述:
hr = pHandler->SetCurrentMediaType(pType);
此函数执行时没有出现错误。因此,相机应配置为以分辨率为640*480的YUY2进行拍摄。
在onReadSample回调中,我应该收到一个缓冲区大小为的样本
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的值返回MFVideoInterrace_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(..)直接在源阅读器上设置媒体类型。这就成功了!
谢谢你的帮助!
在不知道输入媒体类型描述符是什么的情况下,我们在很大程度上只能推测,但最有可能的答案是,即使输入流上没有设置MFT_INPUT_STREAM_WHOLE_SAMPLES
,您也可以处理流。
下一个最可能的原因是交错,在这种情况下,每一帧都是完整的,但不是你所假设的完全分辨率。无论如何,在接受ENTIRE媒体类型描述符之前,您应该验证它。
终于发现了问题:我必须使用SourceReader->SetCurrentMediaType(..)直接在源读取器上设置媒体类型。这就成功了!
谢谢你的帮助!
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- 为什么我在编译 OpenVino 样本时出现此错误
- OPENCV- HYBRIDTRACKINGSPAMPE.CPP样本上的错误
- 错误c2244 dlib贝叶斯网络样本代码
- Media Foundation onReadSample返回的样本大小错误
- SVM训练错误(样本类型的断言失败)
- 链接OpenCV gpu::立体声样本错误
- DirectShow的SampleGrabber检索错误的样本
- Mergevec.obj:10个未解决的链接错误(用于haartraining的OpenCV样本收集)
- 如何修复编译官方样本时不使用bjam的分段错误
- OpenCV用图片样本训练SVM错误