Reputation: 27
I am playing a mp3 file with windows media foundation and try to set the volume but when i try to get IMFSimpleAudioVolume interface it takes a seemingly random amount of tries to do so. I have got 1 through 200ish tries. I tried using IMFAudioStreamVolume but the results are the same
Here is the 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();
}
Upvotes: 1
Views: 295
Reputation: 69642
IMFMediaSession::SetTopology
is asynchronous, so you'd want to sync before asking for service.
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://learn.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;
This is just for illustration, in real code you would want to subscribe to events and handle asynchronously (see e.g. Media Foundation samples).
Upvotes: 2