GPU Compute Software
Ask questions about Intel® Graphics Compute software technologies, such as OpenCL* GPU driver and oneAPI Level Zero
307 Discussions

Activate Intel(R) Quick Sync Video H.264 Encoder MFT consume very long tme

shishuai
Beginner
553 Views

When I use Intel Quick Sync Video H.264 Encoder MFT encoding, the process takes a very long time to execute the ActvateObject for the first time, about 9s, and then the ActvateObject execution is normal.

My codec is:

uint32_t flags = MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER;
MFT_REGISTER_TYPE_INFO input_info;
input_info.guidMajorType = MFMediaType_Video;
input_info.guidSubtype = MFVideoFormat_NV12;
MFT_REGISTER_TYPE_INFO output_info;
output_info.guidMajorType = MFMediaType_Video;
output_info.guidSubtype = VideoCodecToMFSubtype(codec);
 
uint32_t count = 0;
HRESULT hr = MFTEnumEx(MFT_CATEGORY_VIDEO_ENCODER, flags, &input_info,
&output_info, pp_activate, &count);
if (FAILED(hr)) {
LogError("%s Failed to enumerate hardware encoders for %s, hr = %x", __FUNCTION__,
GetCodecName(codec).c_str(), hr);
}
 
LogMessage("%s", __FUNCTION__);
// Try to create the encoder with priority according to merit value.
HRESULT hr = E_FAIL;
for (UINT32 i = 0; i < encoder_count; i++) {
auto vendor = GetDriverVendor(pp_activate[i]);
// Skip flawky Intel hybrid AV1 encoder.
if (codec_ == VideoCodec::kAV1 && vendor == DriverVendor::kIntel) {
// Get the CLSID GUID of the HMFT.
GUID mft_guid = { 0 };
pp_activate[i]->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &mft_guid);
if (mft_guid == kIntelAV1HybridEncoderCLSID) {
LogWarrning("%s Skipped Intel hybrid AV1 encoder MFT", __FUNCTION__);
continue;
}
}
 
// Skip NVIDIA GPU due to https://crbug.com/1088650 for constrained
// baseline profile H.264 encoding, and go to the next instance according
// to merit value.
if (codec_ == VideoCodec::kH264 && is_constrained_h264 &&
vendor == DriverVendor::kNvidia) {
LogWarrning("%s Skipped NVIDIA GPU due to https://crbug.com/1088650", __FUNCTION__);
continue;
}
 
hr = pp_activate[i]->ActivateObject(IID_PPV_ARGS(&encoder_));
if (encoder_.Get() != nullptr) {
activate_ = pp_activate[i];
vendor_ = vendor;
pp_activate[i] = nullptr;
 
// Print the friendly name.
Butel::ScopedCoMem<WCHAR> friendly_name;
UINT32 name_length;
activate_->GetAllocatedString(MFT_FRIENDLY_NAME_Attribute, &friendly_name,
&name_length);
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
std::string codec_name = converter.to_bytes(friendly_name.get());
LogMessage("%s Selected asynchronous hardware encoder's friendly name : %s, index = %d", __FUNCTION__,
codec_name.c_str(), i);
// Encoder is successfully activated.
break;
}
else {
// The component that calls ActivateObject is
// responsible for calling ShutdownObject,
pp_activate[i]->ShutdownObject();
}
}
 
if (FAILED(hr)) {
LogError("%s Couldn't activate asynchronous hardware encoder, hr = %x", __FUNCTION__, hr);
return false;
}
 
if (encoder_.Get() == nullptr) {
LogError("%s No asynchronous hardware encoder instance created", __FUNCTION__);
return false;
}
 
Microsoft::WRL::ComPtr<IMFAttributes> all_attributes;
hr = encoder_->GetAttributes(&all_attributes);
if (SUCCEEDED(hr)) {
// An asynchronous MFT must support dynamic format changes,
UINT32 dynamic = FALSE;
hr = all_attributes->GetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &dynamic);
if (!dynamic) {
LogError("%s Couldn't support dynamic format change", __FUNCTION__);
return false;
}
 
// Unlock the selected asynchronous MFTs,
UINT32 async = FALSE;
hr = all_attributes->GetUINT32(MF_TRANSFORM_ASYNC, &async);
if (!async) {
LogError("%s MFT encoder is not asynchronous", __FUNCTION__);
return false;
 
hr = all_attributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
if (FAILED(hr)) {
LogError("%s Couldn't unlock transform async, hr = %x", __FUNCTION__, hr);
return false;
}
}
 
return true;
}
0 Kudos
0 Replies
Reply