【问题标题】:How to get a SourceReader to decompress frames and send them to a Direct3D9 texture?如何让 SourceReader 解压缩帧并将它们发送到 Direct3D9 纹理?
【发布时间】:2014-03-04 16:25:17
【问题描述】:

我正在尝试让 MediaFoundation SourceReader 读取 H.264 视频文件,并将帧渲染到某些 Direct3D 纹理,这样我就可以使用 Direct3D 渲染它们。

我用的是SharpDX,但原理当然和native code一样。

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

  1. SourceReader 使用SourceReader.ReadSample() 读取和解码视频
  2. VideoProcessor(来自IDirect3DDeviceManager9)使用VideoProcessor.VideoProcessBlt() 将帧传输到 Direct3D9 表面
  3. 我的 Direct3D9 渲染器使用表面来渲染帧,但我想在屏幕上显示

如果它应该是这样工作的,我几乎已经弄清楚了,并且几乎可以运行了。

当我创建 SourceReader 时,我可以通过设置 EnableVideoProcessing 将帧从 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);

问题是当我同时设置EnableVideoProcessingD3DManagerCreateSourceReaderFromURL 失败(0x80070057)。 D3DManager reference 暗示了这一点:

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

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

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

【问题讨论】:

    标签: video direct3d ms-media-foundation sharpdx


    【解决方案1】:

    请查看 SDK 中的 MFCaptureToFile 示例项目,该项目将源阅读器配置为以所需格式输出帧。 ConfigureSourceReader() 方法可以做到这一点。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-23
        • 2023-03-30
        • 2013-11-21
        • 1970-01-01
        • 1970-01-01
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多