[英]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: 有谁知道:
Tutorial and details 教程和细节
Create the graph 创建图表
_graph = (IFilterGraph2)new FilterGraph();
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");
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);
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
。
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; } }
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);
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);
start the graph and wish for some sound or video to be displayed 启动图表并希望显示某些声音或视频
int hr = (_graph as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr);
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.