mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-09-24 23:31:36 +08:00
obs-qsv11: Add codec enum
(Jim description: Adding a codec enum will add support for other codecs)
This commit is contained in:
@@ -80,7 +80,7 @@ void qsv_encoder_version(unsigned short *major, unsigned short *minor)
|
||||
*minor = ver.Minor;
|
||||
}
|
||||
|
||||
qsv_t *qsv_encoder_open(qsv_param_t *pParams)
|
||||
qsv_t *qsv_encoder_open(qsv_param_t *pParams, enum qsv_codec codec)
|
||||
{
|
||||
mfxIMPL impl_list[4] = {MFX_IMPL_HARDWARE, MFX_IMPL_HARDWARE2,
|
||||
MFX_IMPL_HARDWARE3, MFX_IMPL_HARDWARE4};
|
||||
@@ -102,7 +102,7 @@ qsv_t *qsv_encoder_open(qsv_param_t *pParams)
|
||||
impl = impl_list[adapter_idx];
|
||||
|
||||
QSV_Encoder_Internal *pEncoder = new QSV_Encoder_Internal(impl, ver);
|
||||
mfxStatus sts = pEncoder->Open(pParams);
|
||||
mfxStatus sts = pEncoder->Open(pParams, codec);
|
||||
if (sts != MFX_ERR_NONE) {
|
||||
|
||||
#define WARN_ERR_IMPL(err, str, err_name) \
|
||||
|
||||
@@ -87,6 +87,10 @@ struct adapter_info {
|
||||
bool is_dgpu;
|
||||
};
|
||||
|
||||
enum qsv_codec {
|
||||
QSV_CODEC_AVC,
|
||||
};
|
||||
|
||||
#define MAX_ADAPTERS 10
|
||||
extern struct adapter_info adapters[MAX_ADAPTERS];
|
||||
extern size_t adapter_count;
|
||||
@@ -141,7 +145,7 @@ int qsv_param_default_preset(qsv_param_t *, const char *preset,
|
||||
const char *tune);
|
||||
int qsv_encoder_reconfig(qsv_t *, qsv_param_t *);
|
||||
void qsv_encoder_version(unsigned short *major, unsigned short *minor);
|
||||
qsv_t *qsv_encoder_open(qsv_param_t *);
|
||||
qsv_t *qsv_encoder_open(qsv_param_t *, enum qsv_codec codec);
|
||||
int qsv_encoder_encode(qsv_t *, uint64_t, uint8_t *, uint8_t *, uint32_t,
|
||||
uint32_t, mfxBitstream **pBS);
|
||||
int qsv_encoder_encode_tex(qsv_t *, uint64_t, uint32_t, uint64_t, uint64_t *,
|
||||
|
||||
@@ -148,7 +148,7 @@ QSV_Encoder_Internal::~QSV_Encoder_Internal()
|
||||
ClearData();
|
||||
}
|
||||
|
||||
mfxStatus QSV_Encoder_Internal::Open(qsv_param_t *pParams)
|
||||
mfxStatus QSV_Encoder_Internal::Open(qsv_param_t *pParams, enum qsv_codec codec)
|
||||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
@@ -167,7 +167,7 @@ mfxStatus QSV_Encoder_Internal::Open(qsv_param_t *pParams)
|
||||
|
||||
m_pmfxENC = new MFXVideoENCODE(m_session);
|
||||
|
||||
InitParams(pParams);
|
||||
InitParams(pParams, codec);
|
||||
|
||||
sts = m_pmfxENC->Query(&m_mfxEncParams, &m_mfxEncParams);
|
||||
MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);
|
||||
@@ -191,11 +191,14 @@ mfxStatus QSV_Encoder_Internal::Open(qsv_param_t *pParams)
|
||||
return sts;
|
||||
}
|
||||
|
||||
bool QSV_Encoder_Internal::InitParams(qsv_param_t *pParams)
|
||||
bool QSV_Encoder_Internal::InitParams(qsv_param_t *pParams,
|
||||
enum qsv_codec codec)
|
||||
{
|
||||
memset(&m_mfxEncParams, 0, sizeof(m_mfxEncParams));
|
||||
|
||||
m_mfxEncParams.mfx.CodecId = MFX_CODEC_AVC;
|
||||
if (codec == QSV_CODEC_AVC)
|
||||
m_mfxEncParams.mfx.CodecId = MFX_CODEC_AVC;
|
||||
|
||||
m_mfxEncParams.mfx.GopOptFlag = MFX_GOP_STRICT;
|
||||
m_mfxEncParams.mfx.NumSlice = 1;
|
||||
m_mfxEncParams.mfx.TargetUsage = pParams->nTargetUsage;
|
||||
@@ -746,12 +749,13 @@ mfxStatus QSV_Encoder_Internal::ClearData()
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus QSV_Encoder_Internal::Reset(qsv_param_t *pParams)
|
||||
mfxStatus QSV_Encoder_Internal::Reset(qsv_param_t *pParams,
|
||||
enum qsv_codec codec)
|
||||
{
|
||||
mfxStatus sts = ClearData();
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
sts = Open(pParams);
|
||||
sts = Open(pParams, codec);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
return sts;
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
QSV_Encoder_Internal(mfxIMPL &impl, mfxVersion &version);
|
||||
~QSV_Encoder_Internal();
|
||||
|
||||
mfxStatus Open(qsv_param_t *pParams);
|
||||
mfxStatus Open(qsv_param_t *pParams, enum qsv_codec codec);
|
||||
void GetSPSPPS(mfxU8 **pSPSBuf, mfxU8 **pPPSBuf, mfxU16 *pnSPSBuf,
|
||||
mfxU16 *pnPPSBuf);
|
||||
mfxStatus Encode(uint64_t ts, uint8_t *pDataY, uint8_t *pDataUV,
|
||||
@@ -74,12 +74,12 @@ public:
|
||||
uint64_t lock_key, uint64_t *next_key,
|
||||
mfxBitstream **pBS);
|
||||
mfxStatus ClearData();
|
||||
mfxStatus Reset(qsv_param_t *pParams);
|
||||
mfxStatus Reset(qsv_param_t *pParams, enum qsv_codec codec);
|
||||
mfxStatus ReconfigureEncoder();
|
||||
bool UpdateParams(qsv_param_t *pParams);
|
||||
|
||||
protected:
|
||||
bool InitParams(qsv_param_t *pParams);
|
||||
bool InitParams(qsv_param_t *pParams, enum qsv_codec codec);
|
||||
mfxStatus AllocateSurfaces();
|
||||
mfxStatus GetVideoParam();
|
||||
mfxStatus InitBitstream();
|
||||
|
||||
@@ -64,7 +64,7 @@ OBS_DECLARE_MODULE()
|
||||
OBS_MODULE_USE_DEFAULT_LOCALE("obs-qsv11", "en-US")
|
||||
MODULE_EXPORT const char *obs_module_description(void)
|
||||
{
|
||||
return "Intel Quick Sync Video H.264 encoder support for Windows";
|
||||
return "Intel Quick Sync Video support for Windows";
|
||||
}
|
||||
|
||||
extern struct obs_encoder_info obs_qsv_encoder;
|
||||
|
||||
@@ -145,7 +145,7 @@ static void obs_qsv_destroy(void *data)
|
||||
}
|
||||
}
|
||||
|
||||
static void obs_qsv_defaults(obs_data_t *settings)
|
||||
static void obs_qsv_defaults_h264(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_string(settings, "target_usage", "balanced");
|
||||
obs_data_set_default_int(settings, "bitrate", 2500);
|
||||
@@ -337,7 +337,7 @@ static inline void add_rate_controls(obs_property_t *list,
|
||||
}
|
||||
}
|
||||
|
||||
static obs_properties_t *obs_qsv_props(void *unused)
|
||||
static obs_properties_t *obs_qsv_props(enum qsv_codec codec, void *unused)
|
||||
{
|
||||
UNUSED_PARAMETER(unused);
|
||||
|
||||
@@ -352,7 +352,9 @@ static obs_properties_t *obs_qsv_props(void *unused)
|
||||
prop = obs_properties_add_list(props, "profile", TEXT_PROFILE,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
add_strings(prop, qsv_profile_names);
|
||||
|
||||
if (codec == QSV_CODEC_AVC)
|
||||
add_strings(prop, qsv_profile_names);
|
||||
|
||||
obs_property_set_modified_callback(prop, profile_modified);
|
||||
|
||||
@@ -363,7 +365,9 @@ static obs_properties_t *obs_qsv_props(void *unused)
|
||||
prop = obs_properties_add_list(props, "rate_control", TEXT_RATE_CONTROL,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
add_rate_controls(prop, qsv_ratecontrols);
|
||||
if (codec == QSV_CODEC_AVC)
|
||||
add_rate_controls(prop, qsv_ratecontrols);
|
||||
|
||||
obs_property_set_modified_callback(prop, rate_control_modified);
|
||||
|
||||
prop = obs_properties_add_int(props, "bitrate", TEXT_TARGET_BITRATE, 50,
|
||||
@@ -374,30 +378,38 @@ static obs_properties_t *obs_qsv_props(void *unused)
|
||||
50, 10000000, 50);
|
||||
obs_property_int_set_suffix(prop, " Kbps");
|
||||
|
||||
obs_properties_add_int(props, "accuracy", TEXT_ACCURACY, 0, 10000, 1);
|
||||
obs_properties_add_int(props, "convergence", TEXT_CONVERGENCE, 0, 10,
|
||||
1);
|
||||
obs_properties_add_int(props, "qpi", "QPI", 1, 51, 1);
|
||||
obs_properties_add_int(props, "qpp", "QPP", 1, 51, 1);
|
||||
obs_properties_add_int(props, "qpb", "QPB", 1, 51, 1);
|
||||
obs_properties_add_int(props, "icq_quality", TEXT_ICQ_QUALITY, 1, 51,
|
||||
1);
|
||||
prop = obs_properties_add_list(props, "latency", TEXT_LATENCY,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
add_strings(prop, qsv_latency_names);
|
||||
obs_property_set_long_description(prop,
|
||||
obs_module_text("Latency.ToolTip"));
|
||||
if (codec == QSV_CODEC_AVC) {
|
||||
obs_properties_add_int(props, "accuracy", TEXT_ACCURACY, 0,
|
||||
10000, 1);
|
||||
obs_properties_add_int(props, "convergence", TEXT_CONVERGENCE,
|
||||
0, 10, 1);
|
||||
obs_properties_add_int(props, "qpi", "QPI", 1, 51, 1);
|
||||
obs_properties_add_int(props, "qpp", "QPP", 1, 51, 1);
|
||||
obs_properties_add_int(props, "qpb", "QPB", 1, 51, 1);
|
||||
obs_properties_add_int(props, "icq_quality", TEXT_ICQ_QUALITY,
|
||||
1, 51, 1);
|
||||
prop = obs_properties_add_list(props, "latency", TEXT_LATENCY,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
add_strings(prop, qsv_latency_names);
|
||||
obs_property_set_long_description(
|
||||
prop, obs_module_text("Latency.ToolTip"));
|
||||
|
||||
obs_properties_add_int(props, "bframes", TEXT_BFRAMES, 0, 3, 1);
|
||||
|
||||
if (is_skl_or_greater_platform())
|
||||
obs_properties_add_bool(props, "enhancements",
|
||||
TEXT_PERCEPTUAL_ENHANCEMENTS);
|
||||
obs_properties_add_int(props, "bframes", TEXT_BFRAMES, 0, 3, 1);
|
||||
|
||||
if (is_skl_or_greater_platform())
|
||||
obs_properties_add_bool(props, "enhancements",
|
||||
TEXT_PERCEPTUAL_ENHANCEMENTS);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
static obs_properties_t *obs_qsv_props_h264(void *unused)
|
||||
{
|
||||
UNUSED_PARAMETER(unused);
|
||||
return obs_qsv_props(QSV_CODEC_AVC, unused);
|
||||
}
|
||||
|
||||
static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings)
|
||||
{
|
||||
video_t *video = obs_encoder_video(obsqsv->encoder);
|
||||
@@ -613,21 +625,27 @@ static bool obs_qsv_update(void *data, obs_data_t *settings)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *obs_qsv_create(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
static void *obs_qsv_create(enum qsv_codec codec, obs_data_t *settings,
|
||||
obs_encoder_t *encoder)
|
||||
{
|
||||
struct obs_qsv *obsqsv = bzalloc(sizeof(struct obs_qsv));
|
||||
obsqsv->encoder = encoder;
|
||||
obsqsv->codec = codec;
|
||||
|
||||
video_t *video = obs_encoder_video(encoder);
|
||||
const struct video_output_info *voi = video_output_get_info(video);
|
||||
switch (voi->format) {
|
||||
case VIDEO_FORMAT_I010:
|
||||
case VIDEO_FORMAT_P010:
|
||||
const char *const text = obs_module_text("10bitUnsupportedAvc");
|
||||
obs_encoder_set_last_error(encoder, text);
|
||||
error("%s", text);
|
||||
bfree(obsqsv);
|
||||
return NULL;
|
||||
if (codec == QSV_CODEC_AVC) {
|
||||
const char *const text =
|
||||
obs_module_text("10bitUnsupportedAvc");
|
||||
obs_encoder_set_last_error(encoder, text);
|
||||
error("%s", text);
|
||||
bfree(obsqsv);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (voi->colorspace) {
|
||||
case VIDEO_CS_2100_PQ:
|
||||
@@ -643,7 +661,7 @@ static void *obs_qsv_create(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
|
||||
if (update_settings(obsqsv, settings)) {
|
||||
AcquireSRWLockExclusive(&g_QsvLock);
|
||||
obsqsv->context = qsv_encoder_open(&obsqsv->params);
|
||||
obsqsv->context = qsv_encoder_open(&obsqsv->params, codec);
|
||||
ReleaseSRWLockExclusive(&g_QsvLock);
|
||||
|
||||
if (obsqsv->context == NULL)
|
||||
@@ -692,6 +710,11 @@ static void *obs_qsv_create(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
return obsqsv;
|
||||
}
|
||||
|
||||
static void *obs_qsv_create_h264(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return obs_qsv_create(QSV_CODEC_AVC, settings, encoder);
|
||||
}
|
||||
|
||||
static HANDLE get_lib(const char *lib)
|
||||
{
|
||||
HMODULE mod = GetModuleHandleA(lib);
|
||||
@@ -714,29 +737,44 @@ static bool is_intel_gpu_primary(void)
|
||||
return adapters[ovi.adapter].is_intel;
|
||||
}
|
||||
|
||||
|
||||
static void *obs_qsv_create_tex(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
static void *obs_qsv_create_tex(enum qsv_codec codec, obs_data_t *settings,
|
||||
obs_encoder_t *encoder)
|
||||
{
|
||||
char *encoder_id;
|
||||
if (codec == QSV_CODEC_AVC)
|
||||
encoder_id = "obs_qsv11_soft";
|
||||
|
||||
if (!is_intel_gpu_primary()) {
|
||||
blog(LOG_INFO,
|
||||
">>> app not on intel GPU, fall back to old qsv encoder");
|
||||
return obs_encoder_create_rerouted(encoder, "obs_qsv11_soft");
|
||||
return obs_encoder_create_rerouted(encoder,
|
||||
(const char *)encoder_id);
|
||||
}
|
||||
|
||||
if (!obs_nv12_tex_active()) {
|
||||
bool gpu_texture_active = obs_nv12_tex_active();
|
||||
|
||||
if (!gpu_texture_active) {
|
||||
blog(LOG_INFO,
|
||||
">>> nv12 tex not active, fall back to old qsv encoder");
|
||||
return obs_encoder_create_rerouted(encoder, "obs_qsv11_soft");
|
||||
">>> gpu tex not active, fall back to old qsv encoder");
|
||||
return obs_encoder_create_rerouted(encoder,
|
||||
(const char *)encoder_id);
|
||||
}
|
||||
|
||||
if (obs_encoder_scaling_enabled(encoder)) {
|
||||
blog(LOG_INFO,
|
||||
">>> encoder scaling active, fall back to old qsv encoder");
|
||||
return obs_encoder_create_rerouted(encoder, "obs_qsv11_soft");
|
||||
return obs_encoder_create_rerouted(encoder,
|
||||
(const char *)encoder_id);
|
||||
}
|
||||
|
||||
blog(LOG_INFO, ">>> new qsv encoder");
|
||||
return obs_qsv_create(settings, encoder);
|
||||
return obs_qsv_create(codec, settings, encoder);
|
||||
}
|
||||
|
||||
static void *obs_qsv_create_tex_h264(obs_data_t *settings,
|
||||
obs_encoder_t *encoder)
|
||||
{
|
||||
return obs_qsv_create_tex(QSV_CODEC_AVC, settings, encoder);
|
||||
}
|
||||
|
||||
static bool obs_qsv_extra_data(void *data, uint8_t **extra_data, size_t *size)
|
||||
@@ -954,7 +992,8 @@ static bool obs_qsv_encode(void *data, struct encoder_frame *frame,
|
||||
return false;
|
||||
}
|
||||
|
||||
parse_packet(obsqsv, packet, pBS, voi, received_packet);
|
||||
if (obsqsv->codec == QSV_CODEC_AVC)
|
||||
parse_packet(obsqsv, packet, pBS, voi, received_packet);
|
||||
|
||||
ReleaseSRWLockExclusive(&g_QsvLock);
|
||||
|
||||
@@ -997,7 +1036,8 @@ static bool obs_qsv_encode_tex(void *data, uint32_t handle, int64_t pts,
|
||||
return false;
|
||||
}
|
||||
|
||||
parse_packet(obsqsv, packet, pBS, voi, received_packet);
|
||||
if (obsqsv->codec == QSV_CODEC_AVC)
|
||||
parse_packet(obsqsv, packet, pBS, voi, received_packet);
|
||||
|
||||
ReleaseSRWLockExclusive(&g_QsvLock);
|
||||
|
||||
@@ -1009,12 +1049,12 @@ struct obs_encoder_info obs_qsv_encoder = {
|
||||
.type = OBS_ENCODER_VIDEO,
|
||||
.codec = "h264",
|
||||
.get_name = obs_qsv_getname,
|
||||
.create = obs_qsv_create,
|
||||
.create = obs_qsv_create_h264,
|
||||
.destroy = obs_qsv_destroy,
|
||||
.encode = obs_qsv_encode,
|
||||
.update = obs_qsv_update,
|
||||
.get_properties = obs_qsv_props,
|
||||
.get_defaults = obs_qsv_defaults,
|
||||
.get_properties = obs_qsv_props_h264,
|
||||
.get_defaults = obs_qsv_defaults_h264,
|
||||
.get_extra_data = obs_qsv_extra_data,
|
||||
.get_sei_data = obs_qsv_sei,
|
||||
.get_video_info = obs_qsv_video_info,
|
||||
@@ -1026,13 +1066,13 @@ struct obs_encoder_info obs_qsv_encoder_tex = {
|
||||
.type = OBS_ENCODER_VIDEO,
|
||||
.codec = "h264",
|
||||
.get_name = obs_qsv_getname,
|
||||
.create = obs_qsv_create_tex,
|
||||
.create = obs_qsv_create_tex_h264,
|
||||
.destroy = obs_qsv_destroy,
|
||||
.caps = OBS_ENCODER_CAP_DYN_BITRATE | OBS_ENCODER_CAP_PASS_TEXTURE,
|
||||
.encode_texture = obs_qsv_encode_tex,
|
||||
.update = obs_qsv_update,
|
||||
.get_properties = obs_qsv_props,
|
||||
.get_defaults = obs_qsv_defaults,
|
||||
.get_properties = obs_qsv_props_h264,
|
||||
.get_defaults = obs_qsv_defaults_h264,
|
||||
.get_extra_data = obs_qsv_extra_data,
|
||||
.get_sei_data = obs_qsv_sei,
|
||||
.get_video_info = obs_qsv_video_info,
|
||||
|
||||
Reference in New Issue
Block a user