From: SangWoo Kim Date: Sat, 26 Dec 2015 03:52:30 +0000 (+0900) Subject: WEBUI: add "Video codec preset:" menu in Transcoding-Parameters-Stream Profiles trans... X-Git-Tag: v4.2.1~1282 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4507ae24b794b994c560cf95994bc717c2bfc5e9;p=thirdparty%2Ftvheadend.git WEBUI: add "Video codec preset:" menu in Transcoding-Parameters-Stream Profiles transcoding: use user selected video codec preset for H264,H265,qsv,nvenc transcoding --- diff --git a/src/hts_strtab.h b/src/hts_strtab.h index 936199506..3dcdd80dd 100644 --- a/src/hts_strtab.h +++ b/src/hts_strtab.h @@ -34,6 +34,11 @@ struct strtab_u32 { 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)); @@ -117,4 +122,20 @@ strtab2htsmsg0_u32(const struct strtab_u32 tab[], uint32_t n, int i18n, const ch #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_ */ diff --git a/src/plumbing/transcoding.c b/src/plumbing/transcoding.c index a3f1ece65..568f908b1 100644 --- a/src/plumbing/transcoding.c +++ b/src/plumbing/transcoding.c @@ -1331,12 +1331,9 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt) 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); @@ -1365,7 +1362,10 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt) 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); @@ -2065,6 +2065,7 @@ transcoder_set_properties(streaming_target_t *st, 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; diff --git a/src/plumbing/transcoding.h b/src/plumbing/transcoding.h index 10591a91f..9b2871ca7 100644 --- a/src/plumbing/transcoding.h +++ b/src/plumbing/transcoding.h @@ -22,6 +22,7 @@ typedef struct transcoder_prop { char tp_vcodec[32]; + char tp_vcodec_preset[32]; char tp_acodec[32]; char tp_scodec[32]; diff --git a/src/profile.c b/src/profile.c index 4d3423316..47483c45d 100644 --- a/src/profile.c +++ b/src/profile.c @@ -1414,6 +1414,7 @@ typedef struct profile_transcode { uint32_t pro_abitrate; char *pro_language; char *pro_vcodec; + char *pro_vcodec_preset; char *pro_acodec; char *pro_scodec; } profile_transcode_t; @@ -1539,6 +1540,31 @@ profile_class_vcodec_list(void *o, const char *lang) 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) { @@ -1626,6 +1652,16 @@ const idclass_t profile_transcode_class = .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", @@ -1703,6 +1739,8 @@ profile_transcode_can_share(profile_chain_t *prch, */ 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 ?: "")) @@ -1735,6 +1773,7 @@ profile_transcode_work(profile_chain_t *prch, 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); @@ -1836,6 +1875,7 @@ profile_transcode_free(profile_t *_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); } @@ -1960,6 +2000,7 @@ profile_init(void) 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); @@ -1980,6 +2021,7 @@ profile_init(void) 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); @@ -2000,6 +2042,7 @@ profile_init(void) 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);