如何让SourceReader解压缩帧并将它们发送到Direct3D9纹理?

时间:2014-02-07 10:03:54

标签: video direct3d ms-media-foundation sharpdx

我正在尝试使用MediaFoundation SourceReader来读取H.264视频文件,并将帧渲染为一些Direct3D纹理,以便我可以使用Direct3D渲染它们。

我正在使用SharpDX,但其原则当然与本机代码相同。

据我了解,一般数据流应该是这样的:

  1. SourceReader使用SourceReader.ReadSample()
  2. 读取和解码视频
  3. VideoProcessor(来自IDirect3DDeviceManager9)使用VideoProcessor.VideoProcessBlt()
  4. 将框架转移到Direct3D9表面
  5. 我的Direct3D9渲染器使用曲面渲染帧,但我想要在屏幕上
  6. 如果这是它应该如何运作的话,我几乎已经弄明白了,差不多了。

    当我创建EnableVideoProcessing时,我能够通过设置SourceReader来解码从H.264到X8R8G8B8的帧:

    MediaFactory.CreateAttributes(mediaAttributes, 0);
    mediaAttributes.Set(SourceReaderAttributeKeys.EnableVideoProcessing, 1);
    MediaFactory.CreateSourceReaderFromURL(url, mediaAttributes, SourceReader);
    

    通过将媒体类型子类型设置为视频流的X8R8G8B8 GUID:

    VideoSubType = currentMediaType.Get<Guid>(MediaTypeAttributeKeys.Subtype);
    UnpackLong(currentMediaType.Get(MediaTypeAttributeKeys.FrameSize), out VideoWidth, out VideoHeight);
    UnpackLong(currentMediaType.Get(MediaTypeAttributeKeys.FrameRate), out VideoFrameRateNumerator, out VideoFrameRateDenominator);
    VideoInterlaceMode = (VideoInterlaceMode)(uint)(currentMediaType.Get(MediaTypeAttributeKeys.InterlaceMode));
    
    MediaFactory.CreateMediaType(outputMediaType);
    outputMediaType.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video);
    outputMediaType.Set(MediaTypeAttributeKeys.Subtype, VideoSubType);
    outputMediaType.Set(MediaTypeAttributeKeys.FrameSize.Guid, PackLong(VideoWidth, VideoHeight));
    outputMediaType.Set(MediaTypeAttributeKeys.FrameRate.Guid, PackLong(VideoFrameRateNumerator, VideoFrameRateDenominator));
    outputMediaType.Set(MediaTypeAttributeKeys.InterlaceMode.Guid, VideoInterlaceMode);
    outputMediaType.Set(MediaTypeAttributeKeys.PixelAspectRatio.Guid, PackLong(1, 1));
    
    SourceReader.SetCurrentMediaType(streamIndex, outputMediaType);
    

    稍后,当我拨打ReadSample()时,我会收到视频和音频样本,所以我认为解码过程运行正常。

    但是,为了获得VideoProcessor兼容的帧,我需要创建SourceReader,在媒体属性上设置D3DManager,并确保未禁用DXVA:

    mediaAttributes.Set(SourceReaderAttributeKeys.D3DManager, VideoConnector.GetManager());
    mediaAttributes.Set(SourceReaderAttributeKeys.DisableDxva, 0);
    

    当我同时设置CreateSourceReaderFromURLEnableVideoProcessing时,问题是D3DManager失败(0x80070057)。 D3DManager reference

    暗示了这一点
      

    如果您从源阅读器获取压缩视频,则不会设置此属性。在这种情况下,源阅读器不会创建解码器。

    假设我可以稍后解码这些帧(可能是VideoDecoder?),我尝试删除EnableVideoProcessing并离开D3DManagerDisableDxva,但在这种情况下,即使在我有机会使用样本中的数据之前,它的ReadSample也会失败(0xC00D36B4)。

    那么我应该如何读取,解码并将我的帧发送到Direct3D表面?

2 个答案:

答案 0 :(得分:0)

请查看SDK中的MFCaptureToFile示例项目,在那里它配置源阅读器以所需格式输出帧。 ConfigureSourceReader()方法就是这样做的。

答案 1 :(得分:0)

我还没有使用SharpDX,但在原生D3D中,如果你想用DXVA解码视频,你应该 将MF_SOURCE_READER_DISABLE_DXVA设置为false并启用MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING而不是MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING。也许你可以尝试一下。