Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Stores Peak Signal-to-Noise Ratio (PSNR) values for the Y, U, and V planes of an encoded video frame.
Data type
An IMFMediaBuffer containing a MFSampleExtensionPsnrYuv structure.
Remarks
Use IMFAttributes::SetUnknown to attach an IMFMediaBuffer containing the PSNR values to an output sample. Use IMFAttributes::GetUnknown to retrieve the IMFMediaBuffer containing the PSNR values from an output sample. The IMFMediaBuffer contains memory that matches the size of the MFSampleExtensionPsnrYuv structure.
PSNR should only be reported when the entire frame has completed encoding. If the encoder uses multiple slices, the PSNR buffer should be attached to the IMFSample of the last slice.
If the encoder only supports PSNR for the Y plane, the psnrU and psnrV fields shall be zero.
MFCreateDXGISurfaceBuffer can be used to convert a GPU resource into an IMFMediaBuffer.
Examples
The following sample shows a helper function that can be used by implementations of an encoder MFT that supports ICodecAPI. The function shows how to check if quality metrics reporting is enabled on the encoder MFT. If it is enabled, the function shows how to attach the quality metrics onto the output sample. This assumes that each output sample contains a complete frame. If the encoder uses multiple slices, the quality metrics should be attached only to the IMFSample of the last slice.
#include <mfapi.h>
#include <mfobjects.h>
#include <codecapi.h>
#include <wrl.h>
// Function to query and attach PSNR values to output samples
HRESULT ReportPsnrOnOutputSample(
_In_ IMFTransform* encoder,
_In_ IMFSample* outputSample,
_In_ IMFMediaBuffer* psnrBuffer // Pre-created buffer containing PSNR values
)
{
RETURN_HR_IF_NULL(E_INVALIDARG, encoder);
RETURN_HR_IF_NULL(E_INVALIDARG, outputSample);
RETURN_HR_IF_NULL(E_INVALIDARG, psnrBuffer);
// Check if quality metrics (Frame PSNR) are enabled
wil::com_ptr_nothrow<ICodecAPI> codecAPI;
RETURN_IF_FAILED(wil::com_query_to_nothrow(encoder, &codecAPI));
wil::unique_variant value;
RETURN_IF_FAILED(codecAPI->GetValue(&CODECAPI_AVEncVideoEnableFramePsnrYuv, &value));
if (value.vt != VT_BOOL || !value.boolVal) {
return S_OK; // Frame PSNR metric not enabled
}
// Retrieve the sample attributes
wil::com_ptr_nothrow<IMFAttributes> sampleAttributes;
RETURN_IF_FAILED(wil::com_query_to_nothrow(outputSample, &sampleAttributes));
// Attach the pre-created IMFMediaBuffer to the sample's attributes
return sampleAttributes->SetUnknown(MFSampleExtension_FramePsnrYuv, psnrBuffer);
The following example demonstrates how an app can retrieve the quality metrics data from the IMFSample objects that are produced by an encoder MFT.
#include <mfapi.h>
#include <mfobjects.h>
#include <wil.com.h>
#include <wil/result_macros.h>
// Function to retrieve the quality metrics from an IMFSample that an encoder MFT has provided as its
// output.
// The function sets the output parameter "found", to true, if quality metrics were retrieved.
HRESULT RetrievePsnrFromOutputSample(
_In_ IMFSample* outputSample,
_Out_ MFSampleExtensionPsnrYuv* psnrValues,
_Out_ bool* found
)
{
RETURN_HR_IF_NULL(E_INVALIDARG, psnrValues);
*psnrValues = {};
*found = false;
RETURN_HR_IF_NULL(E_INVALIDARG, outputSample);
// Retrieve the sample attributes
wil::com_ptr_nothrow<IMFAttributes> sampleAttributes;
RETURN_IF_FAILED(wil::com_query_to_nothrow(outputSample, &sampleAttributes));
// Retrieve the IMFMediaBuffer containing the PSNR values
wil::com_ptr_nothrow<IMFMediaBuffer> psnrBuffer;
if (SUCCEEDED(sampleAttributes->GetUnknown(MFSampleExtension_FramePsnrYuv, IID_PPV_ARGS(&psnrBuffer))))
{
BYTE* bufferData;
DWORD bufferSize;
RETURN_IF_FAILED(psnrBuffer->Lock(&bufferData, nullptr, &bufferSize));
// Validate that the size if of the data contained in the IMFMediaBuffer matches what we expect.
// In this code sample, we choose to return an error if fail to retrieve the quality metrics.
if (bufferSize <!= (DWORD)sizeof(*psnrValues))
{
psnrBuffer->Unlock();
RETURN_HR(MF_E_BUFFERTOOSMALLFAIL);
}
memcpy(psnrValues, bufferData, sizeof(*psnrValues));
psnrBuffer->Unlock();
*found = true;
}
return S_OK;
}
Requirements
Requirement | Value |
---|---|
Minimum supported client |
Windows 11, version 24H2 |
Minimum supported server |
None. |
Header |
|