Tôi dành nhiều thời gian cố gắng làm cho mẫu DTVViewer của công việc DirectShow tiếc là không thành công. Định dạng video của mạng DVBT là H264 và tôi thấy rằng hành vi IntelliConnect của IFilterGraph
thích sử dụng định dạng Video Mpeg2 hơn.Buộc Mpeg2Demultiplexer sử dụng ffdshow để hiển thị Video kỹ thuật số H264 Video
Đối với những người muốn xem mã, tại đây. Nếu bạn không biết bất cứ điều gì về DirectShow tôi chia sẻ kinh nghiệm của tôi với mã này. Và vấn đề có lẽ nhất là được mô tả trong bước 5 và 6 của hướng dẫn.
Mã cho chức năng helper nối bộ lọc:
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 { } } } }
Có ai biết về:
- Làm thế nào tôi nên kết nối pin h264 để ffdshow?
- Tôi nên sử dụng biểu đồ để sử dụng giải mã video h264 như thế nào?
Hướng dẫn và chi tiết
Tạo đồ thị
_graph = (IFilterGraph2)new FilterGraph();
Chúng tôi đang sử dụng mạng DVBT
01.235.IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();
... mà phải được điều chỉnh để 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");
Tạo một demux mpeg2 để có được riêng EPG/vidoe/Audio/Tiêu suối ra khỏi đơn dòng TV
_mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer(); _graph.AddFilter(_mpeg2Demultiplexer, "MPEG-2 Demultiplexer");
Bây giờ chúng ta tìm kiếm các bộ lọc địa phương cho BDA Nguồn Lọc mà trong trường hợp của tôi là
IT9135 BDA Fitler
DsDevice[] devicesOfCat = DsDevice.GetDevicesOfCat(FilterCategory.BDASourceFiltersCategory); IBaseFilter iteDeviceFilter; _graph.AddSourceFilterForMoniker( devicesOfCat[0].Mon, null, devicesOfCat[0].Name, out iteDeviceFilter);
Bây giờ kết nối bộ lọc:
[DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...
UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter); UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);
Hai bộ lọc phải được kết nối với Demux, để cung cấp EPG (dữ liệu hướng dẫn chương trình). xin lỗi tôi không biết những gì họ đặc biệt là doig
:P
. Chúng được đặt dưới danh mụcBDATransportInformationRenderersCategory
. Chúng tôi cố gắng để tìm thấy chúng bằng tên và kết nối chúng với 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); }
Bây giờ demux được kết nối với cả hai
MPEG-2 Sections and Tables
vàBDA MPEG2 Transport Information Filter
.Bây giờ tạo loại video h264 và thêm đầu ra một pin ra để demux cho loại hình này
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);
Dưới đây, tôi đã cố gắng để tìm kiếm ffdshow Video Decoder đó là khả năng xử lý video H264 và là nằm dưới danh mục
DirectShow Filters
(như trongGraphStudio
).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; } }
Tạo một renderer video cho đầu ra video ...
_videoRenderer = new VideoRendererDefault(); _graph.AddFilter((IBaseFilter)_videoRenderer, "Video Renderer");
... và âm thanh ...
DsDevice defaultDirectSound = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0]; _graph.AddSourceFilterForMoniker( defaultDirectSound.Mon, null, defaultDirectSound.Name, out _audioRender);
Ở đây tôi cố gắng kết nối h264 pin ra của demux để ffdshow. Cuộc gọi phương thức này không thành công với AccessViolationException. Tôi không chắc chắn cách kết nối hai thiết bị này với nhau
:(
.Nhận xét dòng này sẽ dẫn đến biểu đồ bắt đầu chạy, mặc dù có bộ lọc ffdshowVideoDecoder bị ngắt kết nối trong biểu đồ, sẽ không hiển thị bất kỳ thứ gì. IntelliConnect kết nối đầu ra video Mpeg2 với bộ giải mã video có sẵn cục bộ và như tôi đã nói, nó sẽ không hiển thị bất cứ thứ gì.
// UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
ConnectFilters
được vay mượn từ DTVViewer mẫu directshowlibConnectFilters();
tôi chuyển điều chỉnh thực tế đây
tuner.put_TuningSpace(tuningspace); tuner.put_TuneRequest(request);
bắt đầu đồ thị và chúc cho một số âm thanh hoặc video sẽ được hiển thị
int hr = (_graph as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr);
kiểm tra rằng đồ thị đang chạy ...
FilterState pfs; hr = (_graph as IMediaControl).GetState(1000, out pfs); DsError.ThrowExceptionForHR(hr);
và nó nói rằng đồ thị đang chạy.
... Và tôi nên nói rằng tôi đang sử dụng Windows XP :) – Bakhshi
Bạn có thể tạo biểu đồ theo cách thủ công bằng GraphEdit không? Nếu có, vui lòng bao gồm biểu đồ thủ công làm ảnh chụp màn hình. – Odys
@odyodyodys Tôi không còn làm việc với dự án đó nữa. nhưng tôi không thể tạo biểu đồ bằng GraphEdit. Nó đòi hỏi rất nhiều cấu hình cổng mà là không thể trong GE. Cuối cùng tôi đã sử dụng thành phần TeamMediaPortal mà tôi trích xuất nó ra khỏi mã nguồn. – Bakhshi