2012-06-26 20 views
22

Paso mucho tiempo tratando de hacer que la muestra de DTVViewer de DirectShow funcione desafortunadamente sin éxito. El formato de video de la red DVBT es H264 y encontré que el comportamiento de IntelliConnect de IFilterGraph prefiere usar el formato de video Mpeg2.Cómo forzar a Mpeg2Demultiplexer a usar ffdshow para procesar H264 Digital TV Video

Para aquellos que quieren ver el código, aquí está. Si no sabe nada sobre DirectShow, compartí mi experiencia con este código. Y el problema más probable se describe en paso 5 y 6 del tutorial.

  • El código de función auxiliar que conecta filtros:

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

¿Alguien sabe acerca de:

  1. ¿Cómo debo conectar la clavija h264 a ffdshow?
  2. ¿Cómo debo recomendar el gráfico para usar la decodificación de video h264?

  • Tutorial y detalles

    1. Crear el gráfico

      _graph = (IFilterGraph2)new FilterGraph(); 
      
    2. Estamos utilizando la red DVB-T

      IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider(); 
      

      ... que debe ser sintonizado a 602000KHz @ 8 MHz ONID = 1 = 1 TSID 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. Crear un demux MPEG2 para obtener por separado EPG/Vidoe/audio/texto fluye hacia fuera de TV de simple flujo

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

      Ahora que sus resultados de búsqueda locales para BDA Fuente de filtro que en mi caso es IT9135 BDA Fitler

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

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

      Dos filtros deben estar conectados a demux, para proporcionar datos de la guía EPG (programa). lo siento, no sé lo que son específicamente doig :P. Están ubicados en la categoría BDATransportInformationRenderersCategory. Tratamos de encontrar por su nombre y conectarlos a demultiplexar

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

      Ahora demux está conectado tanto MPEG-2 Sections and Tables y BDA MPEG2 Transport Information Filter.

    5. Ahora crea tipo de vídeo H264 y añadir la salida de un pin de salida demultiplexar para este 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); 
      

      A continuación, traté de buscar ffdshow decodificador de vídeo que es capaz de procesar vídeo H264 y está ubicado en la categoría DirectShow Filters (como en 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. Crear un procesador de vídeo para salida de vídeo ...

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

      ... y audio ...

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

      Aquí me trataron de conectar el pin de salida h264 de demux a ffdshow. Esta llamada a método falla con AccessViolationException. No estoy seguro de cómo conectar estos dos juntos :(.

      Al comentar esta línea aparecerá un gráfico que se iniciará, aunque hay un filtro ffdshowVideoDecoder desconectado en el gráfico, no se mostrará nada. IntelliConnect conecta la salida de video Mpeg2 a un decodificador de video disponible localmente y como dije no mostrará nada.

      // UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264); 
      
    7. ConnectFilters es tomada de la muestra DTVViewer de directshowlib

      ConnectFilters(); 
      

      me moví de sintonización real aquí

      tuner.put_TuningSpace(tuningspace); 
      tuner.put_TuneRequest(request); 
      
    8. iniciar la gráfica y el deseo de algún sonido o vídeo que se mostrará

      int hr = (_graph as IMediaControl).Run(); 
      DsError.ThrowExceptionForHR(hr); 
      
    9. cheque que el gráfico está en marcha ...

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

      y se dice que el gráfico está en marcha.

+0

... Y mejor diré que estoy usando Windows XP :) – Bakhshi

+0

¿Puedes crear el gráfico manualmente usando GraphEdit? De ser así, incluya el gráfico manual como captura de pantalla. – Odys

+0

@odyodyodys Ya no trabajo en ese proyecto. pero no pude crear el gráfico usando solo GraphEdit. Requiere mucha configuración de puertos que es imposible en GE. Finalmente utilicé el componente TeamMediaPortal que extraje de los códigos fuente. – Bakhshi

Respuesta

1

¿Ha comprobado que su ffdshow está habilitado para H264/AVC? Abra las propiedades del filtro y en la sección "Códecs", el formato H264/AVC debe estar habilitado (también puede desactivar el decodificador Mpeg2 solo para asegurarse de que no prefiera este formato).

Otra cosa, puede intentar usar otro demultiplexor Mpeg2. El "Demultiplexor MPEG-2" predeterminado no se comporta de la misma manera en diferentes entornos. Hay muchos otros filtros que pueden demultiplexar TS y si puede invertir algo de dinero, le recomiendo usar MainConcept o Elecard.

+0

gracias por pasar. Sí, el H262 fue habilitado en las propiedades de ffdshow. Sobre el uso de otros demuxes, no estoy seguro si los probé o no. ha sido un tiempo. De todos modos, si tienes algo en ejecución, ¿puedes compartir tu experiencia aquí para que otros puedan aprender algo de ello? Gracias – Bakhshi

Cuestiones relacionadas