使用交叉条

[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayerIMFMediaEngine音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

如果视频捕获卡具有多个物理输入,或者支持多个数据的硬件路径,则筛选器图可能包含模拟视频横线筛选器。 捕获图形生成器在需要时自动添加此筛选器;它将从捕获筛选器上游。 根据硬件的不同,筛选器图可能包含横线筛选器的多个实例。

横线筛选器公开 IAMCrossbar 接口,可用于将特定输入路由到特定输出。 例如,视频卡可能具有同轴连接器和 S-Video 输入。 这些将表示为横线筛选器上的输入引脚。 若要选择输入,请使用 IAMCrossbar::Route 方法将相应的输入引脚路由到横线的输出引脚。

若要在图形中查找横线筛选器,可以使用 ICaptureGraphBuilder2::FindInterface 方法搜索支持 IAMCrossbar 的筛选器。 例如,以下代码搜索两个横线:

// Search upstream for a crossbar.
IAMCrossbar *pXBar1 = NULL;
hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pSrc,
        IID_IAMCrossbar, (void**)&pXBar1);
if (SUCCEEDED(hr)) 
{
    // Found one crossbar. Get its IBaseFilter interface.
    IBaseFilter *pFilter = NULL;
    hr = pXBar1->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
    if (SUCCEEDED(hr)) 
    {
        // Search upstream for another crossbar.
        IAMCrossbar *pXBar2 = NULL;
        hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pFilter,
                 IID_IAMCrossbar, (void**)&pXBar2);
        pFilter->Release();

        if (SUCCEEDED(hr))
        {
            /* ... */
            pXBar2->Release();
        }
    }
    pXBar1->Release();
}

有关更通用的方法,请参阅 AmCap 示例中的 CCrossbar 类。

有了指向 IAMCrossbar 接口的指针后,可以获取有关横线筛选器的信息,包括每个引脚的物理类型,以及哪些输入引脚可以路由到哪个输出引脚的矩阵。

  • 若要确定引脚所对应的物理连接器的类型,请调用 IAMCrossbar::get_CrossbarPinInfo 方法。 方法返回 PhysicalConnectorType 枚举的成员。 例如,S-Video 引脚返回值PhysConn_Video_SVideo。

    get_CrossbarInfo 方法还指示两个引脚是否相互关联。 例如,视频调谐器引脚可能与音频调谐器引脚相关。 相关引脚具有相同的引脚方向,并且通常是卡上同一个物理插孔或连接器的一部分。

  • 若要确定是否可以将输入引脚路由到特定输出引脚,请调用 IAMCrossbar::CanRoute 方法。

  • 若要确定引脚之间的当前路由,请调用 IAMCrossbar::get_IsRoutedTo 方法。

上述方法均按索引号指定引脚,输出引脚和输入引脚均从零开始编制索引。 调用 IAMCrossbar::get_PinCounts 方法来查找筛选器上的引脚数。

例如,以下代码向控制台窗口显示有关横线筛选器的信息:

// Helper function to associate a name with the type.
const char * GetPhysicalPinName(long lType)
{
    switch (lType) 
    {
    case PhysConn_Video_Tuner:            return "Video Tuner";
    case PhysConn_Video_Composite:        return "Video Composite";
    case PhysConn_Video_SVideo:           return "S-Video";
    case PhysConn_Video_RGB:              return "Video RGB";
    case PhysConn_Video_YRYBY:            return "Video YRYBY";
    case PhysConn_Video_SerialDigital:    return "Video Serial Digital";
    case PhysConn_Video_ParallelDigital:  return "Video Parallel Digital"; 
    case PhysConn_Video_SCSI:             return "Video SCSI";
    case PhysConn_Video_AUX:              return "Video AUX";
    case PhysConn_Video_1394:             return "Video 1394";
    case PhysConn_Video_USB:              return "Video USB";
    case PhysConn_Video_VideoDecoder:     return "Video Decoder";
    case PhysConn_Video_VideoEncoder:     return "Video Encoder";
        
    case PhysConn_Audio_Tuner:            return "Audio Tuner";
    case PhysConn_Audio_Line:             return "Audio Line";
    case PhysConn_Audio_Mic:              return "Audio Microphone";
    case PhysConn_Audio_AESDigital:       return "Audio AES/EBU Digital";
    case PhysConn_Audio_SPDIFDigital:     return "Audio S/PDIF";
    case PhysConn_Audio_SCSI:             return "Audio SCSI";
    case PhysConn_Audio_AUX:              return "Audio AUX";
    case PhysConn_Audio_1394:             return "Audio 1394";
    case PhysConn_Audio_USB:              return "Audio USB";
    case PhysConn_Audio_AudioDecoder:     return "Audio Decoder";
        
    default:                              return "Unknown Type";
    }    
}

void DisplayCrossbarInfo(IAMCrossbar *pXBar)
{
    HRESULT hr;
    long cOutput = -1, cInput = -1;
    hr = pXBar->get_PinCounts(&cOutput, &cInput);

    for (long i = 0; i < cOutput; i++)
    {
        long lRelated = -1, lType = -1, lRouted = -1;

        hr = pXBar->get_CrossbarPinInfo(FALSE, i, &lRelated, &lType);
        hr = pXBar->get_IsRouted(i, &lRouted);

        printf("Output pin %d: %s\n", i, GetPhysicalPinName(lType));
        printf("\tRelated out: %d, Routed in: %d\n", lRelated, lRouted);
        printf("\tSwitching Matrix: ");

        for (long j = 0; j < cInput; j++)
        {
            hr = pXBar->CanRoute(i, j);
            printf("%d-%s", j, (S_OK == hr ? "Yes" : "No"));
        }
        printf("\n\n");
    }

    for (i = 0; i < cInput; i++)
    {
        long lRelated = -1, lType = -1;

        hr = pXBar->get_CrossbarPinInfo(TRUE, i, &lRelated, &lType);

        printf("Input pin %d - %s\n", i, GetPhysicalPinName(lType));
        printf("\tRelated in: %d\n", lRelated);
    }
}

对于假设卡,此函数可能会生成以下输出:

Output pin 0: S-Video
    Related out: 2, Routed in: 0
    Switching Matrix: 0-Yes 1-No 2-No 3-No
Output pin 1 - Video Tuner
    Related out: 2, Routed in: 1
    Switching Matrix: 0-No 1-Yes 2-No 3-No
Output pin 2 - Audio decoder
    Related out: 1, Routed in: -1
    Switching Matrix: 0-No 1-No 2-Yes 3-Yes

Input pin 0 - S-Video
    Related in: 2
Input pin 1 - Video Tuner
    Related in: 3
Input pin 2 - Audio line
    Related in: 0
Input pin 3 - Audio tuner
    Related in: 1

在输出端,S-Video 和视频调谐器都与音频解码器相关。 在输入端,视频调谐器与音频调谐器相关,而 S-Video 与中的音频线相关。 S-Video 输入路由到 S-Video 输出;视频调谐器输入将路由到视频调谐器输出。 目前,不会将任何路由到音频解码器,但中的音频行或音频调谐器都可以路由到其中。

可以通过调用 IAMCrossbar::Route 方法更改现有路由。