65.9K
CodeProject 正在变化。 阅读更多。
Home

DirectShow - 使用 IKsPropertySet 进行精细电视调谐。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (18投票s)

2004 年 8 月 21 日

3分钟阅读

viewsIcon

214145

如何在 DirectShow 中进行精细电视调谐 / 如何设置电视调谐器设备的自定义视频频率?

引言

如果您正在使用 DirectShow 为您的调谐器设备开发电视调谐器应用程序,那么您肯定会寻找一些可以执行精细电视调谐(即,您希望手动设置视频频率以在特定电视频道上获得精确的视频信号)的函数,但不幸的是,在标准的 DirectShow 电视调谐接口 IAMTunerIAMTVTuner 中没有这样的函数。

DirectShow 电视调谐架构基于预定义的频率表,并且电视调谐器过滤器(kstvtune.ax)具有内部频率表列表。每个频率表包含一个频率列表,对应于给定国家/地区的广播或有线频率。因此,当您使用 IAMTuner 接口时,它会根据所选国家/地区从内部频率表中获取频道频率值,并调谐电视频道。

由于 IAMTuner 接口不允许您手动修改特定频道的频率值,因此您无法在预览时进行精细调谐。但是,IAMTVTuner 接口中有一个 AutoTune 函数可以帮助您进行精细调谐,但这也不会让您在动态手动微调或设置自定义视频频率方面有任何控制权。

但是以下代码将向您描述使用 IKsPropertySet 进行动态精细调谐的完整细节。我撰写这篇文章只是为了帮助那些真正想获得有关此主题的一些线索的人,因为我知道在这个主题上获得帮助是多么困难。甚至,您都不会在整个 DirectShow 文档中找到任何可以帮助您的函数。

在编写此代码时,我假设读者对 DirectShow 视频捕获有很好的了解,并了解 DirectShow 图构建技术、过滤器和电视调谐器图的详细信息。我希望 DirectShow 的家伙在阅读这篇文章后会很高兴。

这是我在 Code Project 上的第一篇文章,因此你们中的一些人可能会觉得难以阅读 ;)。

// It is assumed that you have constructed the complete TV tuner Graph 
// of your Device.And will use this function to set custom frequencies 
// or to fine tune a tuned TV channel.Please also make sure to set the 
// appropriate Video standard and contry code before calling this function.

#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;  

    // Query the IKsPropertySet on your Device TV Tuner Filter.
    // m_pTvtuner is IBaseFilter Pointer of your TV Tuner Filter.   

    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; 

    // Check either the Property is supported or not by the Tuner drivers 

    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;

    // Here the real magic starts

    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(Win32® 驱动程序模型内核流式传输)架构的一部分,允许驱动程序提供可以在没有 API 扩展的情况下使用的扩展功能。

此代码执行的基本 3 个步骤是..

  1. 检查调谐器驱动程序对 IKsPropertySet 的支持。
  2. 检查调谐器驱动程序上的 PROPSETID_TUNER 属性。
  3. 以 Hz 为单位设置调谐器上用户定义的视频频率。

Using the Code

SetFrequency 函数可以以多种方式使用,例如,精细电视调谐、手动电视调谐、新电视频道调谐等。

  1. 调谐电视频道的精细调谐。
    • 调用 IAMTuner::put_Channel 以设置所需的电视频道。
    • 调用 IAMTVTuner::get_VideoFrequency 以获取当前的视频频率。
    • 通过在原始频道频率中添加所需的 +/- 频率值来调用 SetFrequency,并执行该操作,直到您在该频道上找到最佳视频质量。
  2. 手动电视调谐。
    • 使用您所需的 Hz 频率值调用 SetFrequency
      HRESULT hr= SetFrequency( 67250000 )
© . All rights reserved.