Поделиться через


Работа с перекрестиями

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие 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();
}

Более обобщенный подход см. в разделе Класс CCrossbar в примере AmCap.

Получив указатель на интерфейс 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 .