Trascorro molto tempo a cercare di rendere sfortunatamente l'esempio di DirectShow di DTVViewer senza successo. Il formato video della rete DVBT è H264 e ho scoperto che il comportamento di IntelliConnect di IFilterGraph
preferisce utilizzare il formato video Mpeg2.Forzare Mpeg2Demultiplexer a utilizzare ffdshow per eseguire il rendering del video TV digitale H264
Per coloro che vogliono vedere il codice, eccolo. Se non sai nulla di DirectShow ho condiviso la mia esperienza con questo codice. E il problema più probabile è descritto in passaggio 5 e 6 del tutorial.
Il codice per la funzione di supporto che collega filtri:
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 { } } } }
Qualcuno sa su:
- Come devo collegare il perno h264 di ffdshow?
- Come dovrei consigliare il grafico per utilizzare la decodifica video h264?
Tutorial e dettagli
Creare il grafico
_graph = (IFilterGraph2)new FilterGraph();
Stiamo utilizzando rete DVBT
01.235.IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
... che deve essere sintonizzato 602000KHz @ 8 MHz ONID = 1 IDST = 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");
Creare un demux MPEG2 per ottenere separati EPG/Vidoe/Audio/Testo flussi fuori Stream TV singolo
_mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer(); _graph.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer");
Ora cerchiamo filtri locali per BDA Fonte filtro che nel mio caso è
IT9135 BDA Fitler
DsDevice[] devicesOfCat = DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory); IBaseFilter iteDeviceFilter; _graph.AddSourceFilterForMoniker( devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter);
ora connettersi filtri:
[DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...
UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter); UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);
Due filtri devono essere collegati a demux, per fornire EPG (dati della guida del programma). scusate, non so cosa siano specificamente doig
:P
. Si trovano sotto la categoriaBDATransportInformationRenderersCategory
. Cerchiamo di trovarli per nome e collegarli demuxDsDevice[] 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); }
Ora demux è collegato sia
MPEG-2 Sections and Tables
eBDA MPEG2 Transport Information Filter
.Ora creare tipo di video H264 e aggiungere l'uscita un pin di uscita demux per questo 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);
Qui di seguito, ho provato a cercare ffdshow Video Decoder che è in grado di elaborare il video H264 ed è situato sotto la categoria
DirectShow Filters
(come inGraphStudio
).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; } }
Creare un renderer video per l'uscita video ...
_videoRenderer = new VideoRendererDefault(); _graph.AddFilter((IBaseFilter)_videoRenderer, "Video Renderer");
... e audio ...
DsDevice defaultDirectSound = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0]; _graph.AddSourceFilterForMoniker( defaultDirectSound.Mon, null, defaultDirectSound.Name, out _audioRender);
Qui ho cercato di collegare il pin di uscita H264 di demux a ffdshow. Questa chiamata al metodo ha esito negativo con AccessViolationException. Non sono sicuro di come collegare questi due insieme
:(
.Commentando questa riga si otterrà un grafico che inizia a funzionare, sebbene nel grafico sia presente un filtro ffdshowVideoDecoder disconnesso, non verrà mostrato nulla. IntelliConnect collega l'uscita video Mpeg2 a un decodificatore video disponibile localmente e, come ho detto, non mostrerà nulla.
// UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
ConnectFilters
è preso da DTVViewer campione di directshowlibConnectFilters();
mi sono trasferito sintonizzazione reale qui
tuner.put_TuningSpace(tuningspace); tuner.put_TuneRequest(request);
avviare il grafico e desiderare un suono o un video da visualizzare
int hr = (_graph as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr);
verifica che il grafico è in funzione ...
FilterState pfs; hr = (_graph as IMediaControl).GetState(1000, out pfs); DsError.ThrowExceptionForHR(hr);
e si dice che il grafico è in esecuzione.
... E direi che sto usando Windows XP :) – Bakhshi
Puoi creare manualmente il grafico usando GraphEdit? In tal caso, includi il grafico manuale come screenshot. – Odys
@odyodyodys Non lavoro più su quel progetto. ma non ero in grado di creare il grafico usando solo GraphEdit. Richiede molte configurazioni di porte che sono impossibili in GE. Finalmente ho usato il componente TeamMediaPortal che l'ho estratto dai codici sorgente. – Bakhshi