Blackmagic DirectShow帧率 - 为什么我没有获得捕捉设备能够使用的所有视频模式?

时间:2015-03-13 13:36:20

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

我最近开始尝试使用BlackMagic SDK的DirectShow示例。 我做了我的第一个应用程序但是在阅读卡的可用视频模式(DeckLink Studio 4K)时我遇到了一些奇怪的行为。 旁注:Windows 7 Prof.&amp ;; 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;
}

我当然尝试改变这个: “if((frameRate&lt; 25)||(frameRate&gt; = 50.0))”

要 “if((frameRate&lt; 30)||(frameRate&gt; = 50.0))”

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

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

提前致谢(对不起任何拼写错误 - 来自德国), 马可

1 个答案:

答案 0 :(得分:2)

Blackmagic提供SDK作为主要API,然后他们的DirectShow过滤器构建在此SDK之上。也就是说,DirectShow过滤器提供了SDK功能的一个子集,尤其是您看到隔行扫描/渐进式媒体类型重叠的问题(他们的过滤器在提供具有真正隔行扫描媒体类型的视频源方面不进行隔行捕获或者通过字段),你基本上只限于过滤器提供的内容。