IFilterGraph
的IntelliConnect行为更喜欢使用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 {
}
}
}
}
有人了解吗:
- 我应该如何将h264引脚连接到ffdshow?
- 我应该如何推荐图使用h264视频解码?
教程和详细信息
创建图表
我们正在使用DVBT网络。_graph = (IFilterGraph2)new FilterGraph();
IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
... 这必须调整到602000KHz@8MHz ONID=1 TSID=1 SID=6
创建一个mpeg2解复用器,从单个电视流中获取独立的EPG /视频/音频/文本流。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");
_mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer(); _graph.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer");
现在我们搜索本地过滤器以查找BDA源过滤器,而在我的情况下是
IT9135 BDA Filter
DsDevice[] devicesOfCat = DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory); IBaseFilter iteDeviceFilter; _graph.AddSourceFilterForMoniker( devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter);
现在连接过滤器:
[DVBT 网络提供商] -> [BDA Src 过滤器] -> [MPEG2Demux] -> ...
UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter);
UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);
必须将两个过滤器连接到解复用器上,以提供电视节目指南数据。抱歉,我不知道它们具体是做什么的: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 视频类型并将其添加到 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);
以下是我尝试搜索的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;
}
}
创建视频渲染器以用于视频输出...
_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);
我尝试将demux的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);
开始绘制图表,并期望能够显示一些声音或视频。<\li>int hr = (_graph as IMediaControl).Run();
DsError.ThrowExceptionForHR(hr);
检查图形是否正在运行...
FilterState pfs;
hr = (_graph as IMediaControl).GetState(1000, out pfs);
DsError.ThrowExceptionForHR(hr);
它表示图表正在运行。