首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >媒体基础onReadSample返回样本的错误大小

媒体基础onReadSample返回样本的错误大小
EN

Stack Overflow用户
提问于 2013-11-19 13:11:24
回答 2查看 2K关注 0票数 3

我正在将捕获库从DirectShow翻译到MediaFoundation。捕获库似乎运行得很好,但我在运行Windows 8 32位的平板电脑上安装了集成摄像头,我面临着一个问题。

当枚举捕获格式(如媒体基金会文件中所解释的)时,我得到了以下支持的摄像机格式:

  • 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处的捕获格式,如示例所述:

代码语言:javascript
复制
hr = pHandler->SetCurrentMediaType(pType);      

此函数执行时没有错误。因此,应将照相机配置为以分辨率为640*480的YUY2捕获。

onReadSample回调中,我应该接收一个带有大小缓冲区的示例:

代码语言:javascript
复制
640 * 480 * sizeof(unsigned char) * 2 =  614400 //YUY2 is encoded on 2 bytes

但是,我得到了一个缓冲区大小为169344的样本。下面是回调函数的一部分。

代码语言:javascript
复制
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码的样品?

提前感谢

谢谢你的回答。

我检查了媒体类型的MF_MT_INTERLACE_MODE值,显示视频流包含累进帧。MF_MT_INTERLACE_MODE的值返回MFVideoInterlace_Progressive。

代码语言:javascript
复制
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的值,以查看示例是否是隔行的,并且该示例似乎是交错的。

代码语言:javascript
复制
if (pSample && m_bCapture)
{
    //check if interlaced 
    UINT32 isSampleInterlaced = 0;
    pSample->GetUINT32(MFSampleExtension_Interlaced, &isSampleInterlaced);
    if(isSampleInterlaced)
    {
        //enters here
    }

如何可能流是渐进的,并且样本是交错的?我还在MF_MT_INTERLACE_MODE回调中双重检查了onReadSample的值,它仍然给出了MFT_INPUT_STREAM_WHOLE_SAMPLES值。

关于您的第一个建议,我没有办法在输入流中强制使用标志MFT_INPUT_STREAM_WHOLE_SAMPLES。

提前感谢

我仍然面临这个问题,我现在正在调查不同的溪流。

根据文档,每个媒体源都提供了一个表示描述符,我们可以从中获得可用的流。要获得演示描述符,我们必须调用:

代码语言:javascript
复制
HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);

然后使用IMFPresentationDescriptor::GetStreamDescriptorCount函数请求可用的流:

代码语言:javascript
复制
DWORD nbrStream;
pPD->GetStreamDescriptorCount(&nbrStream);

当我在运行windows 8的宏碁平板电脑上的正面摄像头上请求这个信息时,我发现有三个流可用。我在这些流上循环,请求它们的MediaTypeHandler并检查MajorType。这三种流的主要类型是: MFMediaType_Video,所以所有的流都是视频流。当列出不同流上可用的媒体类型时,我发现所有流都支持640x480的捕获。(一些流具有更多可用媒体类型)。

我测试了选择每个不同的流和适当的格式类型(框架没有返回任何错误),但是我仍然没有收到回调函数中的正确示例.

对这个问题的进展有什么建议吗?

最后发现了问题:我必须使用SourceReader->SetCurrentMediaType(.)直接在源读取器上设置媒体类型。这招成功了!

谢谢你的帮忙!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-29 11:15:59

最后发现了问题:我必须使用SourceReader->SetCurrentMediaType(.)直接在源读取器上设置媒体类型。这招成功了!

谢谢你的帮忙!

票数 1
EN

Stack Overflow用户

发布于 2013-11-19 13:46:27

在不知道输入媒体类型描述符是什么的情况下,我们基本上只能推测,但最有可能的答案是,即使没有在输入流上设置MFT_INPUT_STREAM_WHOLE_SAMPLES,您也可以处理该流。

下一个最可能的原因是隔行,在这种情况下,每个帧都是完整的,但不是完全的分辨率,这是您假设的。无论如何,您应该在接受整个媒体类型描述符之前验证它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20072475

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档