如何获取SourceReader来解压缩帧并将其发送到Direct3D9纹理? [英] How to get a SourceReader to decompress frames and send them to a Direct3D9 texture?

查看:93
本文介绍了如何获取SourceReader来解压缩帧并将其发送到Direct3D9纹理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图获得MediaFoundation SourceReader来读取H.264视频文件,并将帧渲染为某些Direct3D纹理,以便我可以使用Direct3D随意渲染它们.

I am trying to get a MediaFoundation SourceReader to read an H.264 video file, and render the frames to some Direct3D textures so I can them render them as I wish with Direct3D.

我正在使用SharpDX,但是原理当然与本机代码相同.

I'm using SharpDX, but the principles are of course the same as native code.

据我了解,一般数据流应如下所示:

As I understand it, the general data flow should be like this:

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

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

If this is how it's supposed to work, I've pretty much have it figured out, and almost running.

在创建我的 SourceReader 时,通过设置 EnableVideoProcessing ,我能够将帧从H.264解码为X8R8G8B8:

I was able to decode frames from H.264 to X8R8G8B8 by setting EnableVideoProcessing when I created my SourceReader:

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

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

And by setting the media type subtype to the X8R8G8B8 GUID for the video stream:

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()时,我正在获取视频和音频样本,因此我认为解码过程可以正常工作.

Later, when I call ReadSample(), I am getting video and audio samples, so I think the decoding process is working fine.

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

However, in order to get VideoProcessor-compatible frames, I need to create my SourceReader, setting the D3DManager on the media attributes, and also make sure DXVA is not disabled:

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

问题在于,当我同时设置 EnableVideoProcessing D3DManager 时, CreateSourceReaderFromURL 失败(0x80070057).这由 D3DManager 参考:

The problem is that CreateSourceReaderFromURL fails (0x80070057) when I set both EnableVideoProcessing and D3DManager. This is implied by the D3DManager reference:

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

You would not set this attribute if [...] you are getting compressed video from the source reader. In that case, the source reader does not create a decoder.

假设我以后可以解码帧(也许使用 VideoDecoder ?),我尝试删除 EnableVideoProcessing 并只留下 D3DManager DisableDxva ,但在这种情况下, ReadSample 失败了(0xC00D36B4),甚至在我没有机会使用示例中的数据之前.

Supposing I could decode the frames later (perhaps with a VideoDecoder?), I tried removing EnableVideoProcessing and just leave D3DManager and DisableDxva, but in that case, it's ReadSample that fails (0xC00D36B4) even before I get a chance to use the data in the sample.

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

So how am I supposed to read, decode and send my frames to the Direct3D surface?

推荐答案

我没有使用SharpDX,但是在本机D3D中,如果要使用DXVA解码视频,则应该将 MF_SOURCE_READER_DISABLE_DXVA 设置为false并启用 MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING 而不是 MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING .也许您可以尝试一下.

I haven't use SharpDX, but in native D3D, if you want to decode video with DXVA, you should set MF_SOURCE_READER_DISABLE_DXVA to false and enable MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING instead of MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING. Maybe you can try it.

这篇关于如何获取SourceReader来解压缩帧并将其发送到Direct3D9纹理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