2012-06-26 19 views
22

Trascorro molto tempo a cercare di rendere sfortunatamente l'esempio di DirectShow di DTVViewer senza successo. Il formato video della rete DVBT è H264 e ho scoperto che il comportamento di IntelliConnect di IFilterGraph preferisce utilizzare il formato video Mpeg2.Forzare Mpeg2Demultiplexer a utilizzare ffdshow per eseguire il rendering del video TV digitale H264

Per coloro che vogliono vedere il codice, eccolo. Se non sai nulla di DirectShow ho condiviso la mia esperienza con questo codice. E il problema più probabile è descritto in passaggio 5 e 6 del tutorial.

  • Il codice per la funzione di supporto che collega filtri:

    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 { 
          } 
    
         } 
        } 
    } 
    

Qualcuno sa su:

  1. Come devo collegare il perno h264 di ffdshow?
  2. Come dovrei consigliare il grafico per utilizzare la decodifica video h264?

  • Tutorial e dettagli

    1. Creare il grafico

      _graph = (IFilterGraph2)new FilterGraph(); 
      
    2. Stiamo utilizzando rete DVBT

      01.235.
      IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider(); 
      

      ... che deve essere sintonizzato 602000KHz @ 8 MHz ONID = 1 IDST = 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"); 
      
    3. Creare un demux MPEG2 per ottenere separati EPG/Vidoe/Audio/Testo flussi fuori Stream TV singolo

      _mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer(); 
      _graph.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer"); 
      

      Ora cerchiamo filtri locali per BDA Fonte filtro che nel mio caso è IT9135 BDA Fitler

      DsDevice[] devicesOfCat = 
          DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory); 
      
      IBaseFilter iteDeviceFilter; 
      
      _graph.AddSourceFilterForMoniker(
          devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter); 
      
    4. ora connettersi filtri: [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...

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

      Due filtri devono essere collegati a demux, per fornire EPG (dati della guida del programma). scusate, non so cosa siano specificamente doig :P. Si trovano sotto la categoria BDATransportInformationRenderersCategory. Cerchiamo di trovarli per nome e collegarli 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); 
      } 
      

      Ora demux è collegato sia MPEG-2 Sections and Tables e BDA MPEG2 Transport Information Filter.

    5. Ora creare tipo di video H264 e aggiungere l'uscita un pin di uscita demux per questo tipo

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

      Qui di seguito, ho provato a cercare ffdshow Video Decoder che è in grado di elaborare il video H264 ed è situato sotto la categoria DirectShow Filters (come in 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; 
          } 
      } 
      
    6. Creare un renderer video per l'uscita video ...

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

      ... e audio ...

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

      Qui ho cercato di collegare il pin di uscita H264 di demux a ffdshow. Questa chiamata al metodo ha esito negativo con AccessViolationException. Non sono sicuro di come collegare questi due insieme :(.

      Commentando questa riga si otterrà un grafico che inizia a funzionare, sebbene nel grafico sia presente un filtro ffdshowVideoDecoder disconnesso, non verrà mostrato nulla. IntelliConnect collega l'uscita video Mpeg2 a un decodificatore video disponibile localmente e, come ho detto, non mostrerà nulla.

      // UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264); 
      
    7. ConnectFilters è preso da DTVViewer campione di directshowlib

      ConnectFilters(); 
      

      mi sono trasferito sintonizzazione reale qui

      tuner.put_TuningSpace(tuningspace); 
      tuner.put_TuneRequest(request); 
      
    8. avviare il grafico e desiderare un suono o un video da visualizzare

      int hr = (_graph as IMediaControl).Run(); 
      DsError.ThrowExceptionForHR(hr); 
      
    9. verifica che il grafico è in funzione ...

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

      e si dice che il grafico è in esecuzione.

+0

... E direi che sto usando Windows XP :) – Bakhshi

+0

Puoi creare manualmente il grafico usando GraphEdit? In tal caso, includi il grafico manuale come screenshot. – Odys

+0

@odyodyodys Non lavoro più su quel progetto. ma non ero in grado di creare il grafico usando solo GraphEdit. Richiede molte configurazioni di porte che sono impossibili in GE. Finalmente ho usato il componente TeamMediaPortal che l'ho estratto dai codici sorgente. – Bakhshi

risposta

1

Hai controllato che il ffdshow è abilitato per H264/AVC? Apri le proprietà del filtro e nella sezione "Codec", il formato H264/AVC deve essere abilitato (puoi anche disabilitare il decoder Mpeg2 solo per assicurarti che non preferisca questo formato).

Un'altra cosa, puoi provare a usare un altro demultiplexer Mpeg2. Il predefinito "Demultiplexer MPEG-2" non si comporta allo stesso modo su ambienti diversi. Ci sono molti altri filtri che possono demux TS e se è possibile investire un po 'di soldi, mi consiglia di utilizzare MainConcept o Elecard.

+0

grazie per il passaggio. Sì, l'H262 era abilitato nelle proprietà ffdshow. Riguardo all'utilizzo di altri demi, non sono sicuro se li ho testati o meno. è passato un po 'di tempo. comunque, se hai qualcosa in esecuzione puoi condividere la tua esperienza qui in modo che gli altri possano imparare qualcosa da esso? Grazie – Bakhshi