uint32_t val;
};
+struct strtab_str {
+ const char *str;
+ const char *val;
+};
+
static int str2val0(const char *str, const struct strtab tab[], int l)
__attribute((unused));
#define strtab2htsmsg_u32(tab,i18n,lang) strtab2htsmsg0_u32(tab, sizeof(tab) / sizeof(tab[0]), i18n, lang)
+static inline htsmsg_t *
+strtab2htsmsg0_str(const struct strtab_str tab[], uint32_t n, int i18n, const char *lang)
+{
+ uint32_t i;
+ htsmsg_t *e, *l = htsmsg_create_list();
+ for (i = 0; i < n; i++) {
+ e = htsmsg_create_map();
+ htsmsg_add_str(e, "key", tab[i].val);
+ htsmsg_add_str(e, "val", i18n ? tvh_gettext_lang(lang, tab[i].str) : tab[i].str);
+ htsmsg_add_msg(l, NULL, e);
+ }
+ return l;
+}
+
+#define strtab2htsmsg_str(tab,i18n,lang) strtab2htsmsg0_str(tab, sizeof(tab) / sizeof(tab[0]), i18n, lang)
+
#endif /* STRTAB_H_ */
octx->flags |= CODEC_FLAG_GLOBAL_HEADER;
// Default = "medium". We gain more encoding speed compared to the loss of quality when lowering it _slightly_.
- if (!strcmp(ocodec->name, "nvenc"))
- av_dict_set(&opts, "preset", "hq", 0);
- else if (!strcmp(ocodec->name, "h264_qsv"))
- av_dict_set(&opts, "preset", "medium", 0);
- else
- av_dict_set(&opts, "preset", "faster", 0);
+ // select preset according to system performance and codec type
+ av_dict_set(&opts, "preset", t->t_props.tp_vcodec_preset, 0);
+ tvhinfo("transcode", "%04X: Using preset %s", shortid(t), t->t_props.tp_vcodec_preset);
// All modern devices should support "high" profile
av_dict_set(&opts, "profile", "high", 0);
octx->flags |= CODEC_FLAG_GLOBAL_HEADER;
// on all hardware ultrafast (or maybe superfast) should be safe
- av_dict_set(&opts, "preset", "ultrafast", 0);
+ // select preset according to system performance
+ av_dict_set(&opts, "preset", t->t_props.tp_vcodec_preset, 0);
+ tvhinfo("transcode", "%04X: Using preset %s", shortid(t), t->t_props.tp_vcodec_preset);
+
// disables encoder features which tend to be bottlenecks for the decoder/player
av_dict_set(&opts, "tune", "fastdecode", 0);
transcoder_props_t *tp = &t->t_props;
strncpy(tp->tp_vcodec, props->tp_vcodec, sizeof(tp->tp_vcodec)-1);
+ strncpy(tp->tp_vcodec_preset, props->tp_vcodec_preset, sizeof(tp->tp_vcodec_preset)-1);
strncpy(tp->tp_acodec, props->tp_acodec, sizeof(tp->tp_acodec)-1);
strncpy(tp->tp_scodec, props->tp_scodec, sizeof(tp->tp_scodec)-1);
tp->tp_channels = props->tp_channels;
uint32_t pro_abitrate;
char *pro_language;
char *pro_vcodec;
+ char *pro_vcodec_preset;
char *pro_acodec;
char *pro_scodec;
} profile_transcode_t;
return profile_class_codec_list(profile_class_vcodec_sct_check, lang);
}
+static htsmsg_t *
+profile_class_vcodec_preset_list(void *o, const char *lang)
+{
+ static const struct strtab_str tab[] = {
+ {N_("ultrafast: h264 / h265") , "ultrafast" },
+ {N_("superfast: h264 / h265") , "superfast" },
+ {N_("veryfast: h264 / h265 / qsv(h264)") , "veryfast" },
+ {N_("faster: h264 / h265 / qsv(h264)") , "faster" },
+ {N_("fast: h264 / h265 / qsv(h264 / h265)") , "fast" },
+ {N_("medium: h264 / h265 / qsv(h264 / h265)") , "medium" },
+ {N_("slow: h264 / h265 / qsv(h264 / h265)") , "slow" },
+ {N_("slower: h264 / h265 / qsv(h264)") , "slower" },
+ {N_("veryslow: h264 / h265 / qsv(h264)") , "veryslow" },
+ {N_("placebo: h264 / h265") , "placebo" },
+ {N_("hq: nvenc(h264 / h265)") , "hq" },
+ {N_("hp: nvenc(h264 / h265)") , "hp" },
+ {N_("bd: nvenc(h264 / h265)") , "bd" },
+ {N_("ll: nvenc(h264 / h265)") , "ll" },
+ {N_("llhq: nvenc(h264 / h265)") , "llhq" },
+ {N_("llhp: nvenc(h264 / h265)") , "llhp" },
+ {N_("default: nvenc(h264 / h265)") , "default" }
+ };
+ return strtab2htsmsg_str(tab, 1, lang);
+}
+
static int
profile_class_acodec_sct_check(int sct)
{
.opts = PO_ADVANCED,
.group = 2
},
+ {
+ .type = PT_STR,
+ .id = "vcodec_preset",
+ .name = N_("Video codec preset"),
+ .off = offsetof(profile_transcode_t, pro_vcodec_preset),
+ .def.s = "faster",
+ .list = profile_class_vcodec_preset_list,
+ .opts = PO_ADVANCED,
+ .group = 2
+ },
{
.type = PT_U32,
.id = "vbitrate",
*/
if (strcmp(pro1->pro_vcodec ?: "", pro2->pro_vcodec ?: ""))
return 0;
+ if (strcmp(pro1->pro_vcodec_preset ?: "", pro2->pro_vcodec_preset ?: ""))
+ return 0;
if (strcmp(pro1->pro_acodec ?: "", pro2->pro_acodec ?: ""))
return 0;
if (strcmp(pro1->pro_scodec ?: "", pro2->pro_scodec ?: ""))
memset(&props, 0, sizeof(props));
strncpy(props.tp_vcodec, pro->pro_vcodec ?: "", sizeof(props.tp_vcodec)-1);
+ strncpy(props.tp_vcodec_preset, pro->pro_vcodec_preset ?: "", sizeof(props.tp_vcodec_preset)-1);
strncpy(props.tp_acodec, pro->pro_acodec ?: "", sizeof(props.tp_acodec)-1);
strncpy(props.tp_scodec, pro->pro_scodec ?: "", sizeof(props.tp_scodec)-1);
props.tp_resolution = profile_transcode_resolution(pro);
{
profile_transcode_t *pro = (profile_transcode_t *)_pro;
free(pro->pro_vcodec);
+ free(pro->pro_vcodec_preset);
free(pro->pro_acodec);
free(pro->pro_scodec);
}
htsmsg_add_u32 (conf, "resolution", 384);
htsmsg_add_u32 (conf, "channels", 2);
htsmsg_add_str (conf, "vcodec", "libvpx");
+ htsmsg_add_str (conf, "vcodec_preset", "faster");
htsmsg_add_str (conf, "acodec", "libvorbis");
htsmsg_add_bool(conf, "shield", 1);
(void)profile_create(NULL, conf, 1);
htsmsg_add_u32 (conf, "resolution", 384);
htsmsg_add_u32 (conf, "channels", 2);
htsmsg_add_str (conf, "vcodec", "libx264");
+ htsmsg_add_str (conf, "vcodec_preset", "faster");
htsmsg_add_str (conf, "acodec", "aac");
htsmsg_add_bool(conf, "shield", 1);
(void)profile_create(NULL, conf, 1);
htsmsg_add_u32 (conf, "resolution", 384);
htsmsg_add_u32 (conf, "channels", 2);
htsmsg_add_str (conf, "vcodec", "libx264");
+ htsmsg_add_str (conf, "vcodec_preset", "faster");
htsmsg_add_str (conf, "acodec", "aac");
htsmsg_add_bool(conf, "shield", 1);
(void)profile_create(NULL, conf, 1);