c++ - Blackmagic DirectShow Framerate - 为什么我没有获得我的捕获设备支持的所有视频模式?

标签 c++ visual-studio video directshow video-capture

我最近开始尝试使用 BlackMagic SDK 的 DirectShow 示例。 我制作了第一个应用程序,但在读取卡(DeckLink Studio 4K)的可用视频模式时遇到了一些奇怪的行为。 旁注:相同的行为发生在 Windows 7 Prof. & HP x64 和 Win 8.1 Pro x64 上。

我的问题是,我无法获得 25p、29.97p 和 30p 等视频模式。 尽管捕获设备具备这些功能,但它们与 Blackmagic Media Express 的配合更加完美。

HRESULT CDecklinkCaptureDlg::PopulateVideoControl()
{
HRESULT hr = S_OK;
if (m_pVideoCapture)
{
    int count = m_videoFormatCtrl.GetCount();
    if (count)
    {
        for (int item=0; item<count; ++item)
        {
            DeleteMediaType((AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(item));
        }
        m_videoFormatCtrl.ResetContent();
    }

    CComPtr<IAMStreamConfig> pISC = NULL;
    hr = CDSUtils::FindPinInterface(m_pVideoCapture, &MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast<void**>(&pISC));
    if (SUCCEEDED(hr))
    {
        int count, size;
        hr = pISC->GetNumberOfCapabilities(&count, &size);
        if (SUCCEEDED(hr))
        {
            if (sizeof(VIDEO_STREAM_CONFIG_CAPS) == size)
            {
                AM_MEDIA_TYPE* pmt = NULL;
                VIDEO_STREAM_CONFIG_CAPS vscc;
                VIDEOINFOHEADER* pvih = NULL;

                for (int index=0; index<count; ++index)
                {
                    hr = pISC->GetStreamCaps(index, &pmt, reinterpret_cast<BYTE*>(&vscc));
                    if (SUCCEEDED(hr))
                    {
                        TCHAR       buffer[128];
                        float       frameRate;
                        char*       pixelFormatString;

                        ZeroMemory(buffer, sizeof(buffer));

                        pvih = (VIDEOINFOHEADER*)pmt->pbFormat;
                        //
                        if (pvih->bmiHeader.biBitCount == 16)
                            pixelFormatString = TEXT("8 bit 4:2:2 YUV");
                        else if (pvih->bmiHeader.biBitCount == 20)
                            pixelFormatString = TEXT("10 bit 4:2:2 YUV");
                        else if (pvih->bmiHeader.biBitCount == 30)
                            pixelFormatString = TEXT("10 bit 4:4:4 RGB");
                        else
                            pixelFormatString = TEXT("");           


                        if (486 == pvih->bmiHeader.biHeight)
                        {
                            if (417083 == pvih->AvgTimePerFrame)
                            {
                                StringCbPrintf(buffer, sizeof(buffer), TEXT("NTSC - %s (3:2 pulldown removal)"), pixelFormatString);
                            }
                            else
                            {
                                StringCbPrintf(buffer, sizeof(buffer), TEXT("NTSC - %s"), pixelFormatString);
                            }
                        }
                        else if (576 == pvih->bmiHeader.biHeight)
                        {
                            StringCbPrintf(buffer, sizeof(buffer), TEXT("PAL - %s"), pixelFormatString);
                        }
                        else
                        {
                            frameRate = (float)UNITS / pvih->AvgTimePerFrame;

                            if (720 == pvih->bmiHeader.biHeight)
                            {
                                // 720p
                                if ((frameRate - (int)frameRate) > 0.01)
                                {
                                    StringCbPrintf(buffer, sizeof(buffer), TEXT("HD 720p %.2f - %s"), frameRate, pixelFormatString);
                                }
                                else
                                {
                                    StringCbPrintf(buffer, sizeof(buffer), TEXT("HD 720p %.0f - %s"), frameRate, pixelFormatString);
                                }
                            }
                            else if (1080 == pvih->bmiHeader.biHeight)
                            {
                                if ((frameRate < 25) || (frameRate >= 50.0))        // 1080p23, 1080p24, 1080p50, 1080p5994, 1080p60
                                {
                                    // Progressive 1080
                                    if ((frameRate - (int)frameRate) > 0.01)
                                    {
                                        StringCbPrintf(buffer, sizeof(buffer), TEXT("HD 1080p %.2f - %s"), frameRate, pixelFormatString);
                                    }
                                    else
                                    {
                                        StringCbPrintf(buffer, sizeof(buffer), TEXT("HD 1080p %.0f - %s"), frameRate, pixelFormatString);
                                    }
                                }
                                else
                                {
                                    // Interlaced 1080
                                    if ((frameRate - (int)frameRate) > 0.01)
                                    {
                                        StringCbPrintf(buffer, sizeof(buffer), TEXT("HD 1080i %.2f - %s"), frameRate*2.0f, pixelFormatString);
                                    }
                                    else
                                    {
                                        StringCbPrintf(buffer, sizeof(buffer), TEXT("HD 1080i %.0f - %s"), frameRate*2.0f, pixelFormatString);
                                    }
                                }
                            }
                            else if (1556 == pvih->bmiHeader.biHeight)
                            {
                                if ((frameRate - (int)frameRate) > 0.01)
                                {
                                    StringCbPrintf(buffer, sizeof(buffer), TEXT("2K 1556p %.2f - %s"), frameRate, pixelFormatString);
                                }
                                else
                                {
                                    StringCbPrintf(buffer, sizeof(buffer), TEXT("2K 1556p %.0f - %s"), frameRate, pixelFormatString);
                                }
                            }
                        }

                        // If the display mode was recognized, add it to the listbox UI
                        if (buffer[0] != 0)
                        {
                            // add the item description to combo box
                            int n = m_videoFormatCtrl.AddString(buffer);
                            // store media type pointer in item's data section
                            m_videoFormatCtrl.SetItemData(n, (DWORD_PTR)pmt);

                            // set default format
                            if ((pvih->AvgTimePerFrame == m_vihDefault.AvgTimePerFrame) &&
                                (pvih->bmiHeader.biWidth == m_vihDefault.bmiHeader.biWidth) &&
                                (pvih->bmiHeader.biHeight == m_vihDefault.bmiHeader.biHeight) &&
                                (pvih->bmiHeader.biBitCount == m_vihDefault.bmiHeader.biBitCount))
                            {
                                m_videoFormatCtrl.SetCurSel(n);
                                pISC->SetFormat(pmt);
                            }
                        }
                        else
                        {
                            DeleteMediaType(pmt);
                        }
                    }
                }
            }
            else
            {
                m_videoFormatCtrl.AddString(TEXT("ERROR: Unable to retrieve video formats"));
            }
        }
    }

    // as the device is being changed, update the IDecklinkInputStatus interface
    {
        CAutoLock lock(&m_csInputStatusLock);   // prevent thread from using this interface while it is changed

        m_pIDecklinkStatus = m_pVideoCapture;
        if (m_pIDecklinkStatus)
        {
            m_pIDecklinkStatus->RegisterVideoStatusChangeEvent((unsigned long)m_hInputStatusChangeEvent);   
        }
    }
}
else
{
    hr = E_POINTER;
}

return hr;
}

现在我当然尝试改变这个: “如果((帧率 < 25)||(帧率 >= 50.0))”

到 “如果((帧率 < 30)||(帧率 >= 50.0))”

但这只是将 1080 50i/59,94i/60i 重命名为 25p/29.97p/30p。 我没有给我使用 30p 的能力,它只是重命名为 30p 但仍然捕获 60i。

也许更有经验的人可以找出问题所在。我认为它与 DirectShow 解释有关,即 59.94i 作为 29.97 的帧率,因此它不能填充该帧率两次。

提前致谢(对于任何拼写错误,我们深表歉意 -> 来自德国), 马可

最佳答案

Blackmagic 提供他们的 SDK 作为主要 API,然后他们的 DirectShow 过滤器构建在这个 SDK 之上。也就是说,DirectShow 过滤器提供了 SDK 功能的一个子集,这就是您特别看到隔行扫描/逐行媒体类型重叠问题的地方(它们的过滤器在交付具有真正隔行扫描媒体类型的视频源方面不进行隔行扫描捕获,或者按字段),您基本上只能使用过滤器提供的内容。

关于c++ - Blackmagic DirectShow Framerate - 为什么我没有获得我的捕获设备支持的所有视频模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29033641/

相关文章:

audio - 如何在gstreamer中混合音频和视频

具有父节点的二叉树的 C++ 复制构造函数

c++程序无法在另一台PC上运行并出现libgcc错误

.net - 为什么在建立与 SQL Server 的连接时会发生与网络相关或特定于实例的错误?

Jquery验证单击提交按钮两次ASP.Net core MVC项目

javascript - 视频无法在移动设备上自动播放

ios - Sinch SDK 视频通话本地 View 保持卡住至上次通话最后捕获的帧

c++ - 正则表达式匹配数字的重复模式,后跟任何类型的定界符?

c++ - 数组中元素的自定义排序

visual-studio - VS 2010 : How do I get "next tab", "prev tab"键盘快捷键有效吗?