Best JSON and Base64 libraries for C++ and Windows

The application in previous post Is my system a hybrid (switchable) graphics system? is implemented in C++/WinRT, which I finally decided to give a try.

For authoring and consuming Windows Runtime APIs using C++, there is C++/WinRT. This is Microsoft’s recommended replacement for the C++/CX language projection, and the Windows Runtime C++ Template Library (WRL).

The real question here is this: is WRL at all adopted yet? However it is already superseded by a new thing!

What is really cool about C++/WinRT though – and I do like the most of it – is that good old fashioned apps like desktop and even console ones can seamlessly consume UWP APIs. And this is the field where new and revised API appear now in first place.

If you, for instance, have a need in JSON lib for C++ code, Windows.Data.Json API is at your service. You no longer need a lib for this and many other routine tasks. Here is how you would parse and stringify JSON in plain C++:

std::wstring EncodeBase64(const BYTE* Data, SIZE_T DataSize)
{
	winrt::Windows::Storage::Streams::Buffer Buffer(static_cast<UINT32>(DataSize));
	std::memcpy(Buffer.data(), Data, DataSize);
	Buffer.Length(static_cast<UINT32>(DataSize));
	const winrt::hstring Text = winrt::Windows::Security::Cryptography::CryptographicBuffer::EncodeToBase64String(Buffer);
	return static_cast<std::wstring>(Text);
}
std::wstring EncodeBase64(const std::string& Value)
{
	return EncodeBase64(reinterpret_cast<const BYTE*>(Value.data()), Value.size());
}
std::wstring EncodeBase64(const std::wstring& Value)
{
	return EncodeBase64(ToMultiByte(Value, CP_UTF8));
}
std::wstring EncodeBase64(const winrt::Windows::Data::Json::JsonObject& Value)
{
	return EncodeBase64(static_cast<std::wstring>(Value.Stringify()));
}

std::wstring DecodeBase64(const std::wstring& Value)
{
	winrt::Windows::Storage::Streams::IBuffer Buffer { winrt::Windows::Security::Cryptography::CryptographicBuffer::DecodeFromBase64String(Value) };
	const UINT32 Length = Buffer.Length();
	std::string Result(Length, 0);
	std::memcpy(Result.data(), Buffer.data(), Length);
	return FromMultiByte(Result);
}
winrt::Windows::Data::Json::JsonObject DecodeBase64AsJsonObject(const std::wstring& Value)
{
	return { winrt::Windows::Data::Json::JsonObject::Parse(DecodeBase64(Value)) };
}

This thing can cope with XAML too, and if you get the hump just go read on on C++/WinRT use of co_await and friends for built-in support for UWP IAsyncAction.

Is my system a hybrid (switchable) graphics system?

There is a number of systems out there equipped with multiple GPUs which work cooperatively. The technology itself started from Integrated graphics processing units which brought a “free” GPU into system. Such system equipped with an additional discrete card obtained two GPUs at a time and from certain point it was a challenge to not just choose between the two but also run the two concurrently and utilize the capacity of both.

These GPUs are typically quite different, and there is a rational reason to prefer one to another in certain scenarios. Integrated graphics (iGPU) is typically slower and power consumption efficient, and discrete graphics (dGPU) is a powerful fully featured unit offering “performance over power saving” capabilities.

At certain point of development the seamless operation of two GPUs received a name of hybrid graphics.

By the original definition, “The discrete GPU is a render-only device, and no display outputs are connected to it.” and so if was the case for quite some time when systems like laptops were given two GPUs with an option to choose the GPU for an application to run on. The cooperative operation of the GPUs was as this: “when the discrete GPU is handling all the rendering duties, the final image output to the display is still handled by the Intel integrated graphics processor (IGP). In effect, the IGP is only being used as a simple display controller, resulting in a seamless, flicker-free experience with no need to reboot.

That is, the principal feature of hybrid graphics technology is to be able to transfer data between GPUs in efficient way so that computationally intensive rendering could happen on performance GPU with the results transferred to the other GPU which has physical wiring to a monitor.

We leverage this hardware capability in Rainway game streaming to offer seamless experience of low latency game streaming using any hardware encoder present in the system, not necessarily belonging to the piece of hardware whether video originates at.

