如何获取SourceReader来解压缩帧并将其发送到Direct3D9纹理? [英] How to get a SourceReader to decompress frames and send them to a Direct3D9 texture?
问题描述
我试图获得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:
-
SourceReader
使用SourceReader.ReadSample()
读取和解码视频 -
VideoProcessor
(来自IDirect3DDeviceManager9
)使用VideoProcessor.VideoProcessBlt()
将帧传输到Direct3D9表面 - 我的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屋!