我正在尝试使用MediaFoundation SourceReader来读取H.264视频文件,并将帧渲染为一些Direct3D纹理,以便我可以使用Direct3D渲染它们。
我正在使用SharpDX,但其原则当然与本机代码相同。
据我了解,一般数据流应该是这样的:
SourceReader
使用SourceReader.ReadSample()
VideoProcessor
(来自IDirect3DDeviceManager9
)使用VideoProcessor.VideoProcessBlt()
如果这是它应该如何运作的话,我几乎已经弄明白了,差不多了。
当我创建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);
当我同时设置CreateSourceReaderFromURL
和EnableVideoProcessing
时,问题是D3DManager
失败(0x80070057)。 D3DManager
reference:
如果您从源阅读器获取压缩视频,则不会设置此属性。在这种情况下,源阅读器不会创建解码器。
假设我可以稍后解码这些帧(可能是VideoDecoder
?),我尝试删除EnableVideoProcessing
并离开D3DManager
和DisableDxva
,但在这种情况下,即使在我有机会使用样本中的数据之前,它的ReadSample
也会失败(0xC00D36B4)。
那么我应该如何读取,解码并将我的帧发送到Direct3D表面?
答案 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
。也许你可以尝试一下。