You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Media Foundation播放受保护的MP4内容?

使用Media Foundation播放受保护MP4文件的问题求助

我正尝试用Media Foundation播放MP4文件,按照官方文档可以正常播放未受保护的文件,但播放受保护文件时始终失败。根据播放受保护文件的官方文档说明,这类文件需要额外操作才能播放。我使用了微软PlayReady测试页面提供的前两个MP4测试文件(Media Foundation本应兼容微软自有DRM系统),但无论如何调整操作,播放受保护MP4都会报错MF_E_UNSUPPORTED_BYTESTREAM_TYPE。

失败发生在MESessionTopologySet事件触发期间,而且我实现的IMFContentProtectionManager仅在QueryInterface()时被调用过一次。当前环境是Windows 10系统,请问该如何正确使用Media Foundation播放受保护MP4文件?

以下是我使用的代码:

// initialization
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = MFStartup(MF_VERSION);

// load source
IMFSourceResolver* SourceResolver = NULL;
hr = MFCreateSourceResolver(&SourceResolver);
MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
IUnknown* Object = NULL;
hr = SourceResolver->CreateObjectFromURL(L"tearsofsteel_1080p_60s_24fps.6000kbps.1920x1080.h264-8b.2ch.128kbps.aac.avsep.cenc.mp4", MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_READ, NULL, &ObjectType, &Object);
IMFMediaSource* MediaSource = NULL;
hr = Object->QueryInterface(&MediaSource);
IMFPresentationDescriptor* PresentationDescriptor = NULL;
hr = MediaSource->CreatePresentationDescriptor(&PresentationDescriptor);
hr = MFRequireProtectedEnvironment(PresentationDescriptor);
wprintf_s(L"MFRequireProtectedEnvironment() hr=0x%.08X\n", hr);

// get first stream
IMFStreamDescriptor* StreamDescriptor = NULL;
BOOL Selected = FALSE;
hr = PresentationDescriptor->GetStreamDescriptorByIndex(0, &Selected, &StreamDescriptor);
IMFMediaTypeHandler* MediaTypeHandler = NULL;
hr = StreamDescriptor->GetMediaTypeHandler(&MediaTypeHandler);
GUID MajorType = GUID_NULL;
hr = MediaTypeHandler->GetMajorType(&MajorType);

// create appropriate renderer
IMFActivate* Activate = NULL;
if (MajorType == MFMediaType_Video)
{
    hr = MFCreateVideoRendererActivate(NULL, &Activate);
}
else if (MajorType == MFMediaType_Audio)
{
    hr = MFCreateAudioRendererActivate(&Activate);
}

// build the topology
IMFTopology* Topology = NULL;
hr = MFCreateTopology(&Topology);

// build the source node
IMFTopologyNode* SourceTopologyNode = NULL;
hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &SourceTopologyNode);
hr = SourceTopologyNode->SetUnknown(MF_TOPONODE_SOURCE, MediaSource);
hr = SourceTopologyNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, PresentationDescriptor);
hr = SourceTopologyNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, StreamDescriptor);
hr = Topology->AddNode(SourceTopologyNode);

// build the output node
IMFTopologyNode* OutputTopologyNode = NULL;
hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &OutputTopologyNode);
hr = OutputTopologyNode->SetObject(Activate);
hr = OutputTopologyNode->SetUINT32(MF_TOPONODE_STREAMID, 0);
hr = OutputTopologyNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
hr = Topology->AddNode(OutputTopologyNode);
hr = SourceTopologyNode->ConnectOutput(0, OutputTopologyNode, 0);

// create the protected session
IMFMediaSession* MediaSession = NULL;
IMFAttributes* Configuration = NULL;
hr = MFCreateAttributes(&Configuration, 1);
IUnknown* ContentProtectionManager = new ContentProtectionManagerImpl();
Configuration->SetUnknown(MF_SESSION_CONTENT_PROTECTION_MANAGER, ContentProtectionManager);
IMFActivate* EnablerActivate = NULL;
hr = MFCreatePMPMediaSession(0, Configuration, &MediaSession, &EnablerActivate);

// set the topology
hr = MediaSession->SetTopology(0, Topology);

// get the event status
IMFMediaEvent* Event = NULL;
hr = MediaSession->GetEvent(0, &Event);
MediaEventType Type = MEUnknown;
hr = Event->GetType(&Type);
HRESULT Status = S_OK;
hr = Event->GetStatus(&Status);
wprintf_s(L"Event Type=%d Status=0x%.08X\n", Type, Status);

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:35:04