Microsoft Windows operating system and its DirectX Graphics Infrastructure (DXGI) in particular stepped in to hide the details of switchable graphics from applications. Depending on settings, which can be defined per application, an application would see different enumeration order of adapters and operating system would either indicate a “true” adapter as a host of connected monitor, or it would otherwise indicate a different GPU transferring the rendering results between the GPUs behind the scene, such as during desktop composition process.

Side effects of seamless operation of GPUs and misreporting of GPU having monitor connection is that Desktop Duplication API cannot work with undescriptive error codes in certain cases (Error generated when Desktop Duplication API-capable application is run against discrete GPU) or Output Protection Manager API communication reports wrong security certificates.

Recent updates of Windows introduced GPU preference right in the OS settings:

Starting with Windows 10 build 17093, Microsoft is introducing a new Graphics settings page for Multi-GPU systems that allows you to manage the graphics performance preference of your apps. You may be familiar with similar graphics control panels from AMD and Nvidia, and you can continue to use those control panels. When you set an application preference in the Windows Graphics settings, that will take precedence over the other control panel settings.

However these ongoing updates actually extended the boundaries of hybrid system itself. If original hybrid system was defined as a system with primary iGPU with a monitor connected, and additional render-only secondary powerful dGPU, the recent version of Microsoft Windows can run multiple GPU systems with full featured discrete graphics adapter with monitor connected to it, and secondary iGPU being still a part of heterogeneous setup. In certain sense this update invalidated previous technical information and definitions that assumed that it is iGPU which as physical wiring to monitor in hybrid systems.

Even though there is a seemingly seamless operation of multiple GPUs, the GPUs still remain in master/slave relation: the operating system is responsible for composition of final image on the GPU with monitor (DXGI output) connection.

I developed a simple application (see download link at the bottom of the post) that discovers properties of hybrid systems and identifies the “main” GPU with output connection. The application is displaying the details on whether operating system can trick applications and report another GPU following GPU preference settings, and indicates “main” GPUs with an asterisk.

Here are some of the results:

Continue reading →

AMD PowerXpress/Enduro switchable graphics DXGI issue

Yesterday I wrote about the NVIDIA Optimus problem with DXGI where Output Protection Manager API reported Intel certificate for NVIDIA DXGI adapter.

AMD hybrid graphics known as “PowerXpress” (and most recently as “Enduro”) exhibits the same behavior:

Adapters
 AMD Radeon HD 8850M
 Intel(R) HD Graphics Family 

Adapter: AMD Radeon HD 8850M
 Vendor Identifier: 0x1002
 [...]
 Output: \.\DISPLAY1
 [...]

Output Protection Manager (OPM Semantics)
 Certificate Subject: IntelVpgOpm2011
 OPM_GET_OUTPUT_ID: OutputId 0x0000000000040F04
 OPM_GET_ADAPTER_BUS_TYPE: ulInformation OPM_BUS_TYPE_OTHER | OPM_BUS_IMPLEMENTATION_MODIFIER_INSIDE_OF_CHIPSET | OPM_COPP_COMPATIBLE_BUS_TYPE_INTEGRATED
 OPM_GET_CONNECTOR_TYPE: ulInformation OPM_CONNECTOR_TYPE_DISPLAYPORT_EMBEDDED
 [...]

Output Duplication
 Exception: Указанный интерфейс устройства или уровень компонента не поддерживается в данной системе (0x887A0004; DXGI_ERROR_UNSUPPORTED); https://support.microsoft.com/en-ie/help/3019314/error-generated-when-desktop-duplication-api-capable-application-is-ru 

Interestingly, it seems that NVIDIA managed to resolve this problem in their most recent hybrid graphics solutions somehow (no suitable device handy), however AMD in turn seems to have this line of product discontinued at all (community forum questions look like desperate self-help service). Or I just failed to find accurate information on the topic.

MediaFoundationDxgiCapabilities: GPU preference & Hybrid GPU systems

I added a section that enumerates DXGI adapters with the help IDXGIFactory6::EnumAdapterByGpuPreference – this is included into the produced output.

Unfortunately the method does not distinguish between dual GPU systems, such as with discrete GPU and additional CPU integrated Intel GPU…

