Blackmagic DirectShow Framerate - 为什么我没有获得我的捕获设备支持的所有视频模式?
Blackmagic DirectShow Framerate - Why am I not getting all of the video modes that my capture device is capable of?
我最近开始尝试使用 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;
}
现在我当然试着改变这个:
"if ((frameRate < 25) || (frameRate >= 50.0))"
到
"if ((frameRate < 30) || (frameRate >= 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 功能的一个子集,这就是您特别看到 interlaced/progressive 媒体类型重叠问题的地方(它们的过滤器在交付具有真正交错媒体类型的视频源方面不进行交错捕获,或按字段),您基本上只能使用过滤器提供的内容。
我最近开始尝试使用 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;
}
现在我当然试着改变这个: "if ((frameRate < 25) || (frameRate >= 50.0))"
到 "if ((frameRate < 30) || (frameRate >= 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 功能的一个子集,这就是您特别看到 interlaced/progressive 媒体类型重叠问题的地方(它们的过滤器在交付具有真正交错媒体类型的视频源方面不进行交错捕获,或按字段),您基本上只能使用过滤器提供的内容。