强制Mpeg2Demultiplexer使用ffdshow的呈现H264数字电视视频 [英] Forcing Mpeg2Demultiplexer to use ffdshow to render H264 Digital TV Video

查看:497
本文介绍了强制Mpeg2Demultiplexer使用ffdshow的呈现H264数字电视视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了很多时间试图使DirectShow的工作DTVViewer样品遗憾的是没有成功。 DVB-T网络的视频格式是H264,我发现 IFilterGraph prefers的IntelliConnect行为,使用MPEG2视频格式。

对于那些谁希望看到code,在这儿呢。如果你不知道的DirectShow什么我分享我的经验,这code。而最有可能的问题是在本教程的步骤5和6 描述。

  • 在$ C $下的辅助功能,连接过滤器:

     公共静态无效UnsafeConnectFilters(IFilterGraph2图,IBaseFilter源,IBaseFilter DEST,Func键< AMMediaType,布尔> sourceMedia predicate = NULL,Func键和LT; AMMediaType,布尔> destMedia predicate = NULL){
        的foreach(宜宾自旋IteratePinsByDirection(来源PinDirection.Output)){
            如果(IsConnected(旋))
                继续;
            INT进账;
            AMMediaType [] sourceTypes = GetMajorType(旋转,出来取);
            如果(取大于0){
                GUID sourceType的= sourceTypes [0] .majorType;
                尝试 {
                    如果(sourceMedia predicate = NULL和放大器;!&安培;!sourceMedia predicate(sourceTypes [0]))
                        继续;
                    的foreach(宜宾引脚IteratePinsByDirection(DEST,PinDirection.Input)){
                        如果(IsConnected(PIN))
                            继续;
                        VAR类型= GetMajorType(引脚,流出取);
                        尝试 {
                            如果(取大于0){
                                的Guid DESTTYPE =类型[0] .majorType;
                                如果(destMedia predicate = NULL和放大器;!&安培;!destMedia predicate(类型[0]))
                                    继续;
                                如果(sourceType的== DESTTYPE){
                                    spin.Connect(销,类型[0]);
                                    返回;
                                }
                            }
                            其他 {
                                spin.Connect(销,sourceTypes [0]);
                                返回;
                            }
                        }
                        最后 {
                        }
                    }
                }
                最后 {
                }
    
            }
        }
    }
     

