gpt4 book ai didi

c# - 强制 Mpeg 2 解复用器使用 ffdshow 渲染 H 264 数字电视视频

转载 作者:IT王子 更新时间:2023-10-29 04:31:42 31 4
gpt4 key购买 nike

不幸的是,我花了很多时间尝试使 DirectShow 的 DTVViewer 示例正常工作,但没有成功。 DVBT 网络的视频格式是 H264,我发现 IFilterGraph 的 IntelliConnect 行为更喜欢使用 Mpeg2 视频格式。

对于那些想看代码的人,就在这里。如果您对 DirectShow 一无所知,我分享了我使用这段代码的经验。本教程的第 5 步和第 6 步中描述了最有可能的问题。

  • 连接过滤器的辅助函数代码:

    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 {
    }

    }
    }
    }

有没有人知道:

  1. 我应该如何将 h264 引脚连接到 ffdshow?
  2. 我应该如何推荐图表使用 h264 视频解码?

  • 教程和详情

    1. 创建图表

      _graph = (IFilterGraph2)new FilterGraph();
    2. 我们正在使用 DVBT 网络

      IBaseFilter networkProvider = (IBaseFilter) new DVBTNetworkProvider();

      ... 必须调到 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. 创建 mpeg2 解复用器以从单个电视流中获取单独的 EPG/视频/音频/文本流

      _mpeg2Demultiplexer = (IBaseFilter) new MPEG2Demultiplexer();
      _graph.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, out iteDeviceFilter);
    4. 现在连接过滤器:[DVBT Net. Provider]->[BDA Src Filter]->[MPEG2Demux]-> ...

      UnsafeConnectFilters(_graph, networkProvider, iteDeviceFilter);
      UnsafeConnectFilters(_graph, iteDeviceFilter, _mpeg2Demultiplexer);

      两个过滤器必须连接到解复用器,以提供 epg(节目指南数据)。抱歉,我不知道它们具体是什么 doig :P。它们位于 BDATransportInformationRenderersCategory 类别下。我们尝试通过名称找到它们并将它们连接到 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);
      }

      现在 demux 连接到 MPEG-2 Sections and TablesBDA MPEG2 Transport Information Filter

    5. 现在创建 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);

      下面,我尝试搜索能够处理 H264 视频并位于 DirectShow Filters 类别下的 ffdshow Video Decoder(如 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. 为视频输出创建视频渲染器 ...

      _videoRenderer = new VideoRendererDefault();
      _graph.AddFilter((IBaseFilter)_videoRenderer, "Video Renderer");

      ...和音频...

      DsDevice defaultDirectSound = 
      DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory)[0];

      _graph.AddSourceFilterForMoniker(
      defaultDirectSound.Mon, null, defaultDirectSound.Name,
      out _audioRender);

      这里我尝试将 demux 的 h264 输出引脚连接到 ffdshow。此方法调用因 AccessViolationException 而失败。我不确定如何将这两者连接在一起 :(

      注释此行将导致图表开始运行,尽管图表中有断开连接的 ffdshowVideoDecoder 过滤器,但不会显示任何内容。 IntelliConnect 将 Mpeg2 视频输出连接到本地可用的视频解码器,正如我所说,它不会显示任何内容。

      // UnsafeConnectFilters(_graph, _mpeg2Demultiplexer, ffdshow, type => type.majorType == MediaType.Video && type.subType == MediaSubType.H264);
    7. ConnectFilters 借鉴了 directshowlib 的 DTVViewer 示例

      ConnectFilters();

      我把实际调音移到了这里

      tuner.put_TuningSpace(tuningspace);
      tuner.put_TuneRequest(request);
    8. 启动图形并希望显示一些声音或视频

      int hr = (_graph as IMediaControl).Run();
      DsError.ThrowExceptionForHR(hr);
    9. 检查图表是否正在运行......

      FilterState pfs;
      hr = (_graph as IMediaControl).GetState(1000, out pfs);
      DsError.ThrowExceptionForHR(hr);

      它表示图形正在运行。

最佳答案

您是否检查过您的 ffdshow 是否启用了 H264/AVC?打开过滤器属性,在“编解码器”部分,应启用 H264/AVC 格式(您也可以禁用 Mpeg2 解码器,以确保它不喜欢这种格式)。

另外,您可以尝试使用另一个 Mpeg2 解复用器。默认的“MPEG-2 解复用器”在不同的环境中表现不同。还有许多其他过滤器可以解复用 TS,如果您可以投资一些钱,我建议您使用 MainConcept 或 Elecard。

关于c# - 强制 Mpeg 2 解复用器使用 ffdshow 渲染 H 264 数字电视视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11201638/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com