我最近开始尝试使用BlackMagic SDK的DirectShow示例。 我做了我的第一个应用程序,但在阅读卡的可用视频模式(DeckLink Studio 4K)时遇到了一些奇怪的行为。 旁注:同样的行为发生在Windows 7教授& HP x64和Win 8.1 Pro x64。Blackmagic DirectShow Framerate - 为什么我没有获取我的拍摄设备所能支持的所有视频模式?
我的问题是,我没有得到像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)| |(frameRate> = 50.0))“
但是,只是将1080 50i/59,94i/60i重命名为25p/29.97p/30p。 我不给我使用30p的能力,它只是改名为30p,但仍然捕获60i。
也许有人更有经验可以找出问题。我认为这与DirectShow interpresing有关,即59.94i作为29.97的帧率,因此它不能填充该帧率两次。
在此先感谢(和抱歉任何拼错 - >来自德国), 马尔科
感谢您的澄清,我会使用API,但是我发现它确实很难(特别是编程技能有限)来构建一个简单的软件,允许记录到文件并截取屏幕截图。在这种情况下,DirectShow Capture/record样例非常棒。 – 2015-03-14 18:23:44
是否有任何使用内置录像机的“本机”API的示例。 我想要一个全屏应用程序(Media Express不支持预览窗口的全屏显示)和记录器和屏幕截图功能。 截图不会是问题,因为我可以实现整个屏幕的简单捕获 – 2015-03-14 21:52:53
有问题的部分是体面的视频编码器(通常是H.264编码器,反过来) - 它们通常不是免费的,所以它们不可用的盒子。通常需要第三方视频编码器或使用Windows Media或M-JPEG编码器。那么选择编码器就意味着容器(文件)格式。我看到你正在使用股票视频过滤器,因为它很容易使用。我建议[WM ASF Writer](https://msdn.microsoft.com/en-us/library/windows/desktop/dd318239%28)过滤器作为最容易记录的文件,尽管它需要一些棘手的设置。 – 2015-03-15 18:21:25