我正在使用 Windows Media Foundation 播放 mp3 檔案并嘗試設定音量,但是當我嘗試獲取 IMFSimpleAudioVolume 介面時,它需要進行看似隨機的嘗試。我有 1 到 200 次嘗試。我嘗試使用 IMFAudioStreamVolume 但結果相同
這是main.cpp
#include <iostream>
#include <windows.h>
#include <mfapi.h>
#include <mfidl.h>
#include <winrt/base.h>
#pragma comment (lib, "Mfplat.lib")
#pragma comment (lib, "Mfuuid.lib")
#pragma comment (lib, "Mf.lib")
#pragma comment (lib, "Winmm.lib")
template <class T>
using comptr = winrt::com_ptr<T>;
void AddBranchToTopology(comptr<IMFTopology> topology, comptr<IMFMediaSource> mediaSource, comptr<IMFPresentationDescriptor> presentationDesc);
int main()
{
MFStartup(MF_VERSION);
HRESULT hr = S_OK;
comptr<IMFMediaSession> mediaSession;
hr = MFCreateMediaSession(NULL, mediaSession.put());
comptr<IMFSourceResolver> sourceResolver;
MFCreateSourceResolver(sourceResolver.put());
comptr<IMFMediaSource> mediaSource;
MF_OBJECT_TYPE objType = MF_OBJECT_INVALID;
{
comptr<IUnknown> unknown;
hr = sourceResolver->CreateObjectFromURL(L"<file path>",
MF_RESOLUTION_MEDIASOURCE, NULL, &objType, unknown.put());
mediaSource = unknown.as<IMFMediaSource>();
unknown.detach();
}
comptr<IMFPresentationDescriptor> presentationDesc;
hr = mediaSource->CreatePresentationDescriptor(presentationDesc.put());
comptr<IMFTopology> topology;
hr = MFCreateTopology(topology.put());
AddBranchToTopology(topology, mediaSource, presentationDesc);
mediaSession->SetTopology(NULL, topology.get());
comptr<IMFSimpleAudioVolume> simpleVolume;
DWORD tries = 0;
while (!simpleVolume)
{
hr = MFGetService(mediaSession.get(), MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(simpleVolume.put()));
tries ;
}
std::cout << tries << "\n";
PROPVARIANT var;
PropVariantInit(&var);
var.vt = VT_EMPTY;
mediaSession->Start(&GUID_NULL, &var);
simpleVolume->SetMasterVolume(0.5f);
while (true)
{
if (GetAsyncKeyState(VK_ESCAPE) & 1)
{
break;
}
}
mediaSession->Shutdown();
mediaSource->Shutdown();
MFShutdown();
return 0;
}
void AddBranchToTopology(comptr<IMFTopology> topology, comptr<IMFMediaSource> mediaSource, comptr<IMFPresentationDescriptor> presentationDesc)
{
comptr<IMFStreamDescriptor> streamDesc;
comptr<IMFTopologyNode> sourceNode;
comptr <IMFTopologyNode> outputNode;
comptr<IMFActivate> activate;
BOOL selected = FALSE;
HRESULT hr = S_OK;
hr = presentationDesc->GetStreamDescriptorByIndex(0, &selected, streamDesc.put());
hr = MFCreateAudioRendererActivate(activate.put());
hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, sourceNode.put());
hr = sourceNode->SetUnknown(MF_TOPONODE_SOURCE, mediaSource.get());
hr = sourceNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, presentationDesc.get());
hr = sourceNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, streamDesc.get());
hr = topology->AddNode(sourceNode.get());
hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, outputNode.put());
hr = outputNode->SetObject(activate.get());
hr = outputNode->SetUINT32(MF_TOPONODE_STREAMID, 0);
hr = outputNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
hr = topology->AddNode(outputNode.get());
hr = sourceNode->ConnectOutput(0, outputNode.get(), 0);
activate->ShutdownObject();
}
uj5u.com熱心網友回復:
IMFMediaSession::SetTopology 是異步的,因此您需要在請求服務之前進行同步。
此方法是異步的。如果該方法回傳 S_OK,則媒體會話會在操作完成時發送 MESessionTopologySet 事件。
mediaSession->SetTopology(NULL, topology.get());
// INSERT BEGIN //
// https://docs.microsoft.com/en-us/windows/win32/medfound/mesessiontopologyset
auto const MediaEventGenerator = mediaSession.as<IMFMediaEventGenerator>();
for(; ; )
{
winrt::com_ptr<IMFMediaEvent> MediaEvent;
winrt::check_hresult(MediaEventGenerator->GetEvent(0, MediaEvent.put()));
MediaEventType Type;
winrt::check_hresult(MediaEvent->GetType(&Type));
//std::cout << Type << std::endl;
if(Type == MESessionTopologySet)
break;
}
// INSERT END //
comptr<IMFSimpleAudioVolume> simpleVolume;
這只是為了說明,在實際代碼中,您可能希望訂閱事件并異步處理(參見例如Media Foundation 示例)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/418331.html
標籤:
上一篇:VirtualProtect中的最后一個引數是做什么用的?
下一篇:滾動條重復winapic
