Принуждение Mpeg2Demultiplexer к использованию ffdshow для рендеринга H264 цифрового телевизионного видео

Я трачу много времени, пытаясь заставить DTVViewer образец DirectShow работать, к сожалению, безуспешно. Видеоформат сети DVBT — H264, и я обнаружил, что поведение IntelliConnect IFilterGraphпредпочитает использовать видеоформат Mpeg2.

Для тех, кто хочет увидеть код, вот он. Если вы ничего не знаете о DirectShow, я поделился своим опытом работы с этим кодом. И наиболее вероятная проблема описана в шагах 5 и 6руководства.

  • Код для вспомогательной функции, которая подключает фильтры:

    public static void UnsafeConnectFilters(IFilterGraph2 graph, IBaseFilter source, IBaseFilter dest, Func sourceMediaPredicate=null, Func destMediaPredicate=null) {
    foreach (вращение IP-адреса в IteratePinsByDirection (источник, PinDirection.Output)) {
    если(Подключен(спин))
    Продолжать;
    получено;
    AMMediaType [] sourceTypes = GetMajorType (раскрутить, извлечь);
    если (выбрано> 0) {
    Guid sourceType=sourceTypes[0].majorType;
    пытаться {
    if(sourceMediaPredicate!=null&&!sourceMediaPredicate(sourceTypes[0]))
    Продолжать;
    foreach (контакт IPin в IteratePinsByDirection (dest, PinDirection.Input)) {
    если (подключен (вывод))
    Продолжать;
    var types = GetMajorType (булавка, получено);
    пытаться {
    если (выбрано> 0) {
    Guid destType=types[0].основной тип;
    if(destMediaPredicate!=null&&!destMediaPredicate(типы[0]))
    Продолжать;
    если (исходный тип == тип назначения) {
    spin.Connect (пин, типы [0]);
    вернуть;
     }
     }
    еще {
    spin.Connect(pin, sourceTypes[0]);
    вернуть;
     }
     }
    наконец {
     }
     }
     }
    наконец {
     }
    
     }
     }
    }
    

