Подтвердить что ты не робот

Принуждение Mpeg2Demultiplexer для использования ffdshow для рендеринга H264 Digital TV Video

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

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

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

    public static void UnsafeConnectFilters(IFilterGraph2 graph, IBaseFilter source, IBaseFilter dest, Func<AMMediaType, bool> sourceMediaPredicate=null, Func<AMMediaType, bool> destMediaPredicate=null) {
        foreach(IPin spin in IteratePinsByDirection(source, PinDirection.Output)) {
            if(IsConnected(spin))
                continue;
            int fetched;
            AMMediaType[] sourceTypes=GetMajorType(spin, out fetched);
            if(fetched>0) {
                Guid sourceType=sourceTypes[0].majorType;
                try {
                    if(sourceMediaPredicate!=null&&!sourceMediaPredicate(sourceTypes[0]))
                        continue;
                    foreach(IPin pin in IteratePinsByDirection(dest, PinDirection.Input)) {
                        if(IsConnected(pin))
                            continue;
                        var types=GetMajorType(pin, out fetched);
                        try {
                            if(fetched>0) {
                                Guid destType=types[0].majorType;
                                if(destMediaPredicate!=null&&!destMediaPredicate(types[0]))
                                    continue;
                                if(sourceType==destType) {
                                    spin.Connect(pin, types[0]);
                                    return;
                                }
                            }
                            else {
                                spin.Connect(pin, sourceTypes[0]);
                                return;
                            }
                        }
                        finally {
                        }
                    }
                }
                finally {
                }
    
            }
        }
    }
    

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

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

  • Учебное пособие и сведения

    • Создайте график

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

      IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
      

      ... который должен быть настроен на 602000 кГц при 8 МГц ONID = 1 TSID = 1 SID = 6

      ITuner tuner = (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 request;
      tuningspace.CreateTuneRequest(out request);
      ILocator locator = (ILocator) new DVBTLocator();
      locator.put_CarrierFrequency(602000);
      ((IDVBTLocator) locator).put_Bandwidth(8);
      request.put_Locator(locator);
      IDVBTuneRequest dvbrequest = (IDVBTuneRequest) request;
      dvbrequest.put_TSID(1);
      dvbrequest.put_ONID(1);
      dvbrequest.put_SID(6);
      _graph.AddFilter(networkProvider, "Network Provider");
      
    • Создайте mpeg2 demux для получения отдельных потоков EPG/Vidoe/Audio/Text из одного телевизионного потока.

      _mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer();
      _graph.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, out iteDeviceFilter);
      
    • Теперь подключите фильтры: [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...

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

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

      DsDevice[] dsDevices = 
          DsDevice.GetDevicesOfCat(FilterCategory.BDATransportInformationRenderersCategory);
      
      foreach (DsDevice dsDevice in dsDevices)
      {
          IBaseFilter filter;
      
          _graph.AddSourceFilterForMoniker(
              dsDevice.Mon, null, dsDevice.Name, out filter);
      
          if(dsDevice.Name == "BDA MPEG2 Transport Information Filter")
              _bdaTIF = filter;
          else if(dsDevice.Name == "MPEG-2 Sections and Tables")
          {
              _mpeg2SectionsAndTables = filter;
          }
          UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, filter);
      }
      

      Теперь demux подключается как к MPEG-2 Sections and Tables, так и к BDA MPEG2 Transport Information Filter.

    • Теперь создайте тип видео h264 и добавьте вывод выходного вывода в demux для этого типа

      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 = null;
      foreach (DsDevice directshowfilter in directshowfilters)
      {
          if(directshowfilter.Name == "ffdshow Video Decoder")
          {
              _graph.AddSourceFilterForMoniker(
                  directshowfilter.Mon, null, directshowfilter.Name, 
                  out ffdshow);
      
              break;
          }
      }
      
    • Создайте средство визуализации видео для вывода видео...

      _videoRenderer = new VideoRendererDefault();
      _graph.AddFilter((IBaseFilter)_videoRenderer, "Video Renderer");
      

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

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

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

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

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

      ConnectFilters();
      

      Я перевел реальную настройку здесь

      tuner.put_TuningSpace(tuningspace);
      tuner.put_TuneRequest(request);
      
    • запустите график и захотите отобразить какой-либо звук или видео

      int hr = (_graph as IMediaControl).Run();
      DsError.ThrowExceptionForHR(hr);
      
    • проверьте, что график запущен...

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

      и он говорит, что график запущен.

4b9b3361

Ответ 1

Вы проверили, что ваш ffdshow включен для H264/AVC? Откройте свойства фильтра, а в разделе "Кодеки" должен быть включен формат H264/AVC (вы также можете отключить декодер Mpeg2, чтобы убедиться, что он не будет использовать этот формат).

Другое дело, вы можете попробовать использовать другой демультиплексор Mpeg2. По умолчанию "MPEG-2 Demultiplexer" не ведет себя одинаково в разных средах. Есть много других фильтров, которые могут использовать demux TS, и если вы можете вложить немного денег, я бы рекомендовал использовать MainConcept или Elecard.