介绍:
如果你在用DirectShow开发TV调试程序,你肯定希望开发一些可以进行TV调谐的功能(你也许希望设置指定频道的信号的视频的频率),但不幸的是,DirectShow的IAMTuner 和 IAMTVTuner里没有固定的函数完成这项功能。
DirectShow 的电视调协架构是基于预先频率定义表,电视调协过滤器有一个内部的频率表。每个频率表包含一个频率列表,并直接和有线或无线传输区域中的信号关联。所以当你使用IAMTuner时,它将从内部频率表中获得所选地区的频道的频率。
因为IAMTuner将不允许你修改指定频道的频率值。你不能很好的调协一个频道。但在IAMTVTuner里有一个AutoTune函数,这将帮助你很好的调协频道,但在飞行或设置自定义频率时这也不能很好的调协。
以下代码将介绍一种在飞行时使用IKsPropertySet进行调协的方式。我是要帮助那些想在电视调协方面能找到一些方法的人,因为我知道这并不容易。在DirectShow你甚至找不到一个简单的函数来完成这些。
当编写以下代码时,我假定你已经精通了DirectShow视频扑捉和用DirectShow进行视频成象的技术,以及过滤和电视图象的调协。我希望对DirectShow熟悉的网友能对此感兴趣。
这是我关于代码的第一篇文章,所以有些部分会很难弄懂:)。
//假定你已经建立了完整的电视调协成象设备。你将使用该函数设置自定义的频率或很好的
//调协电视频道。请确认设置了正确的电视标准和地区编码。
#define INSTANCEDATA_OF_PROPERTY_PTR(x) ((PKSPROPERTY((x))) + 1)
#define INSTANCEDATA_OF_PROPERTY_SIZE(x) (sizeof((x)) - sizeof(KSPROPERTY))
HRESULT SetFrequency(long Freq)
{
HRESULT hr;
DWORD dwSupported=0;
//在电视调协过滤器上查询IKsPropertySet
//m_pTvtuner是一个IBaseFilter的指针
CComPtr m_pKSProp;
hr = m_pTvtuner->QueryInterface(IID_IKsPropertySet, (void**)&m_pKSProp);
if (FAILED(hr))
return E_FAIL;
KSPROPERTY_TUNER_MODE_CAPS_S ModeCaps;
KSPROPERTY_TUNER_FREQUENCY_S Frequency;
memset(&ModeCaps,0,sizeof(KSPROPERTY_TUNER_MODE_CAPS_S));
memset(&Frequency,0,sizeof(KSPROPERTY_TUNER_FREQUENCY_S));
ModeCaps.Mode = AMTUNER_MODE_TV;
//确认参数是否可以被调协设备接受
hr = m_pKSProp->QuerySupported(PROPSETID_TUNER,
KSPROPERTY_TUNER_MODE_CAPS,&dwSupported);
if(SUCCEEDED(hr) && dwSupported&KSPROPERTY_SUPPORT_GET)
{
DWORD cbBytes=0;
hr = m_pKSProp->Get(PROPSETID_TUNER,KSPROPERTY_TUNER_MODE_CAPS,
INSTANCEDATA_OF_PROPERTY_PTR(&ModeCaps),
INSTANCEDATA_OF_PROPERTY_SIZE(ModeCaps),
&ModeCaps,
sizeof(ModeCaps),
&cbBytes);
}
else
return E_FAIL;
Frequency.Frequency=Freq;
if(ModeCaps.Strategy==KS_TUNER_STRATEGY_DRIVER_TUNES)
Frequency.TuningFlags=KS_TUNER_TUNING_FINE;
else
Frequency.TuningFlags=KS_TUNER_TUNING_EXACT;
//这里是主要功能部分
if(Freq>=ModeCaps.MinFrequency && Freq<=ModeCaps.MaxFrequency)
{
hr = m_pKSProp->Set(PROPSETID_TUNER,
KSPROPERTY_TUNER_FREQUENCY,
INSTANCEDATA_OF_PROPERTY_PTR(&Frequency),
INSTANCEDATA_OF_PROPERTY_SIZE(Frequency),
&Frequency,
sizeof(Frequency));
if(FAILED(hr))
return E_FAIL;
}
else
return E_FAIL;
return S_OK;
}
代码解释:
SetFrequency函数为调协设备设置视频频率,Freq参数是要设置的频率单位HZ。代码使用IKsPropertySet来进行操作。IKsPropertySet是WDM KS架构的组成部分,该架构允许设备提供扩展功能何以在没有API扩展的情况下使用。
代码进行基本3个步奏:
在调协驱动里检测IKsPropertySet的支持。
在调协驱动里检测PROPSETID_TUNER 参数。
设置用户定义的视频频率单位HZ。
使用该代码:
SetFrequency函数可以在几种方式中使用,比如,电视调协,手动调协,定义频道等。
使用如下:
调用IAMTuner::put_Channel设置想要的电视频道。
调用IAMTVTuner::get_VideoFrequency获得当前的视频。
调用SetFrequency增加频率或减少频率,直到获得最佳视频效果。