DXGI Capabilities
 NOTE: Baseline capabilities are corresponding to DXGI 1.1
 Windowed Stereo: 0
 DXGI_FEATURE_PRESENT_ALLOW_TEARING: 1
 Adapters by Preference:
 DXGI_GPU_PREFERENCE_UNSPECIFIED: Radeon RX 570 Series (0.0x0000D18A), Intel(R) UHD Graphics 630 (0.0x8E94827B), Microsoft Basic Render Driver (0.0x0000D163)
 DXGI_GPU_PREFERENCE_MINIMUM_POWER: Intel(R) UHD Graphics 630 (0.0x8E94827B), Radeon RX 570 Series (0.0x0000D18A), Microsoft Basic Render Driver (0.0x0000D163)
 DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE: Radeon RX 570 Series (0.0x0000D18A), Intel(R) UHD Graphics 630 (0.0x8E94827B), Microsoft Basic Render Driver (0.0x0000D163)
 Factory Interfaces: IDXGIObject, IDXGIFactory, IDXGIFactory1, IDXGIFactory2, IDXGIFactory3, IDXGIFactory4, IDXGIFactory5, IDXGIFactory6, IDXGIFactory7, IDXGIDisplayControl 

Adapters
 Radeon RX 570 Series
 Intel(R) UHD Graphics 630 

…and hybrid systems such as NVIDIA Optimus and AMD PowerXpress. Those from AMD seem to be discontinued and AMD is traditionally provides zero helpful feedback to developers (although NVIDIA is not any better).

However this time I might have spotted something interesting. On an NVIDIA hybrid system when an app is executed on iGPU, the output is this (expected):

DXGI Capabilities
 NOTE: Baseline capabilities are corresponding to DXGI 1.1
 Windowed Stereo: 0
 DXGI_FEATURE_PRESENT_ALLOW_TEARING: 1
 Adapters by Preference:
 DXGI_GPU_PREFERENCE_UNSPECIFIED: Intel(R) HD Graphics 520 (0.0x00010765), NVIDIA GeForce 940MX (0.0x00010A9D), Microsoft Basic Render Driver (0.0x00010A66)
 DXGI_GPU_PREFERENCE_MINIMUM_POWER: Intel(R) HD Graphics 520 (0.0x00010765), NVIDIA GeForce 940MX (0.0x00010A9D), Microsoft Basic Render Driver (0.0x00010A66)
 DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE: NVIDIA GeForce 940MX (0.0x00010A9D), Intel(R) HD Graphics 520 (0.0x00010765), Microsoft Basic Render Driver (0.0x00010A66)
 Factory Interfaces: IDXGIObject, IDXGIFactory, IDXGIFactory1, IDXGIFactory2, IDXGIFactory3, IDXGIFactory4, IDXGIFactory5, IDXGIFactory6, IDXGIFactory7, IDXGIDisplayControl 

Adapters
 Intel(R) HD Graphics 520
 NVIDIA GeForce 940MX 

[...]

Output Protection Manager (OPM Semantics)
 Certificate Subject: IntelVpgOpm2011
 OPM_GET_OUTPUT_ID: OutputId 0x0000000000040F04
 OPM_GET_ADAPTER_BUS_TYPE: ulInformation OPM_BUS_TYPE_OTHER | OPM_BUS_IMPLEMENTATION_MODIFIER_INSIDE_OF_CHIPSET | OPM_COPP_COMPATIBLE_BUS_TYPE_INTEGRATED
 OPM_GET_CONNECTOR_TYPE: ulInformation OPM_CONNECTOR_TYPE_DISPLAYPORT_EMBEDDED 

[...]
 
Output Duplication
 Direct3D 11 Feature Level: D3D_FEATURE_LEVEL_11_1; https://msdn.microsoft.com/en-us/library/windows/desktop/ff476876#Overview
 Mode Description:
 Width: 1 920
 Height: 1 080
 Refresh Rate: 138 500 000/2 310 880 (59,934)
 Format: DXGI_FORMAT_B8G8R8A8_UNORM
 Scanline Ordering: DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE
 Scaling: DXGI_MODE_SCALING_UNSPECIFIED
 Rotation: DXGI_MODE_ROTATION_IDENTITY
 Desktop Image In System Memory: 0 

However, when the app is started on dGPU, adapter enumeration order is expectedly changed, and also Desktop Duplication API is dysfunctional as documented here: Error generated when Desktop Duplication API-capable application is run against discrete GPU, but…

