IMFStreamSink::ProcessSample "E_NOINTERFACE No such interface supported" - c++

I'm trying to do a quick and dirty POC. I have a raw H264 file (Not mp4, no container whatsoever, just the raw H264 wrapped in NALU's) to simulate the device my application will ultimately be reading from.
I've been following the Media Foundation Docs. I'm simply reading the H264 file in chunks of 1024 bits using a standard fstream. This just simulated the data getting streamed. From there I'm manually creating IMFSamples and sending them to the decoder. It takes a couple passes to get enough data to fill a frame, but eventually it successfully decodes.
Once I try to pass that off to a IMFStreamSink that I got from the EVR, I get the HRESULT "E_NOINTERFACE No such interface supported" I know that the decompressed sample has data in it. I've used the debugger to confirm. I'm really confused why I'm getting this error as there is no additional data to go along with it.
Here is my code Isolated to the run loop:
while (true) {
// My Loop Stuff
IMFMediaBuffer* inputBuffer = CreateMediaBuffer(1024);
IMFSample* compressedSample = CreateMediaSample(inputBuffer);
if (compressedSample == NULL) {
return 1;
}
BYTE* tempBuff;
DWORD tempMaxLength = 0;
DWORD tempCurrentLength = 0;
hr = inputBuffer->Lock(
&tempBuff,
&tempMaxLength,
&tempCurrentLength
);
if (FAILED(hr)) {
std::cout << "Failed to lock buffer" << std::endl;
return 1;
}
inputTestFile.read((char*)tempBuff, tempMaxLength - tempCurrentLength);
hr = inputBuffer->SetCurrentLength(tempMaxLength - tempCurrentLength);
if (FAILED(hr)) {
std::cout << "Failed to set the lenght of the buffer" << std::endl;
return 1;
}
hr = inputBuffer->Unlock();
if (FAILED(hr)) {
std::cout << "FAILED to unlock buffer!" << std::endl;
return 1;
}
hr = pDecoder->ProcessInput(0, compressedSample, 0);
if (FAILED(hr)) {
std::cout << "Failed sending compressedSample to decoder" << std::endl;
IMFMediaBuffer* outputBuffer = CreateMediaBuffer(streamInfo.cbSize);
IMFSample* decompressedSample = CreateMediaSample(outputBuffer);
_MFT_OUTPUT_DATA_BUFFER outBuff = {};
outBuff.dwStreamID = 0;
outBuff.pSample = decompressedSample;
_MFT_OUTPUT_DATA_BUFFER outBuffs[] = { outBuff };
DWORD outStatus = 0;
hr = pDecoder->ProcessOutput(0, 1, outBuffs, &outStatus);
if (FAILED(hr)) {
std::cout << "FAILED TO PROCESS OUTPUT" << std::endl;
continue;
//return 1;
}
else {
std::cout << "Successfully decoded data!!!" << std::endl;
IMFMediaEvent* mediaEvent = NULL;
ssink->GetEvent(0, &mediaEvent);
if (mediaEvent == NULL) {
// Nothing to do.. Wait for a request for more
continue;
}
hr = ssink->ProcessSample(decompressedSample);
if (FAILED(hr)) {
std::cout << "Failed to process sample to sink" << std::endl;
continue;
}
}
}
// END My Loop Stuff
}
Here is my complete code: (Search for "My Stuff" and "My Loop Stuff" to get around all the boilerplate)
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_H264RENDERINGWINDOW, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_H264RENDERINGWINDOW));
MSG msg;
// My Stuff
HRESULT hr = S_OK;
UINT32 count = 0;
hr = MFStartup(MF_VERSION);
if (FAILED(hr)) {
return 1;
}
IMFActivate** ppActivate = NULL; // Array of activation objects.
IMFTransform* pDecoder = NULL; // Pointer to the decoder.
// Match WMV3 video.
MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, MFVideoFormat_H264 };
UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT |
MFT_ENUM_FLAG_LOCALMFT |
MFT_ENUM_FLAG_SORTANDFILTER;
hr = MFTEnumEx(
MFT_CATEGORY_VIDEO_DECODER,
unFlags,
&info, // Input type
NULL, // Output type
&ppActivate,
&count
);
if (SUCCEEDED(hr) && count == 0)
{
std::cout << "NOT SUCCESS!!!!" << std::endl;
//hr = MF_E_TOPO_CODEC_NOT_FOUND;
return 1;
}
// Create the first decoder in the list.
if (SUCCEEDED(hr))
{
std::cout << "SUCCESS AGAIN!!!" << std::endl;
hr = ppActivate[0]->ActivateObject(IID_PPV_ARGS(&pDecoder));
}
DWORD pcInputStreamsNum = 0;
DWORD pcOutputStreamsNum = 0;
hr = pDecoder->GetStreamCount(
&pcInputStreamsNum,
&pcOutputStreamsNum
);
if (FAILED(hr)) {
std::cout << "Unable to get stream count" << std::endl;
return 1;
}
std::cout << "Available Input Streams: " << pcInputStreamsNum << " Available Output Streams: " << pcOutputStreamsNum << std::endl;
IMFMediaType* pInMediaType = NULL;
hr = MFCreateMediaType(
&pInMediaType
);
if (FAILED(hr)) {
std::cout << "Unable to create Input Media Type" << std::endl;
return 1;
}
hr = pDecoder->GetInputAvailableType(
0,
0,
&pInMediaType
);
if (FAILED(hr)) {
std::cout << "Unable to get Input Media Type for Decoder" << std::endl;
return 1;
}
hr = pDecoder->SetInputType(
0,
pInMediaType,
0
);
if (FAILED(hr)) {
std::cout << "Unable to set Media Type for Decoder" << std::endl;
return 1;
}
IMFMediaType* pOutMediaType = NULL;
hr = MFCreateMediaType(
&pOutMediaType
);
hr = pDecoder->GetOutputAvailableType(0, 0, &pOutMediaType);
if (FAILED(hr)) {
std::cout << "Unable to get output type" << std::endl;
return 1;
}
GUID v;
hr = pOutMediaType->GetGUID(MF_MT_SUBTYPE, &v);
if (FAILED(hr)) {
std::cout << "Unable to get output media sub-type" << std::endl;
return 1;
}
hr = pDecoder->SetOutputType(0, pOutMediaType, 0);
if (FAILED(hr)) {
std::cout << "Failed setting output type" << std::endl;
return 1;
}
hr = pDecoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL);
if (FAILED(hr)) {
std::cout << "Failed to send begin streaming message" << std::endl;
return 1;
}
std::cout << "Successfully Initialized the Decoder..." << std::endl;
std::ifstream inputTestFile = std::ifstream("c:\\open\\fbsource\\arvr\\apps\\MagicIsle\\magic-capture.h264", std::ios::binary);
if (!inputTestFile.is_open()) {
std::cout << "unable to open test input file, did run with --capture previously?"
<< std::endl;
return 1;
}
MFT_INPUT_STREAM_INFO inStreamInfo{};
hr = pDecoder->GetInputStreamInfo(
0,
&inStreamInfo
);
if (FAILED(hr)) {
std::cout << "Failed to get the stream info" << std::endl;
return 1;
}
std::cout << "Stream Info: ";
if (inStreamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES" << std::endl;
}
else if (inStreamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_PROVIDES_SAMPLES" << std::endl;
}
MFT_OUTPUT_STREAM_INFO streamInfo{};
hr = pDecoder->GetOutputStreamInfo(
0,
&streamInfo
);
if (FAILED(hr)) {
std::cout << "Failed to get the stream info" << std::endl;
return 1;
}
std::cout << "Stream Info: ";
if (streamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES" << std::endl;
}
else if (streamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_PROVIDES_SAMPLES" << std::endl;
}
else {
std::cout << "NEITHER" << std::endl;
}
IMFPresentationClock* clock = NULL;
hr = MFCreatePresentationClock(&clock);
if (FAILED(hr)) {
return 1;
}
IMFPresentationTimeSource* timeSource = NULL;
hr = MFCreateSystemTimeSource(&timeSource);
if (FAILED(hr)) {
return 1;
}
hr = clock->SetTimeSource(timeSource);
if (FAILED(hr)) {
return 1;
}
hr = clock->Start(0);
if (FAILED(hr)) {
return 1;
}
hr = pRenderer->SetPresentationClock(clock);
if (FAILED(hr)) {
return 1;
}
DWORD rendererCharacteristics = 0;
hr = pRenderer->GetCharacteristics(&rendererCharacteristics);
if ((rendererCharacteristics & MEDIASINK_CANNOT_MATCH_CLOCK) == MEDIASINK_CANNOT_MATCH_CLOCK) {
std::cout << "Cannot Match Clock" << std::endl;
}
if ((rendererCharacteristics & MEDIASINK_RATELESS) == MEDIASINK_RATELESS) {
std::cout << "Rateless" << std::endl;
}
if (FAILED(hr)) {
return 1;
}
IMFStreamSink* ssink = NULL;
hr = pRenderer->GetStreamSinkById(0, &ssink);
if (FAILED(hr)) {
return 1;
}
IMFMediaTypeHandler* ssinkMediaTypeHandler = NULL;
hr = ssink->GetMediaTypeHandler(&ssinkMediaTypeHandler);
if (FAILED(hr)) {
return 1;
}
hr = ssinkMediaTypeHandler->SetCurrentMediaType(pOutMediaType);
// End My Stuff
auto f = [&] {
while (true) {
// My Loop Stuff
IMFMediaBuffer* inputBuffer = CreateMediaBuffer(1024);
IMFSample* compressedSample = CreateMediaSample(inputBuffer);
if (compressedSample == NULL) {
return 1;
}
BYTE* tempBuff;
DWORD tempMaxLength = 0;
DWORD tempCurrentLength = 0;
hr = inputBuffer->Lock(
&tempBuff,
&tempMaxLength,
&tempCurrentLength
);
if (FAILED(hr)) {
std::cout << "Failed to lock buffer" << std::endl;
return 1;
}
inputTestFile.read((char*)tempBuff, tempMaxLength - tempCurrentLength);
hr = inputBuffer->SetCurrentLength(tempMaxLength - tempCurrentLength);
if (FAILED(hr)) {
std::cout << "Failed to set the lenght of the buffer" << std::endl;
return 1;
}
hr = inputBuffer->Unlock();
if (FAILED(hr)) {
std::cout << "FAILED to unlock buffer!" << std::endl;
return 1;
}
hr = pDecoder->ProcessInput(0, compressedSample, 0);
if (FAILED(hr)) {
std::cout << "Failed sending compressedSample to decoder" << std::endl;
IMFMediaBuffer* outputBuffer = CreateMediaBuffer(streamInfo.cbSize);
IMFSample* decompressedSample = CreateMediaSample(outputBuffer);
_MFT_OUTPUT_DATA_BUFFER outBuff = {};
outBuff.dwStreamID = 0;
outBuff.pSample = decompressedSample;
_MFT_OUTPUT_DATA_BUFFER outBuffs[] = { outBuff };
DWORD outStatus = 0;
hr = pDecoder->ProcessOutput(0, 1, outBuffs, &outStatus);
if (FAILED(hr)) {
std::cout << "FAILED TO PROCESS OUTPUT" << std::endl;
continue;
//return 1;
}
else {
std::cout << "Successfully decoded data!!!" << std::endl;
IMFMediaEvent* mediaEvent = NULL;
ssink->GetEvent(0, &mediaEvent);
if (mediaEvent == NULL) {
// Nothing to do.. Wait for a request for more
continue;
}
hr = ssink->ProcessSample(decompressedSample);
if (FAILED(hr)) {
std::cout << "Failed to process sample to sink" << std::endl;
continue;
}
}
}
// END My Loop Stuff
}
};
std::thread t(f);
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
t.join();
return (int) msg.wParam;
}

