MFGetService 在第一次尝试时没有获得 IMFSimpleAudioVolume
MFGetService doesnt get IMFSimpleAudioVolume on first try
我正在使用 windows 媒体基础播放一个 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();
}
IMFMediaSession::SetTopology
是异步的,因此您需要在请求服务之前进行同步。
This method is asynchronous. If the method returns S_OK, the Media Session sends an MESessionTopologySet event when the operation completes.
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 samples)。
我正在使用 windows 媒体基础播放一个 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();
}
IMFMediaSession::SetTopology
是异步的,因此您需要在请求服务之前进行同步。
This method is asynchronous. If the method returns S_OK, the Media Session sends an MESessionTopologySet event when the operation completes.
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 samples)。