提问人:Bakhshi 提问时间:6/26/2012 最后编辑:Ken KinBakhshi 更新时间:3/19/2013 访问量:2588
强制 Mpeg2Demultiplexer 使用 ffdshow 呈现 H264 数字电视视频
Forcing Mpeg2Demultiplexer to use ffdshow to render H264 Digital TV Video
问:
不幸的是,我花了很多时间尝试使DirectShow的DTVViewer示例工作,但没有成功。DVBT网络的视频格式是H264,我发现IntelliConnect的行为更喜欢使用Mpeg2视频格式。IFilterGraph
对于那些想要查看代码的人来说,这里是。如果您对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 { } } } }
有谁知道:
- 如何将 h264 引脚连接到 ffdshow?
- 我应该如何推荐图形使用 h264 视频解码?
教程和详细信息
创建图表
_graph = (IFilterGraph2)new FilterGraph();
我们正在使用DVBT网络
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");
创建一个 mpeg2 多路复用器,从单个电视流中获取单独的 EPG/Vidoe/音频/文本流
_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);
现在连接过滤器:
[DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...
UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter); UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);
必须将两个过滤器连接到解复用器,以提供 epg(节目指南数据)。对不起,我不知道它们具体是什么 doig .它们位于类别下。我们尝试按名称找到它们并将它们连接到解复用器
: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); }
现在,demux 连接到 和 。
MPEG-2 Sections and Tables
BDA MPEG2 Transport Information Filter
现在创建 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);
下面,我尝试搜索能够处理 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; } }
为视频输出创建视频渲染器...
_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);
ConnectFilters
是从 directshowlib 的 DTVViewer 示例中借用的ConnectFilters();
我把实际的调音移到了这里
tuner.put_TuningSpace(tuningspace); tuner.put_TuneRequest(request);
启动图形并希望显示一些声音或视频
int hr = (_graph as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr);
检查图形是否正在运行...
FilterState pfs; hr = (_graph as IMediaControl).GetState(1000, out pfs); DsError.ThrowExceptionForHR(hr);
它说图形正在运行。
答:
您是否检查过您的 ffdshow 是否启用了 H264/AVC?打开过滤器属性,在“编解码器”部分,应启用 H264/AVC 格式(您也可以禁用 Mpeg2 解码器,以确保它不会喜欢这种格式)。
另一件事,您可以尝试使用另一个 Mpeg2 多路复用器。默认的“MPEG-2 解复用器”在不同环境中的行为并不相同。还有许多其他过滤器可以解复用 TS,如果您可以投入一些资金,我建议使用 MainConcept 或 Elecard。
评论