简体   繁体   English

强制Mpeg2Demultiplexer使用ffdshow渲染H264数字电视视频

[英]Forcing Mpeg2Demultiplexer to use ffdshow to render H264 Digital TV Video

I spend a lot of time trying to make DTVViewer sample of DirectShow work unfortunately with no success. 我花了很多时间试图让DTVViewer的DirectShow样本工作不幸,但没有成功。 The video format of DVBT network is H264 and I found that the IntelliConnect behavior of IFilterGraph prefers to use Mpeg2 Video format. DVBT网络的视频格式是H264,我发现IFilterGraph的IntelliConnect行为更喜欢使用Mpeg2视频格式。

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. 如果你对DirectShow一无所知我分享了我对这段代码的经验。 And the most probably problem is described in step 5 and 6 of the tutorial. 最可能的问题在本教程的第5步和第6步中描述。

  • 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? 我应该如何将h264引脚连接到ffdshow?
  2. How should I recommend the graph to use h264 video decoding? 我应该如何推荐使用h264视频解码图?

  • Tutorial and details 教程和细节

    1. Create the graph 创建图表

       _graph = (IFilterGraph2)new FilterGraph(); 
    2. We are using DVBT network 我们正在使用DVBT网络

       IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider(); 

      ... which must be tuned to 602000KHz@8MHz ONID=1 TSID=1 SID=6 ...必须调到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 创建一个mpeg2 demux,从单个电视流中获取单独的EPG / Vidoe /音频/文本流

       _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 现在我们搜索BDA源过滤器的本地过滤器,在我的例子中是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]-> ... 现在连接过滤器: [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ... [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). 必须将两个过滤器连接到demux,以提供epg(节目指南数据)。 sorry I do not know what they specifically are doig :P . 抱歉,我不知道他们具体是什么:P They are located under BDATransportInformationRenderersCategory category. 它们位于BDATransportInformationRenderersCategory类别下。 We try to find them by name and connect them to demux 我们尝试按名称找到它们并将它们连接到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 . 现在,demux连接到MPEG-2 Sections and Tables以及BDA MPEG2 Transport Information Filter

    5. Now create h264 video type and add the output an output pin to demux for this type 现在创建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); 

      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 ). 下面,我尝试搜索能够处理H264视频的ffdshow视频解码器,它位于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; } } 
    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. 在这里,我尝试将demux的h264输出引脚连接到ffdshow。 This method call fails with AccessViolationException. 此方法调用因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. 注释这一行将导致图形开始运行,尽管图中有一个断开的ffdshowVideoDecoder过滤器,但不会显示任何内容。 IntelliConnect connects Mpeg2 video output to a locally available video decoder and as I said it will not display anything. IntelliConnect将Mpeg2视频输出连接到本地可用的视频解码器,正如我所说,它不会显示任何内容。

       // UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264); 
    7. ConnectFilters is borrowed from DTVViewer sample of directshowlib ConnectFilters从directshowlib的DTVViewer样品借

       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? 您是否检查过您的ffdshow是否已启用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). 打开过滤器属性,在“编解码器”部分,应启用H264 / AVC格式(您也可以禁用Mpeg2解码器,以确保它不喜欢这种格式)。

Another thing, you can try using another Mpeg2 demultiplexer. 另外,你可以尝试使用另一个Mpeg2解复用器。 The default "MPEG-2 Demultiplexer" is not behaving the same on different environments. 默认的“MPEG-2解复用器”在不同的环境中表现不一样。 There are many other filters that can demux TS and if you can invest some money, I'd recommend using MainConcept or Elecard. 还有许多其他过滤器可以拆分TS,如果你可以投入一些钱,我建议使用MainConcept或Elecard。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM