2012-06-26 33 views
22

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ề:

  1. Làm thế nào tôi nên kết nối pin h264 để ffdshow?
  2. 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

    1. Tạo đồ thị

      _graph = (IFilterGraph2)new FilterGraph(); 
      
    2. 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"); 
      
    3. 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); 
      
    4. 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ục BDATransportInformationRenderersCategory. 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 Demux

      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); 
      } 
      

      Bây giờ demux được kết nối với cả hai MPEG-2 Sections and TablesBDA MPEG2 Transport Information Filter.

    5. 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ư trong 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; 
          } 
      } 
      
    6. 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); 
      
    7. ConnectFilters được vay mượn từ DTVViewer mẫu directshowlib

      ConnectFilters(); 
      

      tôi chuyển điều chỉnh thực tế đây

      tuner.put_TuningSpace(tuningspace); 
      tuner.put_TuneRequest(request); 
      
    8. 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); 
      
    9. 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.

+0

... Và tôi nên nói rằng tôi đang sử dụng Windows XP :) – Bakhshi

+0

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

+0

@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

Trả lời

1

Bạn có kiểm tra xem ffdshow của bạn được kích hoạt cho H264/AVC? Mở thuộc tính bộ lọc và Trong phần "Codecs", định dạng H264/AVC sẽ được bật (bạn cũng có thể tắt trình giải mã Mpeg2 chỉ để đảm bảo rằng nó không thích định dạng này).

Một điều khác, bạn có thể thử sử dụng bộ tách kênh Mpeg2 khác. Mặc định "MPEG-2 Demultiplexer" không hoạt động giống nhau trên các môi trường khác nhau. Có rất nhiều bộ lọc khác có thể demux TS và nếu bạn có thể đầu tư một số tiền, tôi khuyên bạn nên sử dụng MainConcept hoặc Elecard.

+0

cảm ơn bạn đã ghé qua. Yeah H262 đã được kích hoạt trong thuộc tính ffdshow. Về cách sử dụng các demuxes khác, tôi không chắc chắn nếu tôi thử nghiệm chúng hay không. nó đã được một thời gian. anyway, nếu bạn có bất cứ điều gì đang chạy, bạn có thể chia sẻ kinh nghiệm của bạn ở đây để những người khác có thể học được điều gì đó từ nó? cảm ơn – Bakhshi

Các vấn đề liên quan