DXGI Capabilities
 NOTE: Baseline capabilities are corresponding to DXGI 1.1
 Windowed Stereo: 0
 DXGI_FEATURE_PRESENT_ALLOW_TEARING: 1
 Adapters by Preference:
 DXGI_GPU_PREFERENCE_UNSPECIFIED: NVIDIA GeForce 940MX (0.0x00010A9D), Intel(R) HD Graphics 520 (0.0x00010765), Microsoft Basic Render Driver (0.0x00010A66)
 DXGI_GPU_PREFERENCE_MINIMUM_POWER: Intel(R) HD Graphics 520 (0.0x00010765), NVIDIA GeForce 940MX (0.0x00010A9D), Microsoft Basic Render Driver (0.0x00010A66)
 DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE: NVIDIA GeForce 940MX (0.0x00010A9D), Intel(R) HD Graphics 520 (0.0x00010765), Microsoft Basic Render Driver (0.0x00010A66)
 Factory Interfaces: IDXGIObject, IDXGIFactory, IDXGIFactory1, IDXGIFactory2, IDXGIFactory3, IDXGIFactory4, IDXGIFactory5, IDXGIFactory6, IDXGIFactory7, IDXGIDisplayControl 

Adapters
 NVIDIA GeForce 940MX
 Intel(R) HD Graphics 520 

[...]

Output Protection Manager (OPM Semantics)
 Certificate Subject: IntelVpgOpm2011
 OPM_GET_OUTPUT_ID: OutputId 0x0000000000040F04
 OPM_GET_ADAPTER_BUS_TYPE: ulInformation OPM_BUS_TYPE_OTHER | OPM_BUS_IMPLEMENTATION_MODIFIER_INSIDE_OF_CHIPSET | OPM_COPP_COMPATIBLE_BUS_TYPE_INTEGRATED
 OPM_GET_CONNECTOR_TYPE: ulInformation OPM_CONNECTOR_TYPE_DISPLAYPORT_EMBEDDED

[...]
 
Output Duplication
 Exception: Указанный интерфейс устройства или уровень компонента не поддерживается в данной системе (0x887A0004; DXGI_ERROR_UNSUPPORTED); https://support.microsoft.com/en-ie/help/3019314/error-generated-when-desktop-duplication-api-capable-application-is-ru 

…here is the news: NVIDIA DXGI adapter is enumerated with Intel OPM certificate… What a find!

Download links

Low latency video streaming

Bits of Rainway Pulsar technology at work in this test run. The big monitor is a part of desktop system, by the way, not a high end one: Radeon RX 570 with two monitors, one of which is encoded into H.264 and streamed over network to two pieces of hardware:

  1. Intel NUC with a 2K monitor (small monitor on the left) connected to onboard Intel® Iris® Plus Graphics 640 & its HDMI connector
  2. Xbox One X (in the right bottom corner)

The high FPS 3D thing (by the way, it is “The Universe Within” by BigWIngs) is running on desktop PC and its image is being taken to the other two systems simultaneously via H.264 5 MBit/s encoding.

Ordinary hardware, yet streaming is made right and shows what can be squeezed out.

Will have to check faster hardware, and I think the latency can be cut twice. Interestingly, at some point it might be harder to remote audio at such low latency.

Media Foundation API primitive styling of WinRT windows.mediaCodec

An interesting Media Foundation question on StackOverflow: Weird connection between CoInitializeSecurity() and Media Foundation Encoders

A developer has reasons to discard standard COM security and go RPC_C_IMP_LEVEL_ANONYMOUS. Surprisingly this has effect on Windows Media Foundation API in the part of available codecs (Media Foundation Transforms).

Sample code:

#include <iostream>

#include <winrt\base.h>
#include <mfapi.h>
#include <mftransform.h>

#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfuuid.lib")