有谁知道:

  1. 我应该如何连接H264销到ffdshow的?
  2. 我应该如何推荐使用H264视频解码的图形?

  • 教程和细节

    1. 创建图

        _graph =(IFilterGraph2)新FilterGraph动态();
       

    2. 我们使用的是DVB-T网络

        IBaseFilter networkProvider =(IBaseFilter)新DVBTNetworkProvider();
       

      ...必须调整到602000KHz @ 8MHz的ONID = 1 TSID = 1 SID = 6

        ITuner调谐器=(ITuner)networkProvider;
      IDVBTuningSpace tuningspace =(IDVBTuningSpace)新DVBTuningSpace();
      tuningspace.put_UniqueName(DVB-T TuningSpace);
      tuningspace.put_FriendlyName(DVB-T TuningSpace);
      tuningspace.put__NetworkType(typeof运算(DVBTNetworkProvider).GUID);
      tuningspace.put_SystemType(DVBSystemType.Terrestrial);
      ITuneRequest请求;
      tuningspace.CreateTuneRequest(出请求);
      ILocator定位器=(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 /介绍用户/音频/文本流了单一的电视流

        _mpeg2Demultiplexer =(IBaseFilter)新MPEG2Demultiplexer();
      _graph.AddFilter(_mpeg2Demultiplexer,MPEG-2解复用器);
       

      现在我们搜索本地过滤器BDA源过滤器,在我的情况是 IT9135 BDA Fitler

        DsDevice [] devicesOfCat =
          DsD​​evice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory);
      
      IBaseFilter iteDeviceFilter;
      
      _graph.AddSourceFilterForMoniker(
          devicesOfCat [0] .MON,空,devicesOfCat [0] .name和出iteDeviceFilter);
       

    4. 现在连接的过滤器: [DVB-T网络。供应商 - >北京经济技术开发区SRC滤波器 - > MPEG2Demux] - > ...

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

      两个过滤器必须被连接到DEMUX,以提供EPG(节目指南数据)。对不起,我不知道他们具体是癞:P 。它们都位于 BDATransportInformationRenderersCategory 类别。我们试图找到他们的名字和其连接到DEMUX

        DsDevice [] dsDevices =
          DsD​​evice.GetDevicesOfCat(FilterCategory.BDATransportInformationRenderersCategory);
      
      的foreach(DsDevice dsDevice在dsDevices)
      {
          IBaseFilter过滤器;
      
          _graph.AddSourceFilterForMoniker(
              dsDevice.Mon,空,dsDevice.Name,出过滤器);
      
          如果(dsDevice.Name ==BDA MPEG2传输信息过滤)
              _bdaTIF =过滤器;
          否则,如果(dsDevice.Name ==MPEG-2节和表)
          {
              _mpeg2SectionsAndTables =过滤器;
          }
          UnsafeConnectFilters(_graph,_mpeg2Demultiplexer,过滤器);
      }
       

      现在多路分配器连接到两个 MPEG-2节和表 BDA MPEG2传输信息过滤

    5. 现在创建H264视频类型,并添加输出输出引脚DEMUX这种类型​​

        AMMediaType H264 =新AMMediaType();
      h264.formatType = FormatType.VideoInfo2;
      h264.subType = MediaSubType.H264;
      h264.majorType = MediaType.Video;
      宜宾h264pin;
      ((IMpeg2Demultiplexer)_mpeg2Demultiplexer).CreateOutputPin(H264,H264,出h264pin);
       

      下面,我试图寻找ffdshow的视频德codeR,它能够处理H264视频和位于 DirectShow过滤器类别(如 GraphStudio )。

        DsDevice [] directshowfilters =
          DsD​​evice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory);
      
      IBaseFilter ffdshow的= NULL;
      的foreach(DsDevice directshowfilter在directshowfilters)
      {
          如果(directshowfilter.Name ==ffdshow的视频德codeR)
          {
              _graph.AddSourceFilterForMoniker(
                  directshowfilter.Mon,空,directshowfilter.Name,
                  出ffdshow的);
      
              打破;
          }
      }
       

    6. 创建视频渲染视频输出

        _videoRenderer =新VideoRendererDefault();
      _graph.AddFilter((IBaseFilter)_videoRenderer,视频渲染器);
       

      ...和音频...

        DsDevice defaultDirectSound =
          DsD​​evice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0];
      
      _graph.AddSourceFilterForMoniker(
          defaultDirectSound.Mon,空,defaultDirectSound.Name,
          出_audioRender);
       

      在这里,我试图连接多路分解器的H264输出引脚ffdshow的。此方法调用失败,AccessViolationException。我不知道如何连接这两个在一起:(

      评论此线将导致其开始运行的曲线图,虽然在图中的一条断开ffdshowVideoDe codeR滤波器,将不显示任何东西。 IntelliConnect MPEG2视频输出连接到本地可用的视频去$ C $铬,正如我所说的,将不显示任何内容。

        // UnsafeConnectFilters(_graph,_mpeg2Demultiplexer,ffdshow的,类型=> type.majorType == MediaType.Video和放大器;&安培; type.subType == MediaSubType.H264);
       

    7. ConnectFilters 从directshowlib的DTVViewer样品借

        ConnectFilters();
       

      我搬到这里的实际调整

        tuner.put_TuningSpace(tuningspace);
      tuner.put_TuneRequest(要求);
       

    8. 要显示
    9. 启动图形,并希望一些声音或视频

        INT小时=(_graph为IMediaControl).RUN();
      DsError.ThrowExceptionForHR(小时);
       

    10. 检查图形运行...

        FilterState PFS;
      HR =(_graph为IMediaControl).GetState(1000,出PFS);
      DsError.ThrowExceptionForHR(小时);
       

      和它说,该图运行。

解决方案

你检查你的ffdshow的启用了H264 / AVC?打开过滤器属性并在codeCS部分,H264 / AVC格式,应启用(你还可以禁用MPEG2的德codeR公正,以确保它不会PFER这种格式$ P $)。

另一件事,您可以尝试使用其他的Mpeg2解复用器。默认的MPEG-2解复用器不表现相同于不同的环境。还有很多其他的过滤器,可以解复用TS,如果你可以投资一些钱,我推荐使用MainConcept公司或Elecard。

I spend a lot of time trying to make DTVViewer sample of DirectShow work unfortunately with no success. The video format of DVBT network is H264 and I found that the IntelliConnect behavior of IFilterGraph prefers to use Mpeg2 Video format.

For those who want to see the code, here it is. If you do not know anything about DirectShow I shared my experience with this code. And the most probably problem is described in step 5 and 6 of the tutorial.

  • The code for helper function which connects filters:

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

Does anyone know about:

  1. How should I connect the h264 pin to ffdshow?
  2. How should I recommend the graph to use h264 video decoding?


  • Tutorial and details

    1. Create the graph

      _graph = (IFilterGraph2)new FilterGraph();
      

    2. We are using DVBT network

      IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
      

      ... which must be tuned to 602000KHz@8MHz 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");
      

    3. Create a mpeg2 demux to get separate EPG/Vidoe/Audio/Text streams out of single TV stream

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

      Now we search local filters for BDA Source Filter which in my case is IT9135 BDA Fitler

      DsDevice[] devicesOfCat = 
          DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory);
      
      IBaseFilter iteDeviceFilter;
      
      _graph.AddSourceFilterForMoniker(
          devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter);
      

    4. Now connect filters: [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...

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

      Two filters must be connected to demux, to provide epg (program guide data). sorry I do not know what they specifically are doig :P. They are located under BDATransportInformationRenderersCategory category. We try to find them by name and connect them to 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);
      }
      

      Now demux is connected to both MPEG-2 Sections and Tables and BDA MPEG2 Transport Information Filter.

    5. Now create h264 video type and add the output an output pin to demux for this type

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

      Below, I tried to search for ffdshow Video Decoder which is capable of processing H264 video and is located under DirectShow Filters category(as 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. Create a video renderer for video output ...

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

      ... and audio ...

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

      Here I tried to connect h264 output pin of demux to ffdshow. This method call fails with AccessViolationException. I'm not sure how to connect these two together :(.

      Commenting this line will result in a graph which starts running, although there is an disconnected ffdshowVideoDecoder filter in the graph, will not show anything. IntelliConnect connects Mpeg2 video output to a locally available video decoder and as I said it will not display anything.

      // UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
      

    7. ConnectFilters is borrowed from DTVViewer sample of directshowlib

      ConnectFilters();
      

      I moved actual tuning here

      tuner.put_TuningSpace(tuningspace);
      tuner.put_TuneRequest(request);
      

    8. start the graph and wish for some sound or video to be displayed

      int hr = (_graph as IMediaControl).Run();
      DsError.ThrowExceptionForHR(hr);
      

    9. check that the graph is running ...

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

      and it says that the graph is running.

解决方案

Did you check that your ffdshow is enabled for H264/AVC? Open the filter properties and In "Codecs" section, H264/AVC format should be enabled (you can also disable the Mpeg2 decoder just to make sure it won't prefer this format).

Another thing, you can try using another Mpeg2 demultiplexer. The default "MPEG-2 Demultiplexer" is not behaving the same on different environments. There are many other filters that can demux TS and if you can invest some money, I'd recommend using MainConcept or Elecard.

这篇关于强制Mpeg2Demultiplexer使用ffdshow的呈现H264数字电视视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