Once I try to pass that off to a IMFStreamSink that I got from the EVR, I get the HRESULT "E_NOINTERFACE No such interface supported" I know that the decompressed sample has data in it. I've used the debugger to confirm. I'm really confused why I'm getting this error as there is no additional data to go along with it.
You are sending a sample to the sink when it's in wrong state.
Per Media Sinks >> Data Flow #3, you are responsible to work with events and asynchronous model of Media Foundation sinks. Specifically, media sink requests sample first and only then you can send it.
Normally Media Session or other Media Foundation APIs handle this, but in your case it's your responsibility.

Related

MapViewOfFile() Returns only the Last Word in the Buffer (See the Example)

I wrote a simple inter-process communication with a memory-mapped file. The code works relatively well, but I have a problem with the buffer that I'll explain shortly. Here is the code (C++, Windows):
#define UNICODE
#define _UNICODE
#include <iostream>
#include <tchar.h>
#include <Windows.h>
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
HANDLE hMapFile;
HANDLE hEvent;
HANDLE isOpened = CreateEvent(NULL, true, false, L"IsOpened"); // To check if a `win32mmap w` runs
if (wcscmp(argv[1], L"w") == 0)
{
SetEvent(isOpened);
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, L"mmapFile");
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping() Error: " << GetLastError() << "\n";
return GetLastError();
}
hEvent = CreateEvent(NULL, true, false, L"mmapEvent");
if (hEvent == INVALID_HANDLE_VALUE || hEvent == NULL)
{
std::cout << "CreateEvent() Error: " << GetLastError() << "\n";
return GetLastError();
}
char* buff = (char*)MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 0);
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
while (buff[0] != L'.')
{
std::cin >> buff;
SetEvent(hEvent);
}
UnmapViewOfFile(buff);
}
else if (wcscmp(argv[1], L"r") == 0)
{
if (WaitForSingleObject(isOpened, 0) == WAIT_TIMEOUT)
{
std::cout << "Waiting for `win32mmap w`...";
WaitForSingleObject(isOpened, INFINITE);
std::cout << "\n";
}
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, L"mmapFile");
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping() Error: " << GetLastError() << "\n";
return GetLastError();
}
hEvent = OpenEvent(EVENT_ALL_ACCESS, false, L"mmapEvent");
if (hEvent == INVALID_HANDLE_VALUE || hEvent == NULL)
{
std::cout << "CreateFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
char* buff = (char*)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
while (true)
{
WaitForSingleObject(hEvent, INFINITE);
ResetEvent(hEvent);
if (buff[0] == '.')
{
break;
}
std::cout << buff << "\n";
}
UnmapViewOfFile(buff);
}
else
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
CloseHandle(hMapFile);
return 0;
}
The program is a simple inter-process communication "chat" that relies on memory-mapped files. To use the program, you need to make two executable instance of the program: win32mmap w and win32mmap r. The first instance is used to type text that is displayed in the second instance. When you type . in the first instance, both of them are terminated.
My problem is when I run the 2 instances of the program, and I type the world Hello in the first instance (win32mmap w), the second instance shows Hello as expected. But when I type Hello World in the first instance, the second instance shows only the word World instead of Hello World. How can I fix the code that the buffer will get the whole text?
Your writer is not waiting for the reader to consume the data before overwriting it with new data.
You need 2 events - one for the reader to wait on signaling when the buffer has data to read, and one for the writer to wait on signaling when the buffer needs data.
Try this instead:
#define UNICODE
#define _UNICODE
#include <iostream>
#include <tchar.h>
#include <Windows.h>
const DWORD BufSize = 1024;
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
HANDLE hMapFile;
char* buff;
HANDLE hNeedDataEvent;
HANDLE hHasDataEvent;
DWORD dwError;
HANDLE isOpened = CreateEvent(NULL, TRUE, FALSE, L"IsOpened"); // To check if a `win32mmap w` runs
if (isOpened == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
return dwError;
}
if (wcscmp(argv[1], L"w") == 0)
{
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BufSize, L"mmapFile");
if (hMapFile == NULL)
{
dwError = GetLastError();
std::cout << "CreateFileMapping() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
buff = (char*) MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, BufSize);
if (!buff)
{
dwError = GetLastError();
std::cout << "MapViewOfFile() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
hNeedDataEvent = CreateEvent(NULL, TRUE, TRUE, L"mmapNeedDataEvent");
if (hNeedDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
hHasDataEvent = CreateEvent(NULL, TRUE, FALSE, L"mmapHasDataEvent");
if (hHasDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
SetEvent(isOpened);
while (WaitForSingleObject(hNeedDataEvent, INFINITE) == WAIT_OBJECT_0)
{
std::cin.get(buff, BufSize);
ResetEvent(hNeedDataEvent);
SetEvent(hHasDataEvent);
if (buff[0] == L'.') break;
}
}
else if (wcscmp(argv[1], L"r") == 0)
{
if (WaitForSingleObject(isOpened, 0) == WAIT_TIMEOUT)
{
std::cout << "Waiting for `win32mmap w`...";
WaitForSingleObject(isOpened, INFINITE);
std::cout << "\n";
}
hMapFile = OpenFileMapping(FILE_MAP_READ, FALSE, L"mmapFile");
if (hMapFile == NULL)
{
dwError = GetLastError();
std::cout << "CreateFileMapping() Error: " << dwError << "\n";
return dwError;
}
char* buff = (char*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, BufSize);
if (!buff)
{
dwError = GetLastError();
std::cout << "MapViewOfFile() Error: " << dwError << "\n";
return dwError;
}
hNeedDataEvent = OpenEvent(SYNCHRONIZE, FALSE, L"mmapNeedDataEvent");
if (hNeedDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "OpenEvent() Error: " << dwError << "\n";
return dwError;
}
hHasDataEvent = OpenEvent(SYNCHRONIZE, FALSE, L"mmapHasDataEvent");
if (hHasDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "OpenEvent() Error: " << dwError << "\n";
return dwError;
}
do
{
SetEvent(hNeedDataEvent);
if (WaitForSingleObject(hHasDataEvent, INFINITE) != WAIT_OBJECT_0)
break;
std::cout << buff << "\n";
ResetEvent(hHasDataEvent);
}
while (buff[0] != '.');
}
else
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
UnmapViewOfFile(buff);
CloseHandle(hMapFile);
CloseHandle(hNeedDataEvent);
CloseHandle(hHasDataEvent);
CloseHandle(isOpened);
return 0;
}

Can't set the output type on an HEVC decoder IMFTransform

I've written this program to setup an HEVC decoder based on https://learn.microsoft.com/en-us/windows/win32/medfound/supporting-direct3d-11-video-decoding-in-media-foundation. Everything works fine until the end when I call result = decoder->SetOutputType(0, media_type, 0); this returns the error MF_E_ATTRIBUTENOTFOUND. I'm not sure what's wrong, this error isn't described in the SetOutputType documentation and I've only found a couple examples of HEVC decoding with MF and none of them describe an error like this.
// WindowsProject5.cpp : Defines the entry point for the application.
//
#include <iostream>
#include <initguid.h>
#include <mfapi.h>
#include <mftransform.h>
#include <combaseapi.h>
#include <d3d11.h>
#include <optional>
#include <Mferror.h>
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
auto result = CoInitialize(NULL);
if (result != S_OK) {
std::cout << "CoInitialize failed" << std::endl;
std::terminate();
}
MSG msg;
MFT_REGISTER_TYPE_INFO inputInfo{ MFMediaType_Video , MFVideoFormat_HEVC };
MFT_REGISTER_TYPE_INFO outputInfo{ MFMediaType_Video, MFVideoFormat_NV12 };
IMFActivate** activates;
unsigned int numActivates = 255;
result = MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, MFT_ENUM_FLAG_SYNCMFT, &inputInfo, nullptr, &activates, &numActivates);
if (result != S_OK) {
std::cout << "MFTEnum failed" << std::endl;
std::terminate();
}
std::cout << numActivates << std::endl;
if (!numActivates) {
std::cout << "No HEVC decoders found" << std::endl;
std::terminate();
}
IMFTransform* decoder;
result = activates[0]->ActivateObject(IID_PPV_ARGS(&decoder));
if (result != S_OK) {
std::cout << "ActivateObject failed" << std::endl;
std::terminate();
}
IMFAttributes* attributes;
result = decoder->GetAttributes(&attributes);
if (result != S_OK) {
std::cout << "GetAttributes failed" << std::endl;
std::terminate();
}
auto aware = 123456u;
result = attributes->GetUINT32(MF_SA_D3D11_AWARE, &aware);
if (result != S_OK) {
std::cout << "GetAttributes failed" << std::endl;
std::terminate();
}
std::cout << "MF_SA_D3D11_AWARE = " << aware << std::endl;
if (!aware) {
std::cout << "HEVC decoder is not DirectX aware" << std::endl;
std::terminate();
}
unsigned int resetToken;
IMFDXGIDeviceManager* deviceManager;
result = MFCreateDXGIDeviceManager(&resetToken, &deviceManager);
if (result != S_OK) {
std::cout << "MFCreateDXGIDeviceManager failed" << std::endl;
std::terminate();
}
result = decoder->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<ULONG_PTR>(deviceManager));
if (result != S_OK) {
std::cout << "ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER) failed" << std::endl;
std::terminate();
}
ID3D11Device* device;
D3D_FEATURE_LEVEL featureLevel;
ID3D11DeviceContext* deviceContext;
result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &device, &featureLevel, &deviceContext);
if (result != S_OK) {
std::cout << "D3D11CreateDevice failed" << std::endl;
std::terminate();
}
result = deviceManager->ResetDevice(device, resetToken);
if (result != S_OK) {
std::cout << "ResetDevice failed" << std::endl;
std::terminate();
}
HANDLE deviceHandle;
result = deviceManager->OpenDeviceHandle(&deviceHandle);
if (result != S_OK) {
std::cout << "OpenDeviceHandle failed" << std::endl;
std::terminate();
}
ID3D11VideoDevice* videoDevice;
result = deviceManager->GetVideoService(deviceHandle, IID_PPV_ARGS(&videoDevice));
if (result != S_OK) {
std::cout << "GetVideoService failed" << std::endl;
std::terminate();
}
ID3D11VideoContext* videoContext;
result = deviceContext->QueryInterface(IID_PPV_ARGS(&videoContext));
if (result != S_OK) {
std::cout << "QueryInterface(videoContext) failed" << std::endl;
std::terminate();
}
ID3D10Multithread* multithreaded;
result = device->QueryInterface(IID_PPV_ARGS(&multithreaded));
if (result != S_OK) {
std::cout << "QueryInterface(multithreaded) failed" << std::endl;
std::terminate();
}
multithreaded->SetMultithreadProtected(true);
auto profileCount = videoDevice->GetVideoDecoderProfileCount();
std::optional<GUID> selectedProfile;
for (decltype(profileCount) i = 0; i < profileCount; ++i) {
GUID profile;
result = videoDevice->GetVideoDecoderProfile(i, &profile);
if (result != S_OK) {
std::cout << "GetVideoDecoderProfile(" << i << ") failed" << std::endl;
std::terminate();
}
if (profile == D3D11_DECODER_PROFILE_HEVC_VLD_MAIN) {
selectedProfile = profile;
std::cout << "D3D11_DECODER_PROFILE_HEVC_VLD_MAIN found" << std::endl;
}
else if (profile == D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10) {
std::cout << "D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10 found" << std::endl;
}
}
if (!selectedProfile.has_value()) {
std::cout << "No HEVC decoder profile found" << std::endl;
std::terminate();
}
BOOL supported;
result = videoDevice->CheckVideoDecoderFormat(&selectedProfile.value(), DXGI_FORMAT_NV12, &supported);
if (result != S_OK) {
std::cout << "CheckVideoDecoderFormat failed" << std::endl;
std::terminate();
}
if (!supported) {
std::cout << "Decoder format not supported" << std::endl;
std::terminate();
}
IMFMediaType* media_type;
result = MFCreateMediaType(&media_type);
if (result != S_OK) {
std::cout << "MFCreateMediaType failed" << std::endl;
std::terminate();
}
result = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
if (result != S_OK) {
std::cout << "SetGUID(MF_MT_MAJOR_TYPE) failed" << std::endl;
std::terminate();
}
result = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_HEVC);
if (result != S_OK) {
std::cout << "SetGUID(MF_MT_SUBTYPE) failed" << std::endl;
std::terminate();
}
result = decoder->SetInputType(0, media_type, 0); // No flags
if (result != S_OK) {
std::cout << "SetInputType failed" << std::endl;
std::terminate();
}
for (uint32_t i = 0;
SUCCEEDED(decoder->GetOutputAvailableType(0, i, &media_type)); ++i) {
GUID out_subtype = { 0 };
result = media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype);
if (result != S_OK) {
std::cout << "GetGUID failed" << std::endl;
std::terminate();
}
if (out_subtype == MFVideoFormat_NV12) {
result = decoder->SetOutputType(0, media_type, 0); // No flags
if (result != S_OK) {
std::cout << "SetOutputType failed" << std::endl;
std::terminate();
}
return true;
}
}
return 0;
}
Even though MSDN does not mention other input media type attributes in H.265 / HEVC Video Decoder, you need to set them as well. See H.264 decoder article on what attributes you need: MF_MT_FRAME_SIZE and friends.
You can also use MFTrace SDK tool to check what attributes were queried and reported as missing immediately before you get the failure.
// Have this line added:
MFSetAttributeSize(media_type, MF_MT_FRAME_SIZE, 1280, 720);
result = decoder->SetInputType(0, media_type, 0); // No flags

