我正在将一个捕获库从DirectShow转换到MediaFoundation。这个捕获库似乎工作得很好,但我在运行Windows 8 32位平板电脑上的集成摄像头时遇到了问题。
当枚举捕获格式(如Media Foundation documentation所述)时,我得到了以下支持的相机格式:
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的格式,就像示例中所描述的一样:
这个函数执行时没有错误。因此,相机应该被配置为以640x480的分辨率捕获YUY2图像。
在onReadSample回调中,我应该收到一个带有指定大小缓冲区的样本。
任何建议为什么我会得到一个大小为169344的样本?
提前致谢。
所以视频流不是交错的。我在onReadSample中再次检查了MFSampleExtension_Interlaced的值,以确定样本是否交错,结果发现样本是交错的。
如何在流是渐进式的情况下,样本还是交错的呢?我在onReadSample回调中再次检查了MF_MT_INTERLACE_MODE的值,它仍然给出了MFT_INPUT_STREAM_WHOLE_SAMPLES的值。
关于您的第一个建议,我不想强制将MFT_INPUT_STREAM_WHOLE_SAMPLES标志应用于输入流。
提前感谢。
我仍然面临这个问题,现在我正在调查不同的可用流。
根据文档,每个媒体源都提供一个演示描述符,我们可以从中获取可用的流。要获取演示描述符,我们必须调用:
当我在运行Windows 8的ACER平板电脑上请求前置网络摄像头信息时,我发现有三个流可用。 我遍历了这些流,请求它们的MediaTypeHandler并检查MajorType。 这三个流的主要类型为MFMediaType_Video,因此所有流都是视频流。 在列出不同流可用的媒体类型时,我发现所有流都支持以640x480进行捕获。(某些流具有更多的可用媒体类型)。
我尝试选择每个不同的流和适当的格式类型(框架没有返回任何错误),但我仍然无法在回调函数中收到正确的样本...
有什么建议可以解决这个问题吗?
最终找到了问题所在:我需要直接在源读取器上设置媒体类型,使用SourceReader->SetCurrentMediaType(..)。这样就解决了!感谢您的帮助!
当枚举捕获格式(如Media Foundation documentation所述)时,我得到了以下支持的相机格式:
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);
这个函数执行时没有错误。因此,相机应该被配置为以640x480的分辨率捕获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的值返回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(..)。这样就解决了!感谢您的帮助!