static char config_lock[PATH_MAX];
static int config_lock_fd;
static int config_scanfile_ok;
+#if ENABLE_VAAPI
+int vainfo_probe_enabled;
+#endif
/* *************************************************************************
* Config migration
if (config_migrate(backup))
config_check();
}
+#if ENABLE_VAAPI
+ vainfo_probe_enabled = config.enable_vainfo;
+#endif
tvhinfo(LS_CONFIG, "loaded");
}
.opts = PO_EXPERT,
.group = 7,
},
+#if ENABLE_VAAPI
+ {
+ .type = PT_BOOL,
+ .id = "enable_vainfo",
+ .name = N_("Enable vainfo detection"),
+ .desc = N_("Enable vainfo detection in order to show only "
+ "encoders that are advertised by VAAPI driver.\n"
+ "NOTE: After save, Tvheadend restart is required!"),
+ .off = offsetof(config_t, enable_vainfo),
+ .opts = PO_EXPERT,
+ .group = 7,
+ },
+#endif
{
.type = PT_STR,
.id = "wizard",
uint32_t hdhomerun_server_tuner_count;
char *hdhomerun_server_model_name;
int hdhomerun_server_enable;
+#if ENABLE_VAAPI
+ int enable_vainfo;
+ #endif
} config_t;
extern const idclass_t config_class;
ptr = ((void*)self) + p->off;
switch (p->type) {
case PT_INT:
+ case PT_DYN_INT:
case PT_BOOL:
*u32 = *(int*)ptr;
return 0;
ptr = ((void*)self) + p->off;
switch (p->type) {
case PT_INT:
+ case PT_DYN_INT:
case PT_BOOL:
*s64 = *(int*)ptr;
return 0;
ptr = ((void*)self) + p->off;
switch (p->type) {
case PT_INT:
+ case PT_DYN_INT:
case PT_BOOL:
*dbl = *(int*)ptr;
return 0;
}
break;
case PT_INT:
+ case PT_DYN_INT:
case PT_U16:
case PT_BOOL:
case PT_PERM:
} randseed;
struct rlimit rl;
extern int dvb_bouquets_parse;
-
+#if ENABLE_VAAPI
+ extern int vainfo_probe_enabled;
+#endif
main_tid = pthread_self();
/* Setup global mutexes */
tvhftrace(LS_MAIN, fsmonitor_init);
tvhftrace(LS_MAIN, libav_init);
tvhftrace(LS_MAIN, tvhtime_init);
+#if ENABLE_VAAPI
+ tvhftrace(LS_MAIN, codec_init, vainfo_probe_enabled);
+#else
tvhftrace(LS_MAIN, codec_init);
+#endif
tvhftrace(LS_MAIN, profile_init);
tvhftrace(LS_MAIN, imagecache_init);
tvhftrace(LS_MAIN, http_client_init);
{ "s64", PT_S64_ATOMIC },
{ "dbl", PT_DBL },
{ "time", PT_TIME },
+ { "int", PT_DYN_INT },
{ "langstr", PT_LANGSTR },
{ "perm", PT_PERM },
};
uint32_t u32, opts;
uint16_t u16;
time_t tm;
+ int dyn_i;
#define PROP_UPDATE(v, t)\
snew = &v;\
if (!p->set && (*((t*)cur) != *((t*)snew))) {\
PROP_UPDATE(tm, time_t);
break;
}
+ case PT_DYN_INT: {
+ if (htsmsg_field_get_s64(f, &s64))
+ continue;
+ dyn_i = s64;
+ PROP_UPDATE(dyn_i, int);
+ break;
+ }
case PT_LANGSTR: {
lang_str_t **lstr1 = cur;
lang_str_t *lstr2;
case PT_TIME:
htsmsg_add_s64(m, name, *(time_t *)val);
break;
+ case PT_DYN_INT:
+ htsmsg_add_s64(m, name, *(int *)val);
+ break;
case PT_LANGSTR:
lang_str_serialize(*(lang_str_t **)val, m, name);
break;
case PT_TIME:
htsmsg_add_s64(m, "default", pl->def.tm);
break;
+ case PT_DYN_INT:
+ htsmsg_add_s32(m, "default", pl->def.dyn_i());
+ break;
case PT_LANGSTR:
/* TODO? */
break;
PT_S64_ATOMIC,
PT_DBL,
PT_TIME,
+ PT_DYN_INT,
PT_LANGSTR,
PT_PERM, // like PT_U32 but with the special save
} prop_type_t;
double d; // PT_DBL
time_t tm; // PT_TIME
htsmsg_t *(*list)(void); // islist != 0
+ int (*dyn_i)(void); // dynamically load a PT_DYN_INT
} def;
/* Extended options */
codec_get_profiles_list(enum AVMediaType media_type);
void
+#if ENABLE_VAAPI
+codec_init(int vainfo_probe_enabled);
+#else
codec_init(void);
+#endif
void
codec_done(void);
#include "internals.h"
+#if ENABLE_VAAPI
+#include "vainfo.h"
+#endif
struct TVHCodecs tvh_codecs;
void
+#if ENABLE_VAAPI
+tvh_codecs_register(int vainfo_probe_enabled)
+#else
tvh_codecs_register()
+#endif
{
SLIST_INIT(&tvh_codecs);
tvh_codec_register(&tvh_codec_mpeg2video);
#endif
#if ENABLE_VAAPI
- tvh_codec_register(&tvh_codec_vaapi_h264);
- tvh_codec_register(&tvh_codec_vaapi_hevc);
- tvh_codec_register(&tvh_codec_vaapi_vp8);
- tvh_codec_register(&tvh_codec_vaapi_vp9);
+ if (vainfo_probe_enabled && !vainfo_init(VAINFO_SHOW_LOGS)) {
+ if (vainfo_encoder_isavailable(VAINFO_H264) ||
+ vainfo_encoder_isavailable(VAINFO_H264_LOW_POWER))
+ tvh_codec_register(&tvh_codec_vaapi_h264);
+ if (vainfo_encoder_isavailable(VAINFO_HEVC) ||
+ vainfo_encoder_isavailable(VAINFO_HEVC_LOW_POWER))
+ tvh_codec_register(&tvh_codec_vaapi_hevc);
+ if (vainfo_encoder_isavailable(VAINFO_VP8) ||
+ vainfo_encoder_isavailable(VAINFO_VP8_LOW_POWER))
+ tvh_codec_register(&tvh_codec_vaapi_vp8);
+ if (vainfo_encoder_isavailable(VAINFO_VP9) ||
+ vainfo_encoder_isavailable(VAINFO_VP9_LOW_POWER))
+ tvh_codec_register(&tvh_codec_vaapi_vp9);
+ }
+ else {
+ tvh_codec_register(&tvh_codec_vaapi_h264);
+ tvh_codec_register(&tvh_codec_vaapi_hevc);
+ tvh_codec_register(&tvh_codec_vaapi_vp8);
+ tvh_codec_register(&tvh_codec_vaapi_vp9);
+ }
#endif
#if ENABLE_NVENC
#include "idnode.h"
#include "htsmsg.h"
+#include "transcoding/codec/vainfo.h"
/* defines */
#define VAAPI_ENC_PLATFORM_UNCONSTRAINED 0
#define VAAPI_ENC_LEVEL_HEVC_61 183
#define VAAPI_ENC_LEVEL_HEVC_62 186
+#define VAAPI_ENC_B_REFERENCE_SKIP 0
+#define VAAPI_ENC_B_REFERENCE_I_P 1
+#define VAAPI_ENC_B_REFERENCE_I_P_B 2
+
+#define UI_CODEC_AVAILABLE_OFFSET 0
+#define UI_MAX_B_FRAMES_OFFSET 1
+#define UI_MAX_QUALITY_OFFSET 4
+
+#define TVH_CODEC_PROFILE_VAAPI_UI(codec) \
+ (vainfo_encoder_isavailable(VAINFO_##codec)) + \
+ (vainfo_encoder_maxBfreames(VAINFO_##codec) << UI_MAX_B_FRAMES_OFFSET) + \
+ (vainfo_encoder_maxQuality(VAINFO_##codec) << UI_MAX_QUALITY_OFFSET)
+
/* hts ==================================================================== */
static htsmsg_t *
return strtab2htsmsg(tab, 1, lang);
}
+
+static htsmsg_t *
+b_reference_get_list( void *o, const char *lang )
+{
+ static const struct strtab tab[] = {
+ { N_("skip"), VAAPI_ENC_B_REFERENCE_SKIP },
+ { N_("use P- or I-frames"), VAAPI_ENC_B_REFERENCE_I_P },
+ { N_("use any frame"), VAAPI_ENC_B_REFERENCE_I_P_B },
+ };
+ return strtab2htsmsg(tab, 1, lang);
+}
+
static htsmsg_t *
rc_mode_get_list( void *o, const char *lang )
{
TVHVideoCodecProfile;
int qp;
int quality;
+ int global_quality;
int async_depth;
+/**
+ * VAAPI Encoder availablity.
+ * @note
+ * return:
+ * bit0 - will show if normal encoder is available (VAEntrypointEncSlice)
+ */
+ int ui;
+/**
+ * VAAPI Encoder Low power availablity.
+ * @note
+ * return:
+ * bit0 - will show if low power encoder is available (VAEntrypointEncSliceLP)
+ */
+ int uilp;
+/**
+ * VAAPI Frame used as reference for B-frame [b_depth]
+ * https://www.ffmpeg.org/ffmpeg-codecs.html#toc-VAAPI-encoders
+ * @note
+ * int:
+ * 0 - skip
+ * 1 - all B-frames will refer only to P- or I-frames
+ * 2 - multiple layers of B-frames will be present
+ */
+ int b_reference;
+/**
+ * VAAPI Maximum consecutive B-frame [bf]
+ * https://www.ffmpeg.org/ffmpeg-codecs.html#toc-VAAPI-encoders
+ * @note
+ * int:
+ * 0 - no B-Frames allowed
+ * >0 - number of consecutive B-frames (valid with b_reference = 1 --> "use P- or I-frames")
+ */
int desired_b_depth;
+/**
+ * VAAPI Maximum bitrate [maxrate]
+ * https://www.ffmpeg.org/ffmpeg-codecs.html#toc-VAAPI-encoders
+ * @note
+ * int:
+ * VALUE - max bitrate in bps
+ */
double max_bit_rate;
+/**
+ * VAAPI Maximum bitrate [maxrate]
+ * https://www.ffmpeg.org/ffmpeg-codecs.html#toc-VAAPI-encoders
+ * @note
+ * double:
+ * VALUE - max bitrate in bps
+ */
double bit_rate_scale_factor;
+/**
+ * VAAPI Platform hardware [not ffmpeg parameter]
+ * https://www.ffmpeg.org/ffmpeg-codecs.html#toc-VAAPI-encoders
+ * @note
+ * int:
+ * 0 - Unconstrained (usefull for debug)
+ * 1 - Intel
+ * 2 - AMD
+ */
int platform;
int loop_filter_level;
int loop_filter_sharpness;
return result;
}
+#define TVH_CODEC_PROFILE_VAAPI_CODEC_UI(codec_ui, codec_name) \
+ static const int tvh_codec_profile_vaapi_##codec_ui##_ui(void) \
+ { \
+ return TVH_CODEC_PROFILE_VAAPI_UI(codec_name); \
+ }
+
+// static const int tvh_codec_profile_vaapi_h264_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(h264, H264)
+
+// static const int tvh_codec_profile_vaapi_hevc_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(hevc, HEVC)
+
+// static const int tvh_codec_profile_vaapi_vp8_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(vp8, VP8)
+
+// static const int tvh_codec_profile_vaapi_vp9_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(vp9, VP9)
+
+// static const int tvh_codec_profile_vaapi_h264lp_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(h264lp, H264_LOW_POWER)
+
+// static const int tvh_codec_profile_vaapi_hevclp_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(hevclp, HEVC_LOW_POWER)
+
+// static const int tvh_codec_profile_vaapi_vp8lp_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(vp8lp, VP8_LOW_POWER)
+
+// static const int tvh_codec_profile_vaapi_vp9lp_ui(void)
+TVH_CODEC_PROFILE_VAAPI_CODEC_UI(vp9lp, VP9_LOW_POWER)
+
static int
tvh_codec_profile_vaapi_open(tvh_codec_profile_vaapi_t *self,
AVDictionary **opts)
.type = PT_BOOL,
.id = "low_power", // Don't change
.name = N_("Low Power"),
- .desc = N_("Set low power mode.[if disabled will not send parameter to libav, if enabled codec will disable B frames]"),
+ .desc = N_("Set low power mode.[if disabled will not send 'low power' parameter to libav]"),
.group = 3,
.opts = PO_EXPERT,
.get_opts = codec_profile_class_get_opts,
.type = PT_INT,
.id = "desired_b_depth", // Don't change
.name = N_("Maximum B-frame"),
- .desc = N_("Maximum B-frame reference depth (from 1 to 3) (default 1)"),
+ .desc = N_("Maximum B-frame depth (from 0 to 7, -1=skip) (default 0)"),
.group = 3,
.get_opts = codec_profile_class_get_opts,
.off = offsetof(tvh_codec_profile_vaapi_t, desired_b_depth),
- .intextra = INTEXTRA_RANGE(0, 3, 1),
- .def.i = 1,
+ .intextra = INTEXTRA_RANGE(-1, 7, 1),
+ .def.i = 0,
+ },
+ {
+ .type = PT_INT,
+ .id = "b_reference", // Don't change
+ .name = N_("B-frame reference"),
+ .desc = N_("Frame used as reference for B-frame (default 0)"),
+ .group = 3,
+ .get_opts = codec_profile_class_get_opts,
+ .off = offsetof(tvh_codec_profile_vaapi_t, b_reference),
+ .list = b_reference_get_list,
+ .def.i = 0,
},
{
.type = PT_INT,
.intextra = INTEXTRA_RANGE(0, 64, 1),
.def.i = 44,
},
+ {
+ .type = PT_INT,
+ .id = "quality", // Don't change
+ .name = N_("Quality"),
+ .desc = N_("Set encode quality (trades off against speed, "
+ "higher is faster) [-1=skip 0-15]."),
+ .group = 5,
+ .opts = PO_EXPERT,
+ .get_opts = codec_profile_class_get_opts,
+ .off = offsetof(tvh_codec_profile_vaapi_t, quality),
+ .intextra = INTEXTRA_RANGE(-1, 15, 1),
+ .def.i = 0,
+ },
{}
}
},
int int_bitrate = (int)((double)(self->bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
int int_buffer_size = (int)((double)(self->bit_rate) * 2048.0 * self->buff_factor * (1.0 + self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480));
int int_max_bitrate = (int)((double)(self->max_bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
+ // force max_bitrate to be >= with bitrate (to avoid crash)
+ if (int_bitrate > int_max_bitrate) {
+ tvherror(LS_VAAPI, "Bitrate %d kbps is greater than Max bitrate %d kbps, increase Max bitrate to %d kbps", int_bitrate / 1024, int_max_bitrate / 1024, int_bitrate / 1024);
+ int_max_bitrate = int_bitrate;
+ }
tvhinfo(LS_VAAPI, "Bitrate = %d kbps; Buffer size = %d kbps; Max bitrate = %d kbps", int_bitrate / 1024, int_buffer_size / 1024, int_max_bitrate / 1024);
// https://wiki.libav.org/Hardware/vaapi
// https://blog.wmspanel.com/2017/03/vaapi-libva-support-nimble-streamer.html
// 6 60 E..V.......
// 6.1 61 E..V.......
// 6.2 62 E..V.......
- if (self->rc_mode >= 0) {
+ if (self->rc_mode != VAAPI_ENC_PARAMS_RC_SKIP) {
AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
}
switch (self->platform) {
- case 0:
+ case VAAPI_ENC_PLATFORM_UNCONSTRAINED:
// Uncontrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
+ case VAAPI_ENC_PLATFORM_INTEL:
// Intel
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ int tempSupport = 0;
+ if (self->low_power) {
+ tempSupport = vainfo_encoder_maxBfreames(VAINFO_H264_LOW_POWER);
+ }
+ else {
+ tempSupport = vainfo_encoder_maxBfreames(VAINFO_H264);
+ }
+ if (tempSupport) {
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
+ // max_b_frames
+ AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ }
+ }
+ else {
// max_b_frames
- AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "bf", 0, AV_DICT_DONT_OVERWRITE);
}
+
switch (self->rc_mode) {
- case -1:
+ case VAAPI_ENC_PARAMS_RC_SKIP:
// same like 0 but is not sending 'rc_mode'
- case 0:
+ case VAAPI_ENC_PARAMS_RC_AUTO:
// for auto --> let the driver decide as requested by documentation
if (self->bit_rate) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
- case 4:
+ case VAAPI_ENC_PARAMS_RC_CONSTQP:
+ case VAAPI_ENC_PARAMS_RC_ICQ:
// for constant quality: CQP and ICQ we use qp
if (self->qp) {
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PARAMS_RC_CBR:
// for constant bitrate: CBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 3:
+ case VAAPI_ENC_PARAMS_RC_VBR:
// for variable bitrate: VBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 5:
+ case VAAPI_ENC_PARAMS_RC_QVBR:
// for variable bitrate: QVBR we use bitrate + qp
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 6:
+ case VAAPI_ENC_PARAMS_RC_AVBR:
// for variable bitrate: AVBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
}
break;
}
- if (self->quality >= 0) {
+ if (self->low_power) {
+ tempSupport = vainfo_encoder_maxQuality(VAINFO_H264_LOW_POWER);
+ }
+ else {
+ tempSupport = vainfo_encoder_maxQuality(VAINFO_H264);
+ }
+ if (tempSupport && (self->quality >= 0)) {
AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
}
if (self->low_power) {
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PLATFORM_AMD:
// AMD --> will allow any combination of parameters
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
.ic_class = "codec_profile_vaapi_h264",
.ic_caption = N_("vaapi_h264"),
.ic_properties = (const property_t[]){
- {
- .type = PT_INT,
- .id = "quality", // Don't change
- .name = N_("Quality"),
- .desc = N_("Set encode quality (trades off against speed, "
- "higher is faster) [-1=skip 0-7]."),
- .group = 5,
- .opts = PO_EXPERT,
- .get_opts = codec_profile_class_get_opts,
- .off = offsetof(tvh_codec_profile_vaapi_t, quality),
- .intextra = INTEXTRA_RANGE(-1, 7, 1),
- .def.i = 0,
- },
{
.type = PT_INT,
.id = "level", // Don't change
.list = h264_level_get_list,
.def.i = VAAPI_ENC_LEVEL_H264_3,
},
+ {
+ .type = PT_DYN_INT,
+ .id = "ui", // Don't change
+ .name = N_("User Interface"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, ui),
+ .def.dyn_i= tvh_codec_profile_vaapi_h264_ui,
+ },
+ {
+ .type = PT_DYN_INT,
+ .id = "uilp", // Don't change
+ .name = N_("User Interface (low power)"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, uilp),
+ .def.dyn_i= tvh_codec_profile_vaapi_h264lp_ui,
+ },
{}
}
},
int int_bitrate = (int)((double)(self->bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
int int_buffer_size = (int)((double)(self->bit_rate) * 2048.0 * self->buff_factor * (1.0 + self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480));
int int_max_bitrate = (int)((double)(self->max_bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
+ // force max_bitrate to be >= with bitrate (to avoid crash)
+ if (int_bitrate > int_max_bitrate) {
+ tvherror(LS_VAAPI, "Bitrate %d kbps is greater than Max bitrate %d kbps, increase Max bitrate to %d kbps", int_bitrate / 1024, int_max_bitrate / 1024, int_bitrate / 1024);
+ int_max_bitrate = int_bitrate;
+ }
tvhinfo(LS_VAAPI, "Bitrate = %d kbps; Buffer size = %d kbps; Max bitrate = %d kbps", int_bitrate / 1024, int_buffer_size / 1024, int_max_bitrate / 1024);
// https://wiki.libav.org/Hardware/vaapi
// to find available parameters use:
// hdr E..V....... Include HDR metadata for mastering display colour volume and content light level information
// -tiles <image_size> E..V....... Tile columns x rows
- if (self->rc_mode >= 0) {
+ if (self->rc_mode != VAAPI_ENC_PARAMS_RC_SKIP) {
AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
}
switch (self->platform) {
- case 0:
+ case VAAPI_ENC_PLATFORM_UNCONSTRAINED:
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
if (self->tier >= 0) {
AV_DICT_SET_INT(opts, "tier", self->tier, AV_DICT_DONT_OVERWRITE);
}
+ if (self->quality >= 0) {
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
}
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
+ case VAAPI_ENC_PLATFORM_INTEL:
// Intel
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
switch (self->rc_mode) {
- case -1:
+ case VAAPI_ENC_PARAMS_RC_SKIP:
// same like 0 but is not sending 'rc_mode'
- case 0:
+ case VAAPI_ENC_PARAMS_RC_AUTO:
// for auto --> let the driver decide as requested by documentation
if (self->bit_rate) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
- case 4:
+ case VAAPI_ENC_PARAMS_RC_CONSTQP:
+ case VAAPI_ENC_PARAMS_RC_ICQ:
// for constant quality: CQP and ICQ we use qp
if (self->qp) {
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PARAMS_RC_CBR:
// for constant bitrate: CBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 3:
+ case VAAPI_ENC_PARAMS_RC_VBR:
// for variable bitrate: VBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 5:
+ case VAAPI_ENC_PARAMS_RC_QVBR:
// for variable bitrate: QVBR we use bitrate + qp
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 6:
+ case VAAPI_ENC_PARAMS_RC_AVBR:
// for variable bitrate: AVBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
if (self->tier >= 0) {
AV_DICT_SET_INT(opts, "tier", self->tier, AV_DICT_DONT_OVERWRITE);
}
+ if (self->quality >= 0) {
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
}
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PLATFORM_AMD:
// AMD --> will allow any combination of parameters
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
if (self->tier >= 0) {
AV_DICT_SET_INT(opts, "tier", self->tier, AV_DICT_DONT_OVERWRITE);
}
+ if (self->quality >= 0) {
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
}
.list = hevc_level_get_list,
.def.i = VAAPI_ENC_LEVEL_HEVC_3,
},
+ {
+ .type = PT_DYN_INT,
+ .id = "ui", // Don't change
+ .name = N_("User Interface"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, ui),
+ .def.dyn_i= tvh_codec_profile_vaapi_hevc_ui,
+ },
+ {
+ .type = PT_DYN_INT,
+ .id = "uilp", // Don't change
+ .name = N_("User Interface (low power)"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, uilp),
+ .def.dyn_i= tvh_codec_profile_vaapi_hevclp_ui,
+ },
{}
}
},
int int_bitrate = (int)((double)(self->bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
int int_buffer_size = (int)((double)(self->bit_rate) * 2048.0 * self->buff_factor * (1.0 + self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480));
int int_max_bitrate = (int)((double)(self->max_bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
+ // force max_bitrate to be >= with bitrate (to avoid crash)
+ if (int_bitrate > int_max_bitrate) {
+ tvherror(LS_VAAPI, "Bitrate %d kbps is greater than Max bitrate %d kbps, increase Max bitrate to %d kbps", int_bitrate / 1024, int_max_bitrate / 1024, int_bitrate / 1024);
+ int_max_bitrate = int_bitrate;
+ }
tvhinfo(LS_VAAPI, "Bitrate = %d kbps; Buffer size = %d kbps; Max bitrate = %d kbps", int_bitrate / 1024, int_buffer_size / 1024, int_max_bitrate / 1024);
// https://wiki.libav.org/Hardware/vaapi
// to find available parameters use:
// -loop_filter_level <int> E..V....... Loop filter level (from 0 to 63) (default 16)
// -loop_filter_sharpness <int> E..V....... Loop filter sharpness (from 0 to 15) (default 4)
- if (self->rc_mode >= 0) {
+ if (self->rc_mode != VAAPI_ENC_PARAMS_RC_SKIP) {
AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
}
switch (self->platform) {
- case 0:
+ case VAAPI_ENC_PLATFORM_UNCONSTRAINED:
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
if (self->quality >= 0) {
- AV_DICT_SET_INT(opts, "global_quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->global_quality >= 0) {
+ AV_DICT_SET_INT(opts, "global_quality", self->global_quality, AV_DICT_DONT_OVERWRITE);
}
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
+ case VAAPI_ENC_PLATFORM_INTEL:
// Intel
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
if (self->quality >= 0) {
- AV_DICT_SET_INT(opts, "global_quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->global_quality >= 0) {
+ AV_DICT_SET_INT(opts, "global_quality", self->global_quality, AV_DICT_DONT_OVERWRITE);
}
switch (self->rc_mode) {
- case -1:
+ case VAAPI_ENC_PARAMS_RC_SKIP:
// same like 0 but is not sending 'rc_mode'
- case 0:
+ case VAAPI_ENC_PARAMS_RC_AUTO:
// for auto --> let the driver decide as requested by documentation
if (self->bit_rate) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
- case 4:
+ case VAAPI_ENC_PARAMS_RC_CONSTQP:
+ case VAAPI_ENC_PARAMS_RC_ICQ:
// for constant quality: CQP we use qp
if (self->qp) {
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PARAMS_RC_CBR:
// for constant bitrate: CBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 3:
+ case VAAPI_ENC_PARAMS_RC_VBR:
// for variable bitrate: VBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 5:
+ case VAAPI_ENC_PARAMS_RC_QVBR:
// for variable bitrate: QVBR we use bitrate + qp
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 6:
+ case VAAPI_ENC_PARAMS_RC_AVBR:
// for variable bitrate: AVBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PLATFORM_AMD:
// AMD --> will allow any combination of parameters
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
}
AV_DICT_SET_INT(opts, "bf", 0, 0);
if (self->quality >= 0) {
- AV_DICT_SET_INT(opts, "global_quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->global_quality >= 0) {
+ AV_DICT_SET_INT(opts, "global_quality", self->global_quality, AV_DICT_DONT_OVERWRITE);
}
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
.ic_properties = (const property_t[]){
{
.type = PT_INT,
- .id = "quality", // Don't change
+ .id = "global_quality", // Don't change
.name = N_("Global Quality"),
- .desc = N_("Set encode quality [-1=skip 0-127]."),
+ .desc = N_("Set encode global quality [-1=skip 0-127]."),
.group = 5,
.opts = PO_EXPERT,
.get_opts = codec_profile_class_get_opts,
- .off = offsetof(tvh_codec_profile_vaapi_t, quality),
+ .off = offsetof(tvh_codec_profile_vaapi_t, global_quality),
.intextra = INTEXTRA_RANGE(-1, 127, 1),
.def.i = 40,
},
.intextra = INTEXTRA_RANGE(-1, 15, 1),
.def.i = 4,
},
+ {
+ .type = PT_DYN_INT,
+ .id = "ui", // Don't change
+ .name = N_("User Interface"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, ui),
+ .def.dyn_i= tvh_codec_profile_vaapi_vp8_ui,
+ },
+ {
+ .type = PT_DYN_INT,
+ .id = "uilp", // Don't change
+ .name = N_("User Interface (low power)"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, uilp),
+ .def.dyn_i= tvh_codec_profile_vaapi_vp8lp_ui,
+ },
{}
}
},
int int_bitrate = (int)((double)(self->bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
int int_buffer_size = (int)((double)(self->bit_rate) * 2048.0 * self->buff_factor * (1.0 + self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480));
int int_max_bitrate = (int)((double)(self->max_bit_rate) * 1024.0 * (1.0 + (self->bit_rate_scale_factor * ((double)(self->size.den) - 480.0) / 480.0)));
+ // force max_bitrate to be >= with bitrate (to avoid crash)
+ if (int_bitrate > int_max_bitrate) {
+ tvherror(LS_VAAPI, "Bitrate %d kbps is greater than Max bitrate %d kbps, increase Max bitrate to %d kbps", int_bitrate / 1024, int_max_bitrate / 1024, int_bitrate / 1024);
+ int_max_bitrate = int_bitrate;
+ }
tvhinfo(LS_VAAPI, "Bitrate = %d kbps; Buffer size = %d kbps; Max bitrate = %d kbps", int_bitrate / 1024, int_buffer_size / 1024, int_max_bitrate / 1024);
// https://wiki.libav.org/Hardware/vaapi
// to find available parameters use:
// -loop_filter_level <int> E..V....... Loop filter level (from 0 to 63) (default 16)
// -loop_filter_sharpness <int> E..V....... Loop filter sharpness (from 0 to 15) (default 4)
- if (self->rc_mode >= 0) {
+ if (self->rc_mode != VAAPI_ENC_PARAMS_RC_SKIP) {
AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
}
switch (self->platform) {
- case 0:
+ case VAAPI_ENC_PLATFORM_UNCONSTRAINED:
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
if (self->quality >= 0) {
- AV_DICT_SET_INT(opts, "global_quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->global_quality >= 0) {
+ AV_DICT_SET_INT(opts, "global_quality", self->global_quality, AV_DICT_DONT_OVERWRITE);
}
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
+ case VAAPI_ENC_PLATFORM_INTEL:
// Intel
- if ((self->low_power == 0) && (self->desired_b_depth)) {
- AV_DICT_SET_INT(opts, "b_depth", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
+ if (self->b_reference) {
+ // b_depth
+ AV_DICT_SET_INT(opts, "b_depth", self->b_reference, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->desired_b_depth >= 0) {
// max_b_frames
AV_DICT_SET_INT(opts, "bf", self->desired_b_depth, AV_DICT_DONT_OVERWRITE);
}
AV_DICT_SET(opts, "bsf", "vp9_raw_reorder,vp9_superframe", AV_DICT_DONT_OVERWRITE);
}
if (self->quality >= 0) {
- AV_DICT_SET_INT(opts, "global_quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->global_quality >= 0) {
+ AV_DICT_SET_INT(opts, "global_quality", self->global_quality, AV_DICT_DONT_OVERWRITE);
}
switch (self->rc_mode) {
- case -1:
+ case VAAPI_ENC_PARAMS_RC_SKIP:
// same like 0 but is not sending 'rc_mode'
- case 0:
+ case VAAPI_ENC_PARAMS_RC_AUTO:
// for auto --> let the driver decide as requested by documentation
if (self->bit_rate) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 1:
- case 4:
+ case VAAPI_ENC_PARAMS_RC_CONSTQP:
+ case VAAPI_ENC_PARAMS_RC_ICQ:
// for constant quality: CQP we use qp
if (self->qp) {
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PARAMS_RC_CBR:
// for constant bitrate: CBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 3:
+ case VAAPI_ENC_PARAMS_RC_VBR:
// for variable bitrate: VBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "bufsize", int_buffer_size, AV_DICT_DONT_OVERWRITE);
}
break;
- case 5:
+ case VAAPI_ENC_PARAMS_RC_QVBR:
// for variable bitrate: QVBR we use bitrate + qp
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qp", self->qp, AV_DICT_DONT_OVERWRITE);
}
break;
- case 6:
+ case VAAPI_ENC_PARAMS_RC_AVBR:
// for variable bitrate: AVBR we use bitrate
if (self->bit_rate && self->buff_factor) {
AV_DICT_SET_INT(opts, "b", int_bitrate, AV_DICT_DONT_OVERWRITE);
AV_DICT_SET_INT(opts, "qmax", self->qmax, AV_DICT_DONT_OVERWRITE);
}
break;
- case 2:
+ case VAAPI_ENC_PLATFORM_AMD:
// AMD --> will allow any combination of parameters
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
}
AV_DICT_SET_INT(opts, "bf", 0, 0);
if (self->quality >= 0) {
- AV_DICT_SET_INT(opts, "global_quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ AV_DICT_SET_INT(opts, "quality", self->quality, AV_DICT_DONT_OVERWRITE);
+ }
+ if (self->global_quality >= 0) {
+ AV_DICT_SET_INT(opts, "global_quality", self->global_quality, AV_DICT_DONT_OVERWRITE);
}
if (self->low_power) {
AV_DICT_SET_INT(opts, "low_power", self->low_power, AV_DICT_DONT_OVERWRITE);
.ic_properties = (const property_t[]){
{
.type = PT_INT,
- .id = "quality", // Don't change
+ .id = "global_quality", // Don't change
.name = N_("Global Quality"),
- .desc = N_("Set encode quality [-1=skip 0-255]."),
+ .desc = N_("Set encode global quality [-1=skip 0-255]."),
.group = 5,
.opts = PO_EXPERT,
.get_opts = codec_profile_class_get_opts,
- .off = offsetof(tvh_codec_profile_vaapi_t, quality),
+ .off = offsetof(tvh_codec_profile_vaapi_t, global_quality),
.intextra = INTEXTRA_RANGE(-1, 255, 1),
.def.i = 40,
},
.off = offsetof(tvh_codec_profile_vaapi_t, super_frame),
.def.i = 0,
},
+ {
+ .type = PT_DYN_INT,
+ .id = "ui", // Don't change
+ .name = N_("User Interface"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, ui),
+ .def.dyn_i= tvh_codec_profile_vaapi_vp9_ui,
+ },
+ {
+ .type = PT_DYN_INT,
+ .id = "uilp", // Don't change
+ .name = N_("User Interface (low power)"),
+ .desc = N_("User Interface (bits will show what features are available)."),
+ .group = 3,
+ .opts = PO_PHIDDEN,
+ .off = offsetof(tvh_codec_profile_vaapi_t, uilp),
+ .def.dyn_i= tvh_codec_profile_vaapi_vp9lp_ui,
+ },
{}
}
},
tvh_codec_find(const char *name);
void
+#if ENABLE_VAAPI
+tvh_codecs_register(int vainfo_probe_enabled);
+#else
tvh_codecs_register(void);
+#endif
void
tvh_codecs_forget(void);
void
+#if ENABLE_VAAPI
+codec_init(int vainfo_probe_enabled)
+#else
codec_init(void)
+#endif
{
// codecs
+#if ENABLE_VAAPI
+ tvh_codecs_register(vainfo_probe_enabled);
+#else
tvh_codecs_register();
+#endif
// codec profiles
tvh_codec_profiles_load();
}
}
// pix_fmt
AV_DICT_SET_PIX_FMT(opts, self->pix_fmt, AV_PIX_FMT_YUV420P);
- // max_b_frames
- AV_DICT_SET_INT(opts, "bf", 3, AV_DICT_DONT_OVERWRITE);
return 0;
}
--- /dev/null
+/*
+ * tvheadend - Transcoding
+ *
+ * Copyright (C) 2023 Tvheadend
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "vainfo.h"
+#include "internals.h"
+
+#if ENABLE_VAAPI
+#include <va/va.h>
+#include <fcntl.h>
+#include <va/va_drm.h>
+#include <va/va_str.h>
+#endif
+
+#define CODEC_IS_AVAILABLE 1
+#define CODEC_IS_NOT_AVAILABLE 0
+#define MIN_B_FRAMES 0
+#define MAX_B_FRAMES 7
+#define MIN_QUALITY 0
+#define MAX_QUALITY 15
+
+/* external =================================================================== */
+#if ENABLE_VAAPI
+// this variable is loaded from config: Enable vaapi detection
+extern int vainfo_probe_enabled;
+#endif
+
+/* internal =================================================================== */
+int encoder_h264_isavailable = 0;
+int encoder_h264lp_isavailable = 0;
+int encoder_hevc_isavailable = 0;
+int encoder_hevclp_isavailable = 0;
+int encoder_vp8_isavailable = 0;
+int encoder_vp8lp_isavailable = 0;
+int encoder_vp9_isavailable = 0;
+int encoder_vp9lp_isavailable = 0;
+
+int encoder_h264_maxBfreames = 0;
+int encoder_h264lp_maxBfreames = 0;
+int encoder_hevc_maxBfreames = 0;
+int encoder_hevclp_maxBfreames = 0;
+int encoder_vp8_maxBfreames = 0;
+int encoder_vp8lp_maxBfreames = 0;
+int encoder_vp9_maxBfreames = 0;
+int encoder_vp9lp_maxBfreames = 0;
+
+int encoder_h264_maxQuality = 0;
+int encoder_h264lp_maxQuality = 0;
+int encoder_hevc_maxQuality = 0;
+int encoder_hevclp_maxQuality = 0;
+int encoder_vp8_maxQuality = 0;
+int encoder_vp8lp_maxQuality = 0;
+int encoder_vp9_maxQuality = 0;
+int encoder_vp9lp_maxQuality = 0;
+
+#if ENABLE_VAAPI
+/**
+ * VAINFO was initialized
+ * @note
+ * return:
+ * 0 - not initialized --> will return invalid data
+ * 1 - initialized properly
+ *
+ * NOTE: initialization was performed in /src/transcoding/codec/codec.c
+ */
+int init_done = 0;
+
+int init(int show_log);
+
+static int drm_fd = -1;
+
+static VADisplay
+va_open_display_drm(void)
+{
+ VADisplay va_dpy;
+ int i;
+ static const char *drm_device_paths[] = {
+ "/dev/dri/renderD128",
+ "/dev/dri/card0",
+ "/dev/dri/renderD129",
+ "/dev/dri/card1",
+ NULL
+ };
+ for (i = 0; drm_device_paths[i]; i++) {
+ drm_fd = open(drm_device_paths[i], O_RDWR);
+ if (drm_fd < 0)
+ continue;
+ va_dpy = vaGetDisplayDRM(drm_fd);
+ if (va_dpy)
+ return va_dpy;
+
+ close(drm_fd);
+ drm_fd = -1;
+ }
+ return NULL;
+}
+
+static void
+va_close_display_drm(VADisplay va_dpy)
+{
+ if (drm_fd < 0)
+ return;
+
+ close(drm_fd);
+ drm_fd = -1;
+}
+
+
+static int
+get_config_attributes(VADisplay va_dpy, VAProfile profile, VAEntrypoint entrypoint, int show_log, int codec)
+{
+
+ VAStatus va_status;
+ int i, temp;
+
+ VAConfigAttrib attrib_list[VAConfigAttribTypeMax];
+ int max_num_attributes = VAConfigAttribTypeMax;
+
+ for (i = 0; i < max_num_attributes; i++) {
+ attrib_list[i].type = i;
+ }
+
+ va_status = vaGetConfigAttributes(va_dpy,
+ profile, entrypoint,
+ attrib_list, max_num_attributes);
+ if (VA_STATUS_ERROR_UNSUPPORTED_PROFILE == va_status ||
+ VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT == va_status)
+ return 0;
+
+ if (attrib_list[VAConfigAttribEncMaxRefFrames].value & (~VA_ATTRIB_NOT_SUPPORTED)) {
+ if (show_log) {
+ tvhinfo(LS_VAINFO, " %-35s: l0=%d, l1=%d", vaConfigAttribTypeStr(attrib_list[VAConfigAttribEncMaxRefFrames].type),
+ attrib_list[VAConfigAttribEncMaxRefFrames].value & 0xffff,
+ (attrib_list[VAConfigAttribEncMaxRefFrames].value >> 16) & 0xffff);
+ }
+ temp = (attrib_list[VAConfigAttribEncMaxRefFrames].value >> 16) & 0xffff;
+ if (temp)
+ // this value has to be increased by 1
+ temp++;
+ // limit to max space available in ui
+ if (temp > MAX_B_FRAMES) {
+ tvherror(LS_VAINFO, "show_config_attributes() failed to set max B frames (vainfo:%d --> max=%d)", temp, MAX_B_FRAMES);
+ temp = MAX_B_FRAMES;
+ }
+ switch (codec) {
+ case VAINFO_H264:
+ encoder_h264_maxBfreames = temp;
+ break;
+ case VAINFO_H264_LOW_POWER:
+ encoder_h264lp_maxBfreames = temp;
+ break;
+ case VAINFO_HEVC:
+ encoder_hevc_maxBfreames = temp;
+ break;
+ case VAINFO_HEVC_LOW_POWER:
+ encoder_hevclp_maxBfreames = temp;
+ break;
+ case VAINFO_VP8:
+ encoder_vp8_maxBfreames = temp;
+ break;
+ case VAINFO_VP8_LOW_POWER:
+ encoder_vp8lp_maxBfreames = temp;
+ break;
+ case VAINFO_VP9:
+ encoder_vp9_maxBfreames = temp;
+ break;
+ case VAINFO_VP9_LOW_POWER:
+ encoder_vp9lp_maxBfreames = temp;
+ break;
+ default:
+ tvherror(LS_VAINFO, "codec not available: codec=%d", codec);
+ break;
+ }
+ }
+
+ if (attrib_list[VAConfigAttribEncQualityRange].value != VA_ATTRIB_NOT_SUPPORTED) {
+ if (show_log) {
+ tvhinfo(LS_VAINFO, " %-35s: number of supported quality levels is %d", vaConfigAttribTypeStr(attrib_list[VAConfigAttribEncQualityRange].type),
+ attrib_list[VAConfigAttribEncQualityRange].value <= 1 ? 1 : attrib_list[VAConfigAttribEncQualityRange].value);
+ }
+ temp = attrib_list[VAConfigAttribEncQualityRange].value <= 1 ? 1 : attrib_list[VAConfigAttribEncQualityRange].value;
+ // limit to max space available in ui
+ if (temp > MAX_QUALITY) {
+ tvherror(LS_VAINFO, "show_config_attributes() failed to set max quality (vainfo:%d --> max=%d)", temp, MAX_QUALITY);
+ temp = MAX_QUALITY;
+ }
+ switch (codec) {
+ case VAINFO_H264:
+ encoder_h264_maxQuality = temp;
+ break;
+ case VAINFO_H264_LOW_POWER:
+ encoder_h264lp_maxQuality = temp;
+ break;
+ case VAINFO_HEVC:
+ encoder_hevc_maxQuality = temp;
+ break;
+ case VAINFO_HEVC_LOW_POWER:
+ encoder_hevclp_maxQuality = temp;
+ break;
+ case VAINFO_VP8:
+ encoder_vp8_maxQuality = temp;
+ break;
+ case VAINFO_VP8_LOW_POWER:
+ encoder_vp8lp_maxQuality = temp;
+ break;
+ case VAINFO_VP9:
+ encoder_vp9_maxQuality = temp;
+ break;
+ case VAINFO_VP9_LOW_POWER:
+ encoder_vp9lp_maxQuality = temp;
+ break;
+ default:
+ tvherror(LS_VAINFO, "codec not available: codec=%d", codec);
+ break;
+ }
+ }
+ return 0;
+}
+
+int init(int show_log)
+{
+ VADisplay va_dpy;
+ VAStatus va_status;
+ int major_version, minor_version;
+ int ret_val;
+ const char *driver;
+ int num_entrypoint = 0;
+ VAEntrypoint entrypoint, *entrypoints = NULL;
+ int num_profiles, max_num_profiles, i;
+ VAProfile profile, *profile_list = NULL;
+
+ va_dpy = va_open_display_drm();
+ if (NULL == va_dpy) {
+ tvherror(LS_VAINFO, "vaGetDisplay() failed");
+ ret_val = 2; \
+ goto error_open_display;
+ }
+
+ va_status = vaInitialize(va_dpy, &major_version, &minor_version);
+ if (va_status != VA_STATUS_SUCCESS) {
+ tvherror(LS_VAINFO, "vaInitialize failed with error code %d (%s)", va_status, vaErrorStr(va_status));
+ ret_val = 3;
+ goto error_Initialize;
+ }
+ if (show_log)
+ tvhinfo(LS_VAINFO, "VA-API version: %d.%d", major_version, minor_version);
+
+ driver = vaQueryVendorString(va_dpy);
+ if (show_log)
+ tvhinfo(LS_VAINFO, "Driver version: %s", driver ? driver : "<unknown>");
+
+ num_entrypoint = vaMaxNumEntrypoints(va_dpy);
+ entrypoints = malloc(num_entrypoint * sizeof(VAEntrypoint));
+ if (!entrypoints) {
+ tvherror(LS_VAINFO, "Failed to allocate memory for entrypoint list");
+ ret_val = -1;
+ goto error_entrypoints;
+ }
+
+ max_num_profiles = vaMaxNumProfiles(va_dpy);
+ profile_list = malloc(max_num_profiles * sizeof(VAProfile));
+
+ if (!profile_list) {
+ tvherror(LS_VAINFO, "Failed to allocate memory for profile list");
+ ret_val = 5;
+ goto error_profile_list;
+ }
+
+ va_status = vaQueryConfigProfiles(va_dpy, profile_list, &num_profiles);
+ if (va_status != VA_STATUS_SUCCESS) {
+ tvherror(LS_VAINFO, "vaQueryConfigProfiles failed with error code %d (%s)", va_status, vaErrorStr(va_status));
+ ret_val = 6;
+ goto error_QueryConfigProfiles;
+ }
+
+ for (i = 0; i < num_profiles; i++) {
+ profile = profile_list[i];
+ va_status = vaQueryConfigEntrypoints(va_dpy, profile, entrypoints,
+ &num_entrypoint);
+ if (va_status == VA_STATUS_ERROR_UNSUPPORTED_PROFILE)
+ continue;
+
+ if (va_status != VA_STATUS_SUCCESS) {
+ tvherror(LS_VAINFO, "vaQueryConfigEntrypoints failed with error code %d (%s)", va_status, vaErrorStr(va_status));
+ ret_val = 4;
+ goto error_QueryConfigProfiles;
+ }
+
+ for (entrypoint = 0; entrypoint < num_entrypoint; entrypoint++) {
+ if (show_log)
+ tvhinfo(LS_VAINFO, " %-32s: %s", vaProfileStr(profile), vaEntrypointStr(entrypoints[entrypoint]));
+ // h264
+ if (profile == VAProfileH264High || profile == VAProfileH264ConstrainedBaseline || profile == VAProfileH264Main) {
+ if (entrypoints[entrypoint] == VAEntrypointEncSlice) {
+ encoder_h264_isavailable = 1;
+ // extract attributes
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_H264);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ if (entrypoints[entrypoint] == VAEntrypointEncSliceLP) {
+ encoder_h264lp_isavailable = 1;
+ // extract attributes
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_H264_LOW_POWER);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ }
+ // hevc
+ if (profile == VAProfileHEVCMain || profile == VAProfileHEVCMain10) {
+ if (entrypoints[entrypoint] == VAEntrypointEncSlice) {
+ encoder_hevc_isavailable = 1;
+ // extract attributes
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_HEVC);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ if (entrypoints[entrypoint] == VAEntrypointEncSliceLP) {
+ encoder_hevclp_isavailable = 1;
+ // extract attributes
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_HEVC_LOW_POWER);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ }
+ // vp8
+ if (profile == VAProfileVP8Version0_3) {
+ if (entrypoints[entrypoint] == VAEntrypointEncSlice) {
+ encoder_vp8_isavailable = 1;
+ // extract attributes
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_VP8);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ if (entrypoints[entrypoint] == VAEntrypointEncSliceLP) {
+ encoder_vp8lp_isavailable = 1;
+ // extract attributes
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_VP8_LOW_POWER);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ }
+ // vp9
+ if (profile == VAProfileVP9Profile0 || profile == VAProfileVP9Profile1 || profile == VAProfileVP9Profile2 || profile == VAProfileVP9Profile3) {
+ if (entrypoints[entrypoint] == VAEntrypointEncSlice) {
+ encoder_vp9_isavailable = 1;
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_VP9);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ if (entrypoints[entrypoint] == VAEntrypointEncSliceLP) {
+ encoder_vp9lp_isavailable = 1;
+ ret_val = get_config_attributes(va_dpy, profile_list[i], entrypoints[entrypoint], show_log, VAINFO_VP9_LOW_POWER);
+ if (ret_val) {
+ tvherror(LS_VAINFO, "Failed to get config attributes (error %d)", ret_val);
+ }
+ }
+ }
+ }
+ }
+ init_done = 1;
+ ret_val = 0;
+
+error_QueryConfigProfiles:
+error_profile_list:
+ free(profile_list);
+error_entrypoints:
+ free(entrypoints);
+error_Initialize:
+ vaTerminate(va_dpy);
+error_open_display:
+ va_close_display_drm(va_dpy);
+ // if we had any errors we enable show all codecs (for debugging)
+ if (ret_val) {
+ encoder_h264_isavailable = 1;
+ encoder_h264lp_isavailable = 1;
+ encoder_hevc_isavailable = 1;
+ encoder_hevclp_isavailable = 1;
+ encoder_vp8_isavailable = 1;
+ encoder_vp8lp_isavailable = 1;
+ encoder_vp9_isavailable = 1;
+ encoder_vp9lp_isavailable = 1;
+ }
+
+ return ret_val;
+}
+#endif
+
+/* exposed =================================================================== */
+
+/**
+ * VAINFO initialize.
+ *
+ * @note
+ * Initialize all internal variables according to VAAPI advertised feature
+ * parameter: show_log
+ * 1 = will show vainfo logs with available VAAPI entries
+ * 0 = no logs generated
+ *
+ */
+int vainfo_init(int show_log)
+{
+#if ENABLE_VAAPI
+ int ret = init(show_log);
+ if (ret) {
+ tvherror(LS_VAINFO, "vainfo_init() error: %d", ret);
+ return ret;
+ }
+#endif
+ return 0;
+}
+
+/**
+ * VAINFO Encoder availablity.
+ *
+ * @note
+ * param: CODEC_ID
+ *
+ * return:
+ * 0 - if encoder is not available
+ * 1 - if encoder is available
+ *
+ */
+int vainfo_encoder_isavailable(int codec)
+{
+#if ENABLE_VAAPI
+ if (vainfo_probe_enabled) {
+ if (!init_done)
+ tvherror(LS_VAINFO, "vainfo_init() was not run or generated errors");
+ switch (codec) {
+ case VAINFO_H264:
+ return encoder_h264_isavailable;
+ case VAINFO_H264_LOW_POWER:
+ return encoder_h264lp_isavailable;
+ case VAINFO_HEVC:
+ return encoder_hevc_isavailable;
+ case VAINFO_HEVC_LOW_POWER:
+ return encoder_hevclp_isavailable;
+ case VAINFO_VP8:
+ return encoder_vp8_isavailable;
+ case VAINFO_VP8_LOW_POWER:
+ return encoder_vp8lp_isavailable;
+ case VAINFO_VP9:
+ return encoder_vp9_isavailable;
+ case VAINFO_VP9_LOW_POWER:
+ return encoder_vp9lp_isavailable;
+ default:
+ tvherror(LS_VAINFO, "codec not available: codec=%d", codec);
+ return CODEC_IS_NOT_AVAILABLE;
+ }
+ }
+ else
+#endif
+ return CODEC_IS_AVAILABLE;
+}
+
+
+/**
+ * VAINFO Encoder support for B frames.
+ *
+ * @note
+ * return:
+ * 0 - if encoder is not supporting B frames
+ * > 0 - if encoder is supporting B frames and how many (MAX = 7)
+ *
+ */
+int vainfo_encoder_maxBfreames(int codec)
+{
+#if ENABLE_VAAPI
+ if (vainfo_probe_enabled) {
+ if (!init_done)
+ tvherror(LS_VAINFO, "vainfo_init() was not run or generated errors");
+ switch (codec) {
+ case VAINFO_H264:
+ return encoder_h264_maxBfreames;
+ case VAINFO_H264_LOW_POWER:
+ return encoder_h264lp_maxBfreames;
+ case VAINFO_HEVC:
+ return encoder_hevc_maxBfreames;
+ case VAINFO_HEVC_LOW_POWER:
+ return encoder_hevclp_maxBfreames;
+ case VAINFO_VP8:
+ return encoder_vp8_maxBfreames;
+ case VAINFO_VP8_LOW_POWER:
+ return encoder_vp8lp_maxBfreames;
+ case VAINFO_VP9:
+ return encoder_vp9_maxBfreames;
+ case VAINFO_VP9_LOW_POWER:
+ return encoder_vp9lp_maxBfreames;
+ default:
+ tvherror(LS_VAINFO, "codec not available: codec=%d", codec);
+ return MIN_B_FRAMES;
+ }
+ }
+ else
+#endif
+ return MAX_B_FRAMES;
+}
+
+
+/**
+ * VAINFO Encoder max Quality.
+ *
+ * @note
+ * return:
+ * 0 - if encoder is not supporting Quality
+ * 1 - if encoder is supporting Quality and how much (MAX = 15)
+ *
+ */
+int vainfo_encoder_maxQuality(int codec)
+{
+#if ENABLE_VAAPI
+ if (vainfo_probe_enabled) {
+ if (!init_done)
+ tvherror(LS_VAINFO, "vainfo_init() was not run or generated errors");
+ switch (codec) {
+ case VAINFO_H264:
+ return encoder_h264_maxQuality;
+ case VAINFO_H264_LOW_POWER:
+ return encoder_h264lp_maxQuality;
+ case VAINFO_HEVC:
+ return encoder_hevc_maxQuality;
+ case VAINFO_HEVC_LOW_POWER:
+ return encoder_hevclp_maxQuality;
+ case VAINFO_VP8:
+ return encoder_vp8_maxQuality;
+ case VAINFO_VP8_LOW_POWER:
+ return encoder_vp8lp_maxQuality;
+ case VAINFO_VP9:
+ return encoder_vp9_maxQuality;
+ case VAINFO_VP9_LOW_POWER:
+ return encoder_vp9lp_maxQuality;
+ default:
+ tvherror(LS_VAINFO, "codec not available: codec=%d", codec);
+ return MIN_QUALITY;
+ }
+ }
+ else
+#endif
+ return MAX_QUALITY;
+}
+
+
+/**
+ * VAINFO deinitialize.
+ *
+ * @note
+ * Return all variables to default state
+ *
+ */
+void vainfo_deinit()
+{
+ // this function should not be called
+}
\ No newline at end of file
--- /dev/null
+/*
+ * tvheadend - Transcoding
+ *
+ * Copyright (C) 2023 Tvheadend
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef TVH_TRANSCODING_TRANSCODE_CODEC_VAINFO_H__
+#define TVH_TRANSCODING_TRANSCODE_CODEC_VAINFO_H__
+
+
+/**
+ * VAINFO VAINFO_DONT_SHOW_LOGS.
+ *
+ * @note
+ * Will not print output with detected codec/profiles
+ *
+ */
+#define VAINFO_DONT_SHOW_LOGS 0
+
+/**
+ * VAINFO VAINFO_SHOW_LOGS.
+ *
+ * @note
+ * Will print output with detected codec/profiles
+ *
+ */
+#define VAINFO_SHOW_LOGS 1
+
+
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for H264
+ */
+#define VAINFO_H264 1
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for H264 low power
+ */
+#define VAINFO_H264_LOW_POWER 2
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for HEVC
+ */
+#define VAINFO_HEVC 3
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for HEVC low power
+ */
+#define VAINFO_HEVC_LOW_POWER 4
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for VP8
+ */
+#define VAINFO_VP8 5
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for VP8 low power
+ */
+#define VAINFO_VP8_LOW_POWER 6
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for VP9
+ */
+#define VAINFO_VP9 7
+/**
+ * VAINFO CODEC DEFINE.
+ * @note
+ * Define used when calling functions for VP9 low power
+ */
+#define VAINFO_VP9_LOW_POWER 8
+
+/**
+ * VAINFO initialize.
+ *
+ * @note
+ * Initialize all internal variables according to VAAPI advertised feature
+ * parameter: show_log
+ * 1 = will show vainfo logs with available VAAPI entries
+ * 0 = no logs generated
+ *
+ */
+int vainfo_init(int show_log);
+
+
+/**
+ * VAINFO Encoder availablity.
+ *
+ * @note
+ * param: CODEC_ID
+ *
+ * return:
+ * 0 - if encoder is not available
+ * 1 - if encoder is available
+ *
+ */
+int vainfo_encoder_isavailable(int codec);
+
+
+/**
+ * VAINFO Encoder support for B frames.
+ *
+ * @note
+ * return:
+ * 0 - if encoder is not supporting B frames
+ * > 0 - if encoder is supporting B frames and how many (MAX = 7)
+ *
+ */
+int vainfo_encoder_maxBfreames(int codec);
+
+
+/**
+ * VAINFO Encoder max Quality.
+ *
+ * @note
+ * return:
+ * 0 - if encoder is not supporting Quality
+ * 1 - if encoder is supporting Quality and how much (MAX = 15)
+ *
+ */
+int vainfo_encoder_maxQuality(int codec);
+
+
+/**
+ * VAINFO deinitialize.
+ *
+ * @note
+ * Return all variables to default state
+ *
+ */
+void vainfo_deinit(void);
+
+#endif // TVH_TRANSCODING_TRANSCODE_CODEC_VAINFO_H__
\ No newline at end of file
[LS_TSDEBUG] = { "tsdebug", N_("MPEG-TS Input Debug") },
[LS_CODEC] = { "codec", N_("Codec") },
[LS_VAAPI] = { "vaapi", N_("VA-API") },
+ [LS_VAINFO] = { "vainfo", N_("VAINFO") },
#if ENABLE_DDCI
[LS_DDCI] = { "ddci", N_("DD-CI") },
#endif
LS_TSDEBUG,
LS_CODEC,
LS_VAAPI,
+ LS_VAINFO,
#if ENABLE_DDCI
LS_DDCI,
#endif
form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
}
- function updateFilters(form) {
+ function checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field) {
+ // enable max B frames based on ui (vainfo)
+ var uibframe = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uibframe = (uilp_value & 0xe) >> 1
+ }
+ else {
+ // low power is disabled
+ uibframe = (ui_value & 0xe) >> 1
+ }
+ // messagebox if max B grames > VAINFO.max_b_frames
+ if (uibframe) {
+ if (desired_b_depth_field.getValue() > uibframe)
+ alert('VAINFO maximum B fames is: ' + uibframe)
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ }
+ else {
+ desired_b_depth_field.setDisabled(true);
+ b_reference_field.setDisabled(true);
+ }
+ // enable Quality based on ui (vainfo)
+ var uiquality = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uiquality = (uilp_value & 0xf0) >> 4
+ }
+ else {
+ // low power is disabled
+ uiquality = (ui_value & 0xf0) >> 4
+ }
+ // messagebox if Qality > VAINFO.quality
+ if (uiquality > 1) {
+ if (quality_field.getValue() > uiquality)
+ alert('VAINFO maximum Quality is: ' + uiquality)
+ }
+ else {
+ quality_field.setValue(-1);
+ quality_field.setDisabled(true);
+ }
+ }
+
+ function updateLowPower(form) {
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ }
+
+ function removeConstrains(form) {
+ var bit_rate_field = form.findField('bit_rate');
+ var max_bit_rate_field = form.findField('max_bit_rate');
+ var buff_factor_field = form.findField('buff_factor');
+ var bit_rate_scale_factor_field = form.findField('bit_rate_scale_factor');
+ var qp_field = form.findField('qp');
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ bit_rate_field.setDisabled(false);
+ max_bit_rate_field.setDisabled(false);
+ buff_factor_field.setDisabled(false);
+ bit_rate_scale_factor_field.setDisabled(false);
+ qp_field.setDisabled(false);
+ low_power_field.setDisabled(false);
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ quality_field.setDisabled(false);
+ }
+
+ function updateFilters(form, ui_value, uilp_value) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var bit_rate_field = form.findField('bit_rate');
var qp_field = form.findField('qp');
var low_power_field = form.findField('low_power');
var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
var platform = platform_field.getValue();
switch (platform) {
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
// no filter applied
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
- low_power_field.setDisabled(false);
- desired_b_depth_field.setDisabled(false);
+ removeConstrains(form);
break;
case 1:
// Intel
- // low_power is disabling Max B frame
- desired_b_depth_field.setDisabled(low_power_field.getValue());
+ // enable low_power mode based on ui (vainfo)
+ if ((ui_value & 0x1) && (uilp_value & 0x1))
+ low_power_field.setDisabled(false);
+ else {
+ low_power_field.setDisabled(true);
+ if (uilp_value & 0x1)
+ // only low power is available
+ low_power_field.setValue(true);
+ if (ui_value & 0x1)
+ // only normal is available
+ low_power_field.setValue(false);
+ }
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ // filter based in rc_mode
var rc_mode = rc_mode_field.getValue();
switch (rc_mode) {
case -1:
qp_field.setDisabled(true);
break;
}
- low_power_field.setDisabled(false);
break;
case 2:
// AMD --> will allow any combination of parameters
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
// NOTE: filters to be added later
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
- low_power_field.setDisabled(false);
- desired_b_depth_field.setDisabled(false);
+ removeConstrains(form);
break;
default:
}
var rc_mode_field = form.findField('rc_mode');
var low_power_field = form.findField('low_power');
var hwaccel_field = form.findField('hwaccel');
+ var ui_field = form.findField('ui');
+ var uilp_field = form.findField('uilp');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var quality_field = form.findField('quality');
+ var ui_value = ui_field.getValue();
+ var uilp_value = uilp_field.getValue();
// first time we have to call this manually
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
updateHWFilters(form);
// on platform change
platform_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
});
// on rc_mode change
rc_mode_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
});
// on low_power change
low_power_field.on('check', function(checkbox, value) {
- updateFilters(form);
+ updateLowPower(form);
});
// on hwaccel change
hwaccel_field.on('check', function(checkbox, value) {
updateHWFilters(form);
});
+ // on desired_b_depth change
+ desired_b_depth_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
+ // on quality change
+ quality_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
},
'codec_profile_vaapi_hevc': function(form) {
form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
}
- function updateFilters(form) {
+ function checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field) {
+ // enable max B frames based on ui (vainfo)
+ var uibframe = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uibframe = (uilp_value & 0xe) >> 1
+ }
+ else {
+ // low power is disabled
+ uibframe = (ui_value & 0xe) >> 1
+ }
+ // messagebox if max B grames > VAINFO.max_b_frames
+ if (uibframe) {
+ if (desired_b_depth_field.getValue() > uibframe)
+ alert('VAINFO maximum B fames is: ' + uibframe)
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ }
+ else {
+ desired_b_depth_field.setDisabled(true);
+ b_reference_field.setDisabled(true);
+ }
+ // enable Quality based on ui (vainfo)
+ var uiquality = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uiquality = (uilp_value & 0xf0) >> 4
+ }
+ else {
+ // low power is disabled
+ uiquality = (ui_value & 0xf0) >> 4
+ }
+ // messagebox if Qality > VAINFO.quality
+ if (uiquality > 1) {
+ if (quality_field.getValue() > uiquality)
+ alert('VAINFO maximum Quality is: ' + uiquality)
+ }
+ else {
+ quality_field.setValue(-1);
+ quality_field.setDisabled(true);
+ }
+ }
+
+ function updateLowPower(form) {
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ }
+
+ function removeConstrains(form) {
+ var bit_rate_field = form.findField('bit_rate');
+ var max_bit_rate_field = form.findField('max_bit_rate');
+ var buff_factor_field = form.findField('buff_factor');
+ var bit_rate_scale_factor_field = form.findField('bit_rate_scale_factor');
+ var qp_field = form.findField('qp');
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ bit_rate_field.setDisabled(false);
+ max_bit_rate_field.setDisabled(false);
+ buff_factor_field.setDisabled(false);
+ bit_rate_scale_factor_field.setDisabled(false);
+ qp_field.setDisabled(false);
+ low_power_field.setDisabled(false);
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ quality_field.setDisabled(false);
+ }
+
+ function updateFilters(form, ui_value, uilp_value) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var bit_rate_field = form.findField('bit_rate');
var qp_field = form.findField('qp');
var low_power_field = form.findField('low_power');
var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
var platform = platform_field.getValue();
switch (platform) {
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
// no filter applied
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
- low_power_field.setDisabled(false);
- desired_b_depth_field.setDisabled(false);
+ removeConstrains(form);
break;
case 1:
// Intel
- // low_power is disabling Max B frame
- desired_b_depth_field.setDisabled(low_power_field.getValue());
+ // enable low_power mode based on ui (vainfo)
+ if ((ui_value & 0x1) && (uilp_value & 0x1))
+ low_power_field.setDisabled(false);
+ else {
+ low_power_field.setDisabled(true);
+ if (uilp_value & 0x1)
+ // only low power is available
+ low_power_field.setValue(true);
+ if (ui_value & 0x1)
+ // only normal is available
+ low_power_field.setValue(false);
+ }
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ // filter based in rc_mode
var rc_mode = rc_mode_field.getValue();
switch (rc_mode) {
case -1:
bit_rate_field.setDisabled(false);
max_bit_rate_field.setDisabled(false);
buff_factor_field.setDisabled(true);
- bit_rate_scale_factor_field.setDisabled(true);
+ bit_rate_scale_factor_field.setDisabled(false);
qp_field.setDisabled(true);
break;
}
- low_power_field.setDisabled(false);
break;
case 2:
// AMD --> will allow any combination of parameters
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
// NOTE: filters to be added later
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
- low_power_field.setDisabled(false);
- desired_b_depth_field.setDisabled(false);
+ removeConstrains(form);
break;
default:
}
var rc_mode_field = form.findField('rc_mode');
var low_power_field = form.findField('low_power');
var hwaccel_field = form.findField('hwaccel');
-
+ var ui_field = form.findField('ui');
+ var uilp_field = form.findField('uilp');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var quality_field = form.findField('quality');
+ var ui_value = ui_field.getValue();
+ var uilp_value = uilp_field.getValue();
+
// first time we have to call this manually
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
updateHWFilters(form);
// on platform change
platform_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
});
// on rc_mode change
rc_mode_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
});
// on low_power change
low_power_field.on('check', function(checkbox, value) {
- updateFilters(form);
+ updateLowPower(form);
});
// on hwaccel change
hwaccel_field.on('check', function(checkbox, value) {
updateHWFilters(form);
});
+ // on desired_b_depth change
+ desired_b_depth_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
+ // on quality change
+ quality_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
},
'codec_profile_vaapi_vp8': function(form) {
form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
}
- function updateFilters(form) {
+ function checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field) {
+ // enable max B frames based on ui (vainfo)
+ var uibframe = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uibframe = (uilp_value & 0xe) >> 1
+ }
+ else {
+ // low power is disabled
+ uibframe = (ui_value & 0xe) >> 1
+ }
+ // messagebox if max B grames > VAINFO.max_b_frames
+ if (uibframe) {
+ if (desired_b_depth_field.getValue() > uibframe)
+ alert('VAINFO maximum B fames is: ' + uibframe)
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ }
+ else {
+ desired_b_depth_field.setDisabled(true);
+ b_reference_field.setDisabled(true);
+ }
+ // enable Quality based on ui (vainfo)
+ var uiquality = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uiquality = (uilp_value & 0xf0) >> 4
+ }
+ else {
+ // low power is disabled
+ uiquality = (ui_value & 0xf0) >> 4
+ }
+ // messagebox if Qality > VAINFO.quality
+ if (uiquality > 1) {
+ if (quality_field.getValue() > uiquality)
+ alert('VAINFO maximum Quality is: ' + uiquality)
+ }
+ else {
+ quality_field.setValue(-1);
+ quality_field.setDisabled(true);
+ }
+ }
+
+ function updateLowPower(form) {
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ }
+
+ function removeConstrains(form) {
+ var bit_rate_field = form.findField('bit_rate');
+ var max_bit_rate_field = form.findField('max_bit_rate');
+ var buff_factor_field = form.findField('buff_factor');
+ var bit_rate_scale_factor_field = form.findField('bit_rate_scale_factor');
+ var qp_field = form.findField('qp');
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ bit_rate_field.setDisabled(false);
+ max_bit_rate_field.setDisabled(false);
+ buff_factor_field.setDisabled(false);
+ bit_rate_scale_factor_field.setDisabled(false);
+ qp_field.setDisabled(false);
+ low_power_field.setDisabled(false);
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ quality_field.setDisabled(false);
+ }
+
+ function updateFilters(form, ui_value, uilp_value) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var bit_rate_field = form.findField('bit_rate');
var buff_factor_field = form.findField('buff_factor');
var bit_rate_scale_factor_field = form.findField('bit_rate_scale_factor');
var qp_field = form.findField('qp');
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
var platform = platform_field.getValue();
switch (platform) {
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
// no filter applied
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
+ removeConstrains(form);
break;
case 1:
// Intel
+ // enable low_power mode based on ui (vainfo)
+ if ((ui_value & 0x1) && (uilp_value & 0x1))
+ low_power_field.setDisabled(false);
+ else {
+ low_power_field.setDisabled(true);
+ if (uilp_value & 0x1)
+ // only low power is available
+ low_power_field.setValue(true);
+ if (ui_value & 0x1)
+ // only normal is available
+ low_power_field.setValue(false);
+ }
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ // filter based in rc_mode
var rc_mode = rc_mode_field.getValue();
switch (rc_mode) {
case -1:
bit_rate_field.setDisabled(false);
max_bit_rate_field.setDisabled(false);
buff_factor_field.setDisabled(true);
- bit_rate_scale_factor_field.setDisabled(true);
+ bit_rate_scale_factor_field.setDisabled(false);
qp_field.setDisabled(true);
break;
}
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
// NOTE: filters to be added later
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
+ removeConstrains(form);
break;
default:
}
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
+ var low_power_field = form.findField('low_power');
var hwaccel_field = form.findField('hwaccel');
-
+ var ui_field = form.findField('ui');
+ var uilp_field = form.findField('uilp');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var quality_field = form.findField('quality');
+ var ui_value = ui_field.getValue();
+ var uilp_value = uilp_field.getValue();
+
// first time we have to call this manually
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
updateHWFilters(form);
-
+
// on platform change
platform_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
});
// on rc_mode change
rc_mode_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
+ });
+ // on low_power change
+ low_power_field.on('check', function(checkbox, value) {
+ updateLowPower(form);
});
// on hwaccel change
hwaccel_field.on('check', function(checkbox, value) {
updateHWFilters(form);
});
+ // on desired_b_depth change
+ desired_b_depth_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
+ // on quality change
+ quality_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
},
'codec_profile_vaapi_vp9': function(form) {
form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
}
- function updateFilters(form) {
+ function checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field) {
+ // enable max B frames based on ui (vainfo)
+ var uibframe = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uibframe = (uilp_value & 0xe) >> 1
+ }
+ else {
+ // low power is disabled
+ uibframe = (ui_value & 0xe) >> 1
+ }
+ // messagebox if max B grames > VAINFO.max_b_frames
+ if (uibframe) {
+ if (desired_b_depth_field.getValue() > uibframe)
+ alert('VAINFO maximum B fames is: ' + uibframe)
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ }
+ else {
+ desired_b_depth_field.setDisabled(true);
+ b_reference_field.setDisabled(true);
+ }
+ // enable Quality based on ui (vainfo)
+ var uiquality = 0;
+ if (low_power_field.getValue()) {
+ // low power is enabled
+ uiquality = (uilp_value & 0xf0) >> 4
+ }
+ else {
+ // low power is disabled
+ uiquality = (ui_value & 0xf0) >> 4
+ }
+ // messagebox if Qality > VAINFO.quality
+ if (uiquality > 1) {
+ if (quality_field.getValue() > uiquality)
+ alert('VAINFO maximum Quality is: ' + uiquality)
+ }
+ else {
+ quality_field.setValue(-1);
+ quality_field.setDisabled(true);
+ }
+ }
+
+ function updateLowPower(form) {
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ }
+
+ function removeConstrains(form) {
+ var bit_rate_field = form.findField('bit_rate');
+ var max_bit_rate_field = form.findField('max_bit_rate');
+ var buff_factor_field = form.findField('buff_factor');
+ var bit_rate_scale_factor_field = form.findField('bit_rate_scale_factor');
+ var qp_field = form.findField('qp');
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
+
+ bit_rate_field.setDisabled(false);
+ max_bit_rate_field.setDisabled(false);
+ buff_factor_field.setDisabled(false);
+ bit_rate_scale_factor_field.setDisabled(false);
+ qp_field.setDisabled(false);
+ low_power_field.setDisabled(false);
+ desired_b_depth_field.setDisabled(false);
+ b_reference_field.setDisabled(false);
+ quality_field.setDisabled(false);
+ }
+
+ function updateFilters(form, ui_value, uilp_value) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var bit_rate_field = form.findField('bit_rate');
var buff_factor_field = form.findField('buff_factor');
var bit_rate_scale_factor_field = form.findField('bit_rate_scale_factor');
var qp_field = form.findField('qp');
+ var low_power_field = form.findField('low_power');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var b_reference_field = form.findField('b_reference');
+ var quality_field = form.findField('quality');
var platform = platform_field.getValue();
switch (platform) {
// Unconstrained --> will allow any combination of parameters (valid or invalid)
// this mode is usefull fur future platform and for debugging.
// no filter applied
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
+ removeConstrains(form);
break;
case 1:
// Intel
+ // enable low_power mode based on ui (vainfo)
+ if ((ui_value & 0x1) && (uilp_value & 0x1))
+ low_power_field.setDisabled(false);
+ else {
+ low_power_field.setDisabled(true);
+ if (uilp_value & 0x1)
+ // only low power is available
+ low_power_field.setValue(true);
+ if (ui_value & 0x1)
+ // only normal is available
+ low_power_field.setValue(false);
+ }
+ checkBFrameQuality(low_power_field, desired_b_depth_field, b_reference_field, quality_field);
+ // filter based in rc_mode
var rc_mode = rc_mode_field.getValue();
switch (rc_mode) {
case -1:
bit_rate_field.setDisabled(false);
max_bit_rate_field.setDisabled(false);
buff_factor_field.setDisabled(true);
- bit_rate_scale_factor_field.setDisabled(true);
+ bit_rate_scale_factor_field.setDisabled(false);
qp_field.setDisabled(true);
break;
}
// I am unable to confirm this platform because I don't have the HW
// Is only going to override bf to 0 (as highlited by the previous implementation)
// NOTE: filters to be added later
- bit_rate_field.setDisabled(false);
- max_bit_rate_field.setDisabled(false);
- buff_factor_field.setDisabled(false);
- bit_rate_scale_factor_field.setDisabled(false);
- qp_field.setDisabled(false);
+ removeConstrains(form);
break;
default:
}
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
+ var low_power_field = form.findField('low_power');
var hwaccel_field = form.findField('hwaccel');
-
+ var ui_field = form.findField('ui');
+ var uilp_field = form.findField('uilp');
+ var desired_b_depth_field = form.findField('desired_b_depth');
+ var quality_field = form.findField('quality');
+ var ui_value = ui_field.getValue();
+ var uilp_value = uilp_field.getValue();
+
// first time we have to call this manually
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
updateHWFilters(form);
-
+
// on platform change
platform_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
});
// on rc_mode change
rc_mode_field.on('select', function(combo, record, index) {
- updateFilters(form);
+ updateFilters(form, ui_value, uilp_value);
+ });
+ // on low_power change
+ low_power_field.on('check', function(checkbox, value) {
+ updateLowPower(form);
});
// on hwaccel change
hwaccel_field.on('check', function(checkbox, value) {
updateHWFilters(form);
});
+ // on desired_b_depth change
+ desired_b_depth_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
+ // on quality change
+ quality_field.on('spin', function(spinner, direction, eOpts) {
+ updateFilters(form, ui_value, uilp_value);
+ });
}
};