How to fetch all the channels from an audio session in win32 api?

I want to control all the app volumes programatically in my cpp program. Basically i would like to be able to control independently each app volume as the windows sound mixer does.
from what I read in the windows api doc, I first need to fetch the default endpoint and then the default audio session.
I'm yet done with this I think, that's what I have :
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <Audioclient.h>
#include <audiopolicy.h>
#include <iostream>
int main() {
HRESULT hr = CoInitialize(NULL);
if (hr != S_OK) {
std::cout << "error initializing : " << hr << std::endl;
return -1;
}
else
std::cout << "successfully initialized\n";
IMMDeviceEnumerator* pEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID*)&pEnumerator);
if (hr != S_OK) {
std::cout << "error creating instance : " << hr << std::endl;
return -1;
}
else {
std::cout << "successfully created instance\n";
}
IMMDevice* pDevice = NULL;
hr = pEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eConsole, &pDevice);
pEnumerator->Release();
pEnumerator = NULL;
if (hr != S_OK) {
std::cout << "error getting default endpoint device : " << hr << std::endl;
return -1;
}
else {
LPWSTR id = NULL;
pDevice->GetId(&id);
DWORD state = 0;
pDevice->GetState(&state);
std::cout << "found device 0x" << id << " with state " << state << std::endl;
}
IAudioClient* audioClient = NULL;
hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (LPVOID*)&audioClient);
if (hr != S_OK) {
std::cout << "failed instantiating audio client " << hr << std::endl;
pDevice->Release();
pDevice = NULL;
return -1;
}
else {
std::cout << "successfully instantiated audio client" << std::endl;
}
IAudioSessionManager2* sessionManager = NULL;
hr = pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (LPVOID*) &sessionManager);
pDevice->Release();
pDevice = NULL;
if (hr != S_OK) {
std::cout << "failed instantiating session manager " << hr << std::endl;
return -1;
}
else {
std::cout << "successfully instantiated sessionManager" << std::endl;
}
IAudioSessionControl2* sessionControl = NULL;
hr = sessionManager->GetAudioSessionControl(&GUID_NULL, FALSE, (IAudioSessionControl**)&sessionControl);
if (hr != S_OK) {
std::cout << "failed retrieving session control " << hr << std::endl;
return -1;
}
LPWSTR sessionId = NULL;
hr = sessionControl->GetSessionIdentifier(&sessionId);
if (hr != S_OK) {
std::cout << "failed retrieving session id " << hr << std::endl;
return -1;
}
GUID sessionGuid = {};
hr = CLSIDFromString(sessionId, &sessionGuid);
if (hr != S_OK) {
std::cout << "failed transforming to GUID " << hr << std::endl;
// got fail here the error code is CO_E_CLASSSTRING -> hr = -2147221005
return -1;
}
//need GUID to initialize audio client or get service will fail
IChannelAudioVolume* channelVolume = NULL;
audioClient->GetService(__uuidof(IChannelAudioVolume), (LPVOID*)&channelVolume);
// is there any better way to list all the channels so i can get the name or the process id of each channel
// is channel the right object to use in this case
sessionControl->Release();
sessionControl = NULL;
sessionManager->Release();
sessionManager = NULL;
audioClient->Release();
audioClient = NULL;
CoUninitialize();
return 0;
}
the program fails when it reaches the id to guid part of the code. How to solve that and will the IChannelAudioVolume allow me to change specific app volumes.
I would also appreciate any samples if existing.

