GPU for decoding
How to implement GPU-powered video decoding described in the article:
https://support.medialooks.com/hc/en-us/articles/360000221371-GPU-powered-decoding
If you need to decode different video files using MFReaderClass or MFileClass, it can be helpful to use several GPUs instead of just one or relying on the CPU. Please, note, decoding will be fallback to CPU if the codec is not supported by hardware GPU decoding. Pay your attention, that GPU indexes don't match with the GPU indexes in the task manager.
If you use a hardware Intel decoder, the enumerating goes in this way:
- 0 - Any available device
- 1 - The first Intel Graphics GPU
- 2 - The second Intel Graphics GPU
If you use hardware Nvidia decoder, the enumerating goes in this way:
- -1 - Any available device
- 0 - The first Nvidia GPU
- 1 - The second Nvidia GPU
Intel decoders do not affect the listing of Nvidia decoders and vice versa.
You can select a specific GPU for one of instance MFReaderClass or MFileClass by using the parameters when opening the video file. For example, consider this test setup:
- GPU 0 - Intel UHD Graphics 770 (Integrated GPU).
- GPU 1 - Nvidia Quadro T400 (Nvidia discrete GPU).
- GPU 2 - Nvidia GeForce RTX 4070 (Nvidia discrete GPU).
The following code demonstrates how to decode the first video on a CPU, the next on the Intel Graphics UHD 770, the next on Nvidia T400, and the last two videos on RTX 4070:
MFormats SDK:
m_objReader_1.ReaderOpen(pathToFile_1, "");
m_objReader_2.ReaderOpen(pathToFile_2, "decoder.quicksync=true decoder.force_gpu=1");
m_objReader_3.ReaderOpen(pathToFile_3, "decoder.nvidia=true decoder.force_gpu=0");
m_objReader_4.ReaderOpen(pathToFile_4, "decoder.nvidia=true decoder.force_gpu=1");
m_objReader_5.ReaderOpen(pathToFile_5, "decoder.nvidia=true decoder.force_gpu=1");
The same for MPlatform SDK, just use FileNameSet() instead of ReaderOpen().
GPU for processing
How to enable the GPU pipeline for video processing described in the article:
https://support.medialooks.com/hc/en-us/articles/360028594212-Enable-the-gpu-pipeline
To select a GPU, you need to change "gpu.index" through the system registry:
Computer\HKEY_CURRENT_USER\Software\Medialooks\MFormats\MFFactory
gpu.index = 0
or via code, this must be done before starting any SDK object:
MFFactoryClass m_objFactory = new MFFactoryClass();
m_objFactory.PropsSet("gpu_pipeline", "true");
m_objFactory.PropsSet("gpu.index", "1");
The new method for selecting GPUs via code has been added to the SDK starting with version 2.9.1.13942:
You can get the count of GPUs using the GPUGetCount() method and then get the M_ADAPTER_DESC[] structures using the GPUGetAdapterDescByIndex() method:
int nCount = 0;
m_objFactory.GPUGetCount(out nCount);
M_ADAPTER_DESC[] GPUArray;
if (nCount > 0)
{
GPUArray = new M_ADAPTER_DESC[nCount];
for (int i = 0; i < nCount; i++)
{
m_objFactory.GPUGetAdapterDescByIndex(i, out GPUArray[i]);
}
}
To select the desired GPU, you need to use the GPUSetAdapterByLuid() method
m_objFactory.GPUSetAdapterByLuid(GPUArray[cmbGPUList.SelectedIndex].llAdapterLuid, "");
Please note that .GPUGetCount() returns the number of GPU adapters one more than you can see in the device manager! The reason of this is that the method additionally counts the Microsoft Basic Render Driver. Therefore, always check the contents of the M_ADAPTER_DESC array of elements and the indices of the found devices before working with it.
GPU for encoding
MFormats and MPlatform SDKs let you use different GPUs for video encoding. You can choose which GPU to use for each MFWriterClass (or MWriterClass) instance. Here’s how to do it in two simple steps:
- Select a hardware video codec for your GPU:
- NVIDIA NVENC H.264 Encoder
- Intel Quicksync HW H.264 Encoder
- AMD AMF H.264 Encoder
- Select the GPU for encoding based on the codec you picked. Add force_gpu='index' in the configuration string of the MFWriterClass (or MWriterClass) instance. The 'index' specifies which graphics card to use.
None: one GPU can encode more than one video simultaneously, but always check the specifications to be sure that you don't exceed the limit of simultaneous video encoding for each separate GPU.
The following code demonstrates how to encode the first video on a CPU, the next video on the Intel Graphics UHD 770, the next on Nvidia T400, and the last two videos on RTX 4070:
MFormats SDK:
m_objWriter_1.WriterSet(path_1, 0, "format='mp4' video::codec='libopenh264' video::b='5M'");
m_objWriter_2.WriterSet(path_2, 0, "format='mp4' video::codec='q264hw' video::force_gpu='1'");
m_objWriter_3.WriterSet(path_3, 0, "format='mp4' video::codec='n264' video::force_gpu='0'");
m_objWriter_4.WriterSet(path_4, 0, "format='mp4' video::codec='n264' video::force_gpu='1'");
m_objWriter_5.WriterSet(path_5, 0, "format='mp4' video::codec='n264' video::force_gpu='1'");
Note: GPU indexes are the same, but they refer to the different GPUs:
The same for MPlatform SDK, just use WriterNameSet() instead of WriterSet().