int main()
{
	// https://stackoverflow.com/questions/59368680/weird-connection-between-coinitializesecurity-and-media-foundation-encoders
	WINRT_VERIFY(SUCCEEDED(MFStartup(MF_VERSION, MFSTARTUP_FULL)));
	WINRT_VERIFY(SUCCEEDED(CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_ANONYMOUS, nullptr, EOAC_NONE, nullptr)));
	//WINRT_VERIFY(SUCCEEDED(CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)));
	IMFActivate** Activates = nullptr;
	UINT32 ActivateCount = 0;
	WINRT_VERIFY(SUCCEEDED(MFTEnumEx(MFT_CATEGORY_VIDEO_ENCODER, MFT_ENUM_FLAG_ALL, nullptr, nullptr, &Activates, &ActivateCount)));
	WINRT_ASSERT(Activates || !ActivateCount);
	BOOL Found = FALSE;
	for(UINT32 Index = 0; Index < ActivateCount; Index++)
	{
		IMFActivate*& Activate = Activates[Index];
		WINRT_ASSERT(Activate);
		WCHAR* FriendlyName = nullptr;
		UINT32 FriendlyNameLength;
		WINRT_VERIFY(SUCCEEDED(Activate->GetAllocatedString(MFT_FRIENDLY_NAME_Attribute, &FriendlyName, &FriendlyNameLength)));
		std::wcout << FriendlyName << std::endl;
		if(wcscmp(FriendlyName, L"HEVCVideoExtensionEncoder") == 0)
			Found = TRUE;
		CoTaskMemFree(FriendlyName);
	}
	WINRT_ASSERT(Found);
	CoTaskMemFree(Activates);
	//CoUninitialize();
	WINRT_VERIFY(SUCCEEDED(MFShutdown()));
}

CoInitializeSecurity line in the code above removes the following from enumeration:

  • HEIFImageExtension
  • VP9VideoExtensionEncoder
  • HEVCVideoExtensionEncoder

See the pattern? Why?

Similarly to other and older APIs like DirectShow enumeration function combines uniformly interfaced primitives coming from multiple sources. In this case of Media Foundation, enumeration combines (and filters/orders when requested) traditional transforms registered with the API with information in system registry, limited scope transforms and also transforms coming from Windows Store.

For example, H.256/HEVC video decoder and encoder is added to the system as HEVC Video Extension Windows Store item.

<Identity ProcessorArchitecture="x64" Version="1.0.23254.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Name="Microsoft.HEVCVideoExtension"/>

Its video encoder, in turn, is:

        <uap4:Extension Category="windows.mediaCodec">
          <uap4:MediaCodec DisplayName="HEVCVideoExtensionEncoder" Description="This is a video codec" Category="videoEncoder" wincap3:ActivatableClassId="H265Encoder.CH265EncoderTransform" wincap3:Path="x86\mfh265enc.dll" wincap3:ProcessorArchitecture="x86">
            <uap4:MediaEncodingProperties>
              <uap4:InputTypes>
                <!-- NV12 -->
                <uap4:InputType SubType="3231564e-0000-0010-8000-00aa00389b71" />
                <!-- IYUV -->
                <uap4:InputType SubType="56555949-0000-0010-8000-00AA00389B71" />
                <!-- YV12 -->
                <uap4:InputType SubType="32315659-0000-0010-8000-00AA00389B71" />
                <!-- YUY2 -->
                <uap4:InputType SubType="32595559-0000-0010-8000-00AA00389B71" />
              </uap4:InputTypes>
              <uap4:OutputTypes>
                <!-- HEVC -->
                <uap4:OutputType SubType="43564548-0000-0010-8000-00AA00389B71" />
              </uap4:OutputTypes>
            </uap4:MediaEncodingProperties>
          </uap4:MediaCodec>
        </uap4:Extension>
      </Extensions>

Media Foundation API is capable to pick such mediaCodec from Windows Store applications and make it available to desktop applications. However, there in COM security in the middle of the glue layer. Media Foundation would create a special activation object (CMFWinrtInprocActivate) to implement IMFActivate for such WinRT codec and once activated, the transform acts as usual and as documented. These codecs are also dual interfaced and in addition to traditional Media Foundation interfaces like IMFTransform expose UWP interfaces like IMediaExtension and so they are consumable by UWP applications as well.

Cropped video with Xbox One XAML MediaPlayerElement control

XAML MediaPlayerElement control/class is exhibiting a ridiculous bug on Xbox One: once you are going fullscreen the control is not showing the video correctly. A texture is assumed to be rendered in full and it is cropped instead (left top quarter of actual video or alike).

I saw this before but at that time I had other reasons to not use built-in fullscreen mode. This time the reason is more straightforward – it simply does not work as expected.