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

2019-07-30 02:59发布

我花了很多时间试图让DirectShow的工作DTVViewer样品遗憾的是没有成功。 DVB-T网络的视频格式是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 { } } } } 

有谁知道:

  1. 我应该如何连接H264引脚ffdshow的?
  2. 我应该怎么建议使用H264视频解码的图形?

  • 教程和细节

    1. 创建图表

       _graph = (IFilterGraph2)new FilterGraph(); 
    2. 我们正在使用DVB-T网络

       IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider(); 

      ...必须被调谐到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. 创建一个MPEG2解复用得到独立的EPG /介绍用户/音频/文本流了单一的电视流

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

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

       DsDevice[] devicesOfCat = DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory); IBaseFilter iteDeviceFilter; _graph.AddSourceFilterForMoniker( devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter); 
    4. 现在连接过滤器: [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ... [DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...

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

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

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

      现在,分离器连接到两个MPEG-2 Sections and TablesBDA MPEG2 Transport Information Filter

    5. 现在创建H264视频类型,并添加输出的输出引脚,以解复用器这种类型

       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的视频解码器,它能够处理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; } } 
    6. 创建视频输出的视频渲染器 ...

       _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); 
    7. ConnectFilters从directshowlib的DTVViewer样品借

       ConnectFilters(); 

      我搬到这里实际调整

       tuner.put_TuningSpace(tuningspace); tuner.put_TuneRequest(request); 
    8. 开始为一些声音或视频的图形,并希望显示

       int hr = (_graph as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr); 
    9. 检查图形正在运行...

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

      它说的是,图运行。

Answer 1:

你检查你的ffdshow的是为H264 / AVC启用? 打开过滤器属性并在“编解码器”部分,H264 / AVC格式应该启用(你也可以禁用MPEG2解码公正,以确保它不会喜欢这种格式)。

另一件事,你可以尝试使用其他Mpeg2的解复用器。 默认的“MPEG-2解复用器”不是表现在不同环境下的相同。 有迹象表明,可以解复用TS,如果你可以投资一些钱,我推荐使用MainConcept公司或Elecard许多其他过滤器。



文章来源: Forcing Mpeg2Demultiplexer to use ffdshow to render H264 Digital TV Video