【发布时间】:2014-03-04 16:25:17
【问题描述】:
我正在尝试让 MediaFoundation SourceReader 读取 H.264 视频文件,并将帧渲染到某些 Direct3D 纹理,这样我就可以使用 Direct3D 渲染它们。
我用的是SharpDX,但原理当然和native code一样。
据我了解,一般的数据流应该是这样的:
-
SourceReader使用SourceReader.ReadSample()读取和解码视频 -
VideoProcessor(来自IDirect3DDeviceManager9)使用VideoProcessor.VideoProcessBlt()将帧传输到 Direct3D9 表面 - 我的 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);
问题是当我同时设置EnableVideoProcessing 和D3DManager 时CreateSourceReaderFromURL 失败(0x80070057)。 D3DManager reference 暗示了这一点:
如果 [...] 您从源阅读器获取压缩视频,则不会设置此属性。在这种情况下,源阅读器不会创建解码器。
假设我可以稍后解码帧(可能使用VideoDecoder?),我尝试删除EnableVideoProcessing,只留下D3DManager 和DisableDxva,但在这种情况下,失败的是ReadSample(0xC00D36B4 ) 甚至在我有机会使用样本中的数据之前。
那么我应该如何读取、解码并将我的帧发送到 Direct3D 表面?
【问题讨论】:
标签: video direct3d ms-media-foundation sharpdx