Paso mucho tiempo tratando de hacer que la muestra de DTVViewer de DirectShow funcione desafortunadamente sin éxito. El formato de video de la red DVBT es H264 y encontré que el comportamiento de IntelliConnect de IFilterGraph
prefiere usar el formato de video Mpeg2.Cómo forzar a Mpeg2Demultiplexer a usar ffdshow para procesar H264 Digital TV Video
Para aquellos que quieren ver el código, aquí está. Si no sabe nada sobre DirectShow, compartí mi experiencia con este código. Y el problema más probable se describe en paso 5 y 6 del tutorial.
El código de función auxiliar que conecta filtros:
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 { } } } }
¿Alguien sabe acerca de:
- ¿Cómo debo conectar la clavija h264 a ffdshow?
- ¿Cómo debo recomendar el gráfico para usar la decodificación de video h264?
Tutorial y detalles
Crear el gráfico
_graph = (IFilterGraph2)new FilterGraph();
Estamos utilizando la red DVB-T
IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
... que debe ser sintonizado a 602000KHz @ 8 MHz ONID = 1 = 1 TSID 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");
Crear un demux MPEG2 para obtener por separado EPG/Vidoe/audio/texto fluye hacia fuera de TV de simple flujo
_mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer(); _graph.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer");
Ahora que sus resultados de búsqueda locales para BDA Fuente de filtro que en mi caso es
IT9135 BDA Fitler
DsDevice[] devicesOfCat = DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory); IBaseFilter iteDeviceFilter; _graph.AddSourceFilterForMoniker( devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter);
Ahora conectar filtros:
[DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...
UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter); UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);
Dos filtros deben estar conectados a demux, para proporcionar datos de la guía EPG (programa). lo siento, no sé lo que son específicamente doig
:P
. Están ubicados en la categoríaBDATransportInformationRenderersCategory
. Tratamos de encontrar por su nombre y conectarlos a demultiplexarDsDevice[] 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); }
Ahora demux está conectado tanto
MPEG-2 Sections and Tables
yBDA MPEG2 Transport Information Filter
.Ahora crea tipo de vídeo H264 y añadir la salida de un pin de salida demultiplexar para este tipo
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);
A continuación, traté de buscar ffdshow decodificador de vídeo que es capaz de procesar vídeo H264 y está ubicado en la categoría
DirectShow Filters
(como enGraphStudio
).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; } }
Crear un procesador de vídeo para salida de vídeo ...
_videoRenderer = new VideoRendererDefault(); _graph.AddFilter((IBaseFilter)_videoRenderer, "Video Renderer");
... y audio ...
DsDevice defaultDirectSound = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0]; _graph.AddSourceFilterForMoniker( defaultDirectSound.Mon, null, defaultDirectSound.Name, out _audioRender);
Aquí me trataron de conectar el pin de salida h264 de demux a ffdshow. Esta llamada a método falla con AccessViolationException. No estoy seguro de cómo conectar estos dos juntos
:(
.Al comentar esta línea aparecerá un gráfico que se iniciará, aunque hay un filtro ffdshowVideoDecoder desconectado en el gráfico, no se mostrará nada. IntelliConnect conecta la salida de video Mpeg2 a un decodificador de video disponible localmente y como dije no mostrará nada.
// UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
ConnectFilters
es tomada de la muestra DTVViewer de directshowlibConnectFilters();
me moví de sintonización real aquí
tuner.put_TuningSpace(tuningspace); tuner.put_TuneRequest(request);
iniciar la gráfica y el deseo de algún sonido o vídeo que se mostrará
int hr = (_graph as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr);
cheque que el gráfico está en marcha ...
FilterState pfs; hr = (_graph as IMediaControl).GetState(1000, out pfs); DsError.ThrowExceptionForHR(hr);
y se dice que el gráfico está en marcha.
... Y mejor diré que estoy usando Windows XP :) – Bakhshi
¿Puedes crear el gráfico manualmente usando GraphEdit? De ser así, incluya el gráfico manual como captura de pantalla. – Odys
@odyodyodys Ya no trabajo en ese proyecto. pero no pude crear el gráfico usando solo GraphEdit. Requiere mucha configuración de puertos que es imposible en GE. Finalmente utilicé el componente TeamMediaPortal que extraje de los códigos fuente. – Bakhshi