Я трачу много времени, пытаясь заставить DTVViewer образец DirectShow работать, к сожалению, безуспешно. Видеоформат сети DVBT — H264, и я обнаружил, что поведение IntelliConnect IFilterGraph
предпочитает использовать видеоформат Mpeg2.
Для тех, кто хочет увидеть код, вот он. Если вы ничего не знаете о DirectShow, я поделился своим опытом работы с этим кодом. И наиболее вероятная проблема описана в шагах 5 и 6руководства.
Код для вспомогательной функции, которая подключает фильтры:
public static void UnsafeConnectFilters(IFilterGraph2 graph, IBaseFilter source, IBaseFilter dest, Func sourceMediaPredicate=null, Func destMediaPredicate=null) {
foreach (вращение IP-адреса в IteratePinsByDirection (источник, PinDirection.Output)) {
если(Подключен(спин))
Продолжать;
получено;
AMMediaType [] sourceTypes = GetMajorType (раскрутить, извлечь);
если (выбрано> 0) {
Guid sourceType=sourceTypes[0].majorType;
пытаться {
if(sourceMediaPredicate!=null&&!sourceMediaPredicate(sourceTypes[0]))
Продолжать;
foreach (контакт IPin в IteratePinsByDirection (dest, PinDirection.Input)) {
если (подключен (вывод))
Продолжать;
var types = GetMajorType (булавка, получено);
пытаться {
если (выбрано> 0) {
Guid destType=types[0].основной тип;
if(destMediaPredicate!=null&&!destMediaPredicate(типы[0]))
Продолжать;
если (исходный тип == тип назначения) {
spin.Connect (пин, типы [0]);
вернуть;
}
}
еще {
spin.Connect(pin, sourceTypes[0]);
вернуть;
}
}
наконец {
}
}
}
наконец {
}
}
}
}
Кто-нибудь знает о:
Учебник и подробности
Создание графа
_graph = (IFilterGraph2)new FilterGraph();
Мы используем сеть DVBT
IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
... который должен быть настроен на 602000KHz@8MHz ONID=1 TSID=1 SID=6
ITuner tuning = (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;
tuningspace.CreateTuneRequest (исходящий запрос);
ILocator locator = (ILocator) новый DVBTLocator();
locator.put_CarrierFrequency (602000);
((IDVBTLocator) локатор).put_Bandwidth(8);
request.put_Locator(локатор);
IDVBTuneRequest dvbrequest = (IDVBTuneRequest) запрос;
dvbrequest.put_TSID(1);
dvbrequest.put_ONID(1);
dvbrequest.put_SID (6);
_graph.AddFilter(networkProvider, "Сетевой провайдер");
Создайте демультиплексор mpeg2, чтобы получить отдельные потоки EPG/Vidoe/Audio/Text из одного ТВ-потока.
_mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer();
_граф.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer");
Теперь мы ищем локальные фильтры для BDA Source Filter, в моем случае это IT9135 BDA Fitler
DsDevice[] devicesOfCat =
DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory);
IBaseFilter iteDeviceFilter;
_graph.AddSourceFilterForMoniker(
devicesOfCat[0].Mon, null, devicesOfCat[0].Name, из iteDeviceFilter);
Теперь подключите фильтры: [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 в dsDevices)
{
фильтр IBaseFilter;
_graph.AddSourceFilterForMoniker(
dsDevice.Mon, null, dsDevice.Name, выходной фильтр);
if(dsDevice.Name == "Фильтр транспортной информации BDA MPEG2")
_bdaTIF = фильтр;
else if(dsDevice.Name == "Разделы и таблицы MPEG-2")
{
_mpeg2SectionsAndTables = фильтр;
}
UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, filter);
}
Теперь демультиплексор подключен как к Разделам и таблицам MPEG-2
, так и к Фильтру транспортной информации BDA MPEG2
.
Теперь создайте тип видео 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 Video Decoder, способный обрабатывать видео H264 и расположенный в категории DirectShow Filters
(как в GraphStudio
).
DsDevice[] directshowfilters =
DsDevice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory);
IBaseFilter ffdshow = ноль;
foreach (DsDevice directshowfilter в directshowfilters)
{
if(directshowfilter.Name == "Видеодекодер ffdshow")
{
_graph.AddSourceFilterForMoniker(
directshowfilter.Mon, ноль, directshowfilter.Name,
вне ffdshow);
перерыв;
}
}
Создать средство визуализации видео для вывода видео...
_videoRenderer = new VideoRendererDefault();
_graph.AddFilter((IBaseFilter)_videoRenderer, "Обработчик видео");
... и аудио ...
DsDevice defaultDirectSound =
DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0];
_graph.AddSourceFilterForMoniker(
defaultDirectSound.Mon, null, defaultDirectSound.Name,
вне _audioRender);
Здесь я попытался подключить выходной вывод h264 демультиплексора к ffdshow. Вызов этого метода завершается с ошибкой AccessViolationException. Я не уверен, как соединить эти два вместе :(
.
Комментирование этой строки приведет к запуску графика, хотя на графике есть отключенный фильтр ffdshowVideoDecoder, ничего не покажет IntelliConnect подключает видеовыход Mpeg2 к локально доступному видеодекодеру и, как я уже сказал, ничего не отображает.
// UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
ConnectFilters
заимствован из примера DTVViewer библиотеки directshowlib
ConnectFilters();
Я переместил актуальные настройки сюда
tuning.put_TuningSpace(tuningspace);
Tuner.put_TuneRequest (запрос);
запустить график и пожелать, чтобы отображался звук или видео
int hr = (_graph as IMediaControl).Run();
DsError.ThrowExceptionForHR(ч);
проверить, работает ли граф...
FilterState pfs;
hr = (_graph as IMediaControl).GetState(1000, out pfs);
DsError.ThrowExceptionForHR(ч);
и там написано, что граф работает.