Кто-нибудь знает о:

  1. Как подключить вывод h264 к ffdshow?
  2. Как мне порекомендовать графу использовать декодирование видео h264?

  • Учебник и подробности

    1. Создание графа

      _graph = (IFilterGraph2)new FilterGraph();
      
    2. Мы используем сеть DVBT

      IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
      

      ... который должен быть настроен на 602000KHz@8MHz ONID=1 TSID=1 SID=6

      ITuner tuning = (ITuner) networkProvider;
      IDVBTuningSpace tuningspace = (IDVBTuningSpace) new DVBTuningSpace();
      tuningspace.put_UniqueName("DVBT TuningSpace");
      tuningspace.put_FriendlyName ("DVBT TuningSpace");
      tuningspace.put__NetworkType(typeof (DVBTNetworkProvider).GUID);
      tuningspace.put_SystemType(DVBSystemType.Terrestrial);
      запрос ITuneRequest;
      tuningspace.CreateTuneRequest (исходящий запрос);
      ILocator locator = (ILocator) новый DVBTLocator();
      locator.put_CarrierFrequency (602000);
      ((IDVBTLocator) локатор).put_Bandwidth(8);
      request.put_Locator(локатор);
      IDVBTuneRequest dvbrequest = (IDVBTuneRequest) запрос;
      dvbrequest.put_TSID(1);
      dvbrequest.put_ONID(1);
      dvbrequest.put_SID (6);
      _graph.AddFilter(networkProvider, "Сетевой провайдер");
      
    3. Создайте демультиплексор mpeg2, чтобы получить отдельные потоки EPG/Vidoe/Audio/Text из одного ТВ-потока.

      _mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer();
      _граф.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer");
      

      Теперь мы ищем локальные фильтры для BDA Source Filter, в моем случае это IT9135 BDA Fitler

      DsDevice[] devicesOfCat =
      DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory);
      IBaseFilter iteDeviceFilter;
      
      _graph.AddSourceFilterForMoniker(
      devicesOfCat[0].Mon, null, devicesOfCat[0].Name, из iteDeviceFilter);
      
    4. Теперь подключите фильтры: [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...

      UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter);
      UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);
      

      Два фильтра должны быть подключены к демультиплексору, чтобы обеспечить epg (данные программы передач). извините, я не знаю, что конкретно они делают :P. Они находятся в категории BDATransportInformationRenderersCategory. Пытаемся найти их по имени и подключить к демультиплексору

      DsDevice[] dsDevices =
      DsDevice.GetDevicesOfCat(FilterCategory.BDATransportInformationRenderersCategory);
      foreach (DsDevice dsDevice в dsDevices)
      {
      фильтр IBaseFilter;
      
       _graph.AddSourceFilterForMoniker(
      dsDevice.Mon, null, dsDevice.Name, выходной фильтр);
      
      if(dsDevice.Name == "Фильтр транспортной информации BDA MPEG2")
       _bdaTIF = фильтр;
      else if(dsDevice.Name == "Разделы и таблицы MPEG-2")
       {
       _mpeg2SectionsAndTables = фильтр;
       }
      UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, filter);
      }
      

      Теперь демультиплексор подключен как к Разделам и таблицам MPEG-2, так и к Фильтру транспортной информации BDA MPEG2.

    5. Теперь создайте тип видео h264 и добавьте выходной вывод в демультиплексор для этого типа.

      AMMediaType h264 = new AMMediaType();
      h264.formatType = FormatType.VideoInfo2;
      h264.subType = MediaSubType.H264;
      h264.majorType = MediaType.Video;IPin h264pin;
      ((IMpeg2Demultiplexer) _mpeg2Demultiplexer).CreateOutputPin(h264, "h264", out h264pin);
      

      Ниже я попытался найти ffdshow Video Decoder, способный обрабатывать видео H264 и расположенный в категории DirectShow Filters(как в GraphStudio).

      DsDevice[] directshowfilters =
      DsDevice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory);
      IBaseFilter ffdshow = ноль;
      foreach (DsDevice directshowfilter в directshowfilters)
      {
      if(directshowfilter.Name == "Видеодекодер ffdshow")
       {
       _graph.AddSourceFilterForMoniker(
      directshowfilter.Mon, ноль, directshowfilter.Name,
      вне ffdshow);
      
      перерыв;
       }
      }
      
    6. Создать средство визуализации видео для вывода видео...

      _videoRenderer = new VideoRendererDefault();
      _graph.AddFilter((IBaseFilter)_videoRenderer, "Обработчик видео");
      

      ... и аудио ...

      DsDevice defaultDirectSound =
      DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0];
      
      _graph.AddSourceFilterForMoniker(
      defaultDirectSound.Mon, null, defaultDirectSound.Name,
      вне _audioRender);
      

      Здесь я попытался подключить выходной вывод h264 демультиплексора к ffdshow. Вызов этого метода завершается с ошибкой AccessViolationException. Я не уверен, как соединить эти два вместе :(.

      Комментирование этой строки приведет к запуску графика, хотя на графике есть отключенный фильтр ffdshowVideoDecoder, ничего не покажет IntelliConnect подключает видеовыход Mpeg2 к локально доступному видеодекодеру и, как я уже сказал, ничего не отображает.

       // UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
      
    7. ConnectFiltersзаимствован из примера DTVViewer библиотеки directshowlib

      ConnectFilters();
      

      Я переместил актуальные настройки сюда

      tuning.put_TuningSpace(tuningspace);
      Tuner.put_TuneRequest (запрос);
      
    8. запустить график и пожелать, чтобы отображался звук или видео

      int hr = (_graph as IMediaControl).Run();
      DsError.ThrowExceptionForHR(ч);
      
    9. проверить, работает ли граф...

      FilterState pfs;
      hr = (_graph as IMediaControl).GetState(1000, out pfs);
      DsError.ThrowExceptionForHR(ч);
      

      и там написано, что граф работает.

22
задан Ken Kin 19 March 2013 в 09:57
поделиться