mirror of https://github.com/HandBrake/HandBrake
268 lines
6.6 KiB
C
268 lines
6.6 KiB
C
/* vce_common.c
|
|
*
|
|
* Copyright (c) 2003-2025 HandBrake Team
|
|
* This file is part of the HandBrake source code.
|
|
* Homepage: <http://handbrake.fr/>.
|
|
* It may be used under the terms of the GNU General Public License v2.
|
|
* For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
|
|
*/
|
|
|
|
#include "handbrake/project.h"
|
|
#include "handbrake/handbrake.h"
|
|
|
|
static int is_vcn_available = -1;
|
|
static int is_vcn_hevc_available = -1;
|
|
static int is_vcn_av1_available = -1;
|
|
|
|
#if HB_PROJECT_FEATURE_VCE
|
|
#include "AMF/core/Factory.h"
|
|
#include "AMF/components/VideoEncoderVCE.h"
|
|
#include "AMF/components/VideoEncoderHEVC.h"
|
|
#include "AMF/components/VideoEncoderAV1.h"
|
|
|
|
AMF_RESULT check_component_available(const wchar_t *componentID)
|
|
{
|
|
amf_handle libHandle = NULL;
|
|
AMFInit_Fn initFun;
|
|
AMFFactory *factory = NULL;
|
|
AMFContext *context = NULL;
|
|
AMFContext1 *context1 = NULL;
|
|
AMFComponent *encoder = NULL;
|
|
AMFCaps *encoderCaps = NULL;
|
|
AMF_RESULT result = AMF_FAIL;
|
|
|
|
libHandle = hb_dlopen(AMF_DLL_NAMEA);
|
|
|
|
if(!libHandle)
|
|
{
|
|
result = AMF_FAIL;
|
|
goto clean;
|
|
}
|
|
|
|
initFun = (AMFInit_Fn)(hb_dlsym(libHandle, AMF_INIT_FUNCTION_NAME));
|
|
if(!initFun)
|
|
{
|
|
result = AMF_FAIL;
|
|
hb_error("VCE: Load Library Failed");
|
|
goto clean;
|
|
}
|
|
|
|
result = initFun(AMF_FULL_VERSION, &factory);
|
|
if(result != AMF_OK)
|
|
{
|
|
hb_error("VCE: Init Failed");
|
|
goto clean;
|
|
}
|
|
|
|
result = factory->pVtbl->CreateContext(factory, &context);
|
|
if(result != AMF_OK)
|
|
{
|
|
hb_error("VCE: Context Failed");
|
|
goto clean;
|
|
}
|
|
|
|
result = context->pVtbl->InitDX11(context, NULL, AMF_DX11_1);
|
|
if (result != AMF_OK) {
|
|
result = context->pVtbl->InitDX9(context, NULL);
|
|
if (result != AMF_OK) {
|
|
AMFGuid guid = IID_AMFContext1();
|
|
result = context->pVtbl->QueryInterface(context, &guid, (void**)&context1);
|
|
if (result != AMF_OK) {
|
|
hb_error("VCE: CreateContext1() failed");
|
|
goto clean;
|
|
}
|
|
|
|
result = context1->pVtbl->InitVulkan(context1, NULL);
|
|
if (result != AMF_OK) {
|
|
if (result == AMF_NOT_SUPPORTED)
|
|
hb_error("VCE: AMF via Vulkan is not supported on the given device.\n");
|
|
else
|
|
hb_error("VCE: AMF failed to initialise on the given Vulkan device.\n");
|
|
goto clean;
|
|
}
|
|
}
|
|
}
|
|
|
|
result = factory->pVtbl->CreateComponent(factory, context, componentID, &encoder);
|
|
|
|
if(result != AMF_OK)
|
|
{
|
|
goto clean;
|
|
}
|
|
|
|
result = encoder->pVtbl->GetCaps(encoder, &encoderCaps);
|
|
|
|
clean:
|
|
if (encoderCaps)
|
|
{
|
|
encoderCaps->pVtbl->Clear(encoderCaps);
|
|
encoderCaps->pVtbl->Release(encoderCaps);
|
|
encoderCaps = NULL;
|
|
}
|
|
if (encoder)
|
|
{
|
|
encoder->pVtbl->Terminate(encoder);
|
|
encoder->pVtbl->Release(encoder);
|
|
encoder = NULL;
|
|
}
|
|
if (context)
|
|
{
|
|
context->pVtbl->Terminate(context);
|
|
context->pVtbl->Release(context);
|
|
context = NULL;
|
|
}
|
|
if (context1)
|
|
{
|
|
context1->pVtbl->Terminate(context1);
|
|
context1->pVtbl->Release(context1);
|
|
context1 = NULL;
|
|
}
|
|
if(libHandle)
|
|
{
|
|
hb_dlclose(libHandle);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int hb_vce_h264_available()
|
|
{
|
|
if (hb_is_hardware_disabled())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (is_vcn_available != -1)
|
|
{
|
|
return is_vcn_available;
|
|
}
|
|
|
|
is_vcn_available = (check_component_available(AMFVideoEncoderVCE_AVC) == AMF_OK) ? 1 : 0;
|
|
if (is_vcn_available == 1)
|
|
{
|
|
hb_log("vcn: is available");
|
|
}
|
|
else
|
|
{
|
|
hb_log("vcn: not available on this system");
|
|
}
|
|
|
|
return is_vcn_available;
|
|
}
|
|
|
|
int hb_vce_h265_available()
|
|
{
|
|
if (hb_is_hardware_disabled())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (is_vcn_hevc_available != -1)
|
|
{
|
|
return is_vcn_hevc_available;
|
|
}
|
|
|
|
is_vcn_hevc_available = (check_component_available(AMFVideoEncoder_HEVC) == AMF_OK) ? 1 : 0;
|
|
return is_vcn_hevc_available;
|
|
}
|
|
|
|
int hb_vce_av1_available()
|
|
{
|
|
if (hb_is_hardware_disabled())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (is_vcn_av1_available != -1)
|
|
{
|
|
return is_vcn_av1_available;
|
|
}
|
|
|
|
is_vcn_av1_available = (check_component_available(AMFVideoEncoder_AV1) == AMF_OK) ? 1 : 0;
|
|
return is_vcn_av1_available;
|
|
}
|
|
|
|
int hb_map_vce_preset_name(int vcodec, const char *preset)
|
|
{
|
|
if (vcodec == HB_VCODEC_FFMPEG_VCE_AV1)
|
|
{
|
|
if (strcmp(preset, "high quality") == 0) {
|
|
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY;
|
|
} else if (strcmp(preset, "quality") == 0) {
|
|
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY;
|
|
} else if (strcmp(preset, "balanced") == 0) {
|
|
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED;
|
|
} else if (strcmp(preset, "speed") == 0) {
|
|
return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED;
|
|
}
|
|
}
|
|
else if (vcodec == HB_VCODEC_FFMPEG_VCE_H265 ||
|
|
vcodec == HB_VCODEC_FFMPEG_VCE_H265_10BIT)
|
|
{
|
|
if (strcmp(preset, "quality") == 0) {
|
|
return AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY;
|
|
} else if (strcmp(preset, "balanced") == 0) {
|
|
return AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED;
|
|
} else if (strcmp(preset, "speed") == 0) {
|
|
return AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED;
|
|
}
|
|
}
|
|
else if (vcodec == HB_VCODEC_FFMPEG_VCE_H264)
|
|
{
|
|
if (strcmp(preset, "quality") == 0) {
|
|
return AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY;
|
|
} else if (strcmp(preset, "balanced") == 0) {
|
|
return AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED;
|
|
} else if (strcmp(preset, "speed") == 0) {
|
|
return AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#else // !HB_PROJECT_FEATURE_VCE
|
|
|
|
int hb_vce_h264_available()
|
|
{
|
|
if (is_vcn_available != -1)
|
|
{
|
|
return is_vcn_available;
|
|
}
|
|
|
|
is_vcn_available = -2;
|
|
hb_log("vcn: not compiled into this build.");
|
|
|
|
return -1;
|
|
}
|
|
|
|
int hb_vce_h265_available()
|
|
{
|
|
if (is_vcn_hevc_available != -1)
|
|
{
|
|
return is_vcn_hevc_available;
|
|
}
|
|
|
|
is_vcn_hevc_available = -2;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int hb_vce_av1_available()
|
|
{
|
|
if (is_vcn_av1_available != -1)
|
|
{
|
|
return is_vcn_av1_available;
|
|
}
|
|
|
|
is_vcn_av1_available = -2;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int hb_map_vce_preset_name(int vcodec, const char *preset)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif // HB_PROJECT_FEATURE_VCE
|