to find the IntegrationServiceVersionState of the VM's present in hyper V code using wmi object in c++

Iam trying to find the IntegrationServiceVersionState of the VM's present in hyper V code using wmi object in c++
IntegrationServiceVersionState can be accessed by calling GetSummaryInformation method of the Msvm_VirtualSystemManagementService class present in root\virtualization\v2 namespace
the snippet of code am facing error is
// Set up to call the Msvm_VirtualSystemManagementService::GetSummaryInformation method
BSTR ClassName = SysAllocString(L"Msvm_VirtualSystemManagementService");
BSTR MethodName = SysAllocString(L"GetSummaryInformation");
cout << "setup initialised" << endl;
//get class
IWbemClassObject* pClass = NULL;
hr = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
cout << "class object got" << endl;
GetWMIError(hr);
//to get the path of the class
IEnumWbemClassObject* pEnumerator1 = NULL;
hr = pSvc->ExecQuery(
BSTR(L"WQL"),
BSTR(L"select * from MSVM_VirtualSystemManagementService "),/*where Caption=\"Virtual Machine\"*/
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator1);
IWbemClassObject* pVirtualSystemManagementServiceObj = NULL;
ULONG uReturn1 = 0;
hr = pEnumerator1->Next(WBEM_INFINITE, 1, &pVirtualSystemManagementServiceObj, &uReturn1);
if (uReturn1 == 0)
{
cout << " couldnt load class path " << endl;
}
VARIANT classpath;
hr = pVirtualSystemManagementServiceObj->Get(L"__Path", 0, &classpath, 0, 0);
wcout << " __Path : " << classpath.bstrVal << endl;
// Get Method
IWbemClassObject* pInParamsDefinition = NULL;
hr = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
cout << "method object got" << endl;
GetWMIError(hr);
// get spawn instance
IWbemClassObject* pClassInstance = NULL;
hr = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
cout << "SpAwn instanaaace e" << endl;
GetWMIError(hr);
//setting data
VARIANT SetData ;
VariantInit(&SetData);
SetData.vt = VT_NULL;
hr = pClassInstance->Put(L"SettingData", 0, &SetData, 0);
if (FAILED(hr))
{
cout << "failed to load setting data parameter" << endl;
}
GetWMIError(hr);
cout << "1st parameter set" << endl;
//requested information
VARIANT reqInfo;
VariantInit(&reqInfo);
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 2;
CComSafeArray<int> arr(5);
arr[0] = 1;
arr[1] = 123;
long nIndex = 0;
psa = SafeArrayCreate(VT_I4, 1, rgsabound);
hr = SafeArrayPutElement(psa, &nIndex, &arr[0]);
nIndex++;
SafeArrayPutElement(psa, &nIndex, &arr[1]);
reqInfo.vt = VT_ARRAY | VT_I4;
reqInfo.parray = psa;
hr = pClassInstance->Put(L"RequestedInformation", 0, &reqInfo, 0);
GetWMIError(hr);
cout << "2nd parameter set" << endl;
//execute method
IWbemClassObject* pOutParams = NULL;
hr = pSvc->ExecMethod(classpath.bstrVal, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
GetWMIError(hr);
if (FAILED(hr))
{
cout << "Could not execute method. Error code = 0x" << hex << hr << endl;
}
GetWMIError(hr);
cout << "method executed" << endl;
the above code works properly but am facing problem in the below code
VARIANT varReturnValue;
VariantInit(&varReturnValue);
hr = pOutParams->Get(_bstr_t(L"ReturnValue"), 0,&varReturnValue, NULL, 0);
if (SUCCEEDED(hr))
{
if (varReturnValue.vt == VT_I4)
{
CIMTYPE ct;
VARIANT varJob;
VariantInit(&varJob);
hr = pOutParams->Get(_bstr_t(L"SummaryInformation"), 0, &varJob, &ct, 0);
if (SUCCEEDED(hr))
{
if (varJob.vt == VT_ARRAY | VT_UNKNOWN)
{
VARIANT myvar;
myvar.vt = VT_ARRAY | VT_UNKNOWN;
SAFEARRAY* pSafeArray = V_ARRAY(&myvar);
long lBound, uBound;
SafeArrayGetLBound(pSafeArray, 1, &lBound);
SafeArrayGetUBound(pSafeArray, 1, &uBound);
cout << lBound << endl;
cout << uBound << endl;
UINT16 Element = NULL;
for (long i = lBound; i <= uBound; i++)
{
hr = SafeArrayGetElement(pSafeArray, &i, &Element);
wcout << Element << endl;
}
}
}
}
}
I got the number of VM's correctly, but facing error in getting the array elements. It just throws some garbage values.
Please some one help to rectify this issue

Problems with backbuffer and EndScene hook

So, i've been trying to retrieve the backbuffer data using a EndScene hook, the thing is that for some reason my GetBackBuffer is returning a invalid result (i think) because when i use pSurface->GetDesc() it returns that the backbuffer has Width 1 and height 1, and it always return the pBits filled with 0.
HRESULT WINAPI hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
IDirect3DSurface9* pSurface = 0;
IDirect3DSurface9* pBBuffer = 0;
D3DLOCKED_RECT Lock;
D3DSURFACE_DESC desc;
if (pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface) != D3D_OK)
{
logg << "ERROR GetBackBuffer: " << GetLastError() << endl;
return pEndScene(pDevice);
}
pSurface->GetDesc(&desc);
logg << "Size: " << desc.Width << ", " << desc.Height << endl;
HRESULT hRes = pDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pBBuffer, NULL);
if (hRes != D3D_OK)
{
logg << "ERROR CreateOffscreenPlainSurface: " << GetLastError() << endl;
return pEndScene(pDevice);
}
hRes = pDevice->GetRenderTargetData(pSurface, pBBuffer);
if (hRes != D3D_OK)
{
logg << "ERROR GetRenderTargetData: " << GetLastError() << endl;
return pEndScene(pDevice);
}
pBBuffer->LockRect(&Lock, NULL, D3DLOCK_READONLY);
Com.DrawBuffer(Lock.pBits);
logg << Lock.pBits << endl;
//Usual free memory functions
pSurface->Release();
pBBuffer->UnlockRect();
pBBuffer->Release();
return pEndScene(pDevice);
}