]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
transcode: added h264_nvenc and hevc_nvenc codecs (untested)
authorJaroslav Kysela <perex@perex.cz>
Mon, 4 Sep 2017 14:49:43 +0000 (16:49 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 4 Sep 2017 15:06:03 +0000 (17:06 +0200)
Makefile
Makefile.ffmpeg
configure
src/transcoding/codec/codec.c
src/transcoding/codec/codecs/libs/nvenc.c [new file with mode: 0644]

index b8f0f6944f69f57171c99993971ff8edead07684..531f5e265848418deb26098ac95fe0bdec0295b3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -499,6 +499,9 @@ endif
 ifeq ($(CONFIG_VAAPI),yes)
 LIBS-CODECS += vaapi
 endif
+ifeq ($(CONFIG_NVENC),yes)
+LIBS-CODECS += nvenc
+endif
 ifeq ($(CONFIG_OMX),yes)
 LIBS-CODECS += omx
 endif
index 450014d5e23e362e01e57d0b0fe0a9dd9a978835..8ae182966cec4f53776c96cc458c020af011f130 100644 (file)
@@ -542,7 +542,7 @@ endif
 ifeq (yes,$(CONFIG_NVENC))
 
 EXTLIBS  += nvenc
-ENCODERS += nvenc_h264 nvenc_hevc
+ENCODERS += h264_nvenc hevc_nvenc
 
 endif
 
index 231df23477bff34c33f1fdcb112b8b923ac00124..8cd4d588b09dde62de26c215543208d260440989 100755 (executable)
--- a/configure
+++ b/configure
@@ -534,10 +534,12 @@ if enabled ffmpeg_static; then
   fi
 
   # nvenc
-  if enabled nvenc; then
-    check_cc_header nvEncodeAPI || \
-      die "NVENC library (https://developer.nvidia.com/nvidia-video-codec-sdk) not found"
-  fi
+  # latest ffmpeg has own code
+  enable nvenc
+  #if enabled nvenc; then
+  #  check_cc_header nvEncodeAPI || \
+  #    die "NVENC library (https://developer.nvidia.com/nvidia-video-codec-sdk) not found"
+  #fi
 
   # omx
   if enabled omx; then
index bcf58c424894694f8440f8c6275547e9b12b5e64..eee2956e15d557f5812c7f68d33754bdb026b1b3 100644 (file)
@@ -64,6 +64,11 @@ extern TVHCodec tvh_codec_vaapi_hevc;
 extern TVHCodec tvh_codec_vaapi_vp8;
 #endif
 
+#if ENABLE_NVENC
+extern TVHCodec tvh_codec_nvenc_h264;
+extern TVHCodec tvh_codec_nvenc_hevc;
+#endif
+
 #if ENABLE_OMX
 extern TVHCodec tvh_codec_omx_h264;
 #endif
@@ -279,6 +284,11 @@ tvh_codecs_register()
     tvh_codec_register(&tvh_codec_vaapi_vp8);
 #endif
 
+#if ENABLE_NVENC
+    tvh_codec_register(&tvh_codec_nvenc_h264);
+    tvh_codec_register(&tvh_codec_nvenc_hevc);
+#endif
+
 #if ENABLE_OMX
     tvh_codec_register(&tvh_codec_omx_h264);
 #endif
diff --git a/src/transcoding/codec/codecs/libs/nvenc.c b/src/transcoding/codec/codecs/libs/nvenc.c
new file mode 100644 (file)
index 0000000..4acbb28
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ *  tvheadend - Codec Profiles
+ *
+ *  Copyright (C) 2017 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 "transcoding/codec/internals.h"
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#define PRESET_DEFAULT               0
+#define PRESET_SLOW                  1
+#define PRESET_MEDIUM                2
+#define PRESET_FAST                  3
+#define PRESET_HP                    4
+#define PRESET_HQ                    5
+#define PRESET_BD                    6
+#define PRESET_LOW_LATENCY_DEFAULT   7
+#define PRESET_LOW_LATENCY_HQ        8
+#define PRESET_LOW_LATENCY_HP        9
+#define PRESET_LOSSLESS_DEFAULT      10
+#define PRESET_LOSSLESS_HP           11
+
+#define NV_ENC_PARAMS_RC_AUTO                  0
+#define NV_ENC_PARAMS_RC_CONSTQP               1
+#define NV_ENC_PARAMS_RC_VBR                   2
+#define NV_ENC_PARAMS_RC_CBR                   3
+#define NV_ENC_PARAMS_RC_VBR_MINQP             4
+#define NV_ENC_PARAMS_RC_2_PASS_QUALITY        5
+#define NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP  6
+#define NV_ENC_PARAMS_RC_2_PASS_VBR            7
+
+#define AV_DICT_SET_CQ(d, v, a) \
+    AV_DICT_SET_INT((d), "cq", (v) ? (v) : (a), AV_DICT_DONT_OVERWRITE)
+
+
+/* nvenc ==================================================================== */
+
+typedef struct {
+    TVHVideoCodecProfile;
+    int nvenc_profile;
+    int devicenum;
+    int preset;
+    int rc;
+    int quality;
+} tvh_codec_profile_nvenc_t;
+
+static int
+tvh_codec_profile_nvenc_open(tvh_codec_profile_nvenc_t *self,
+                             AVDictionary **opts)
+{
+    static const struct strtab presettab[] = {
+        {"default",     PRESET_DEFAULT},
+        {"slow",        PRESET_SLOW},
+        {"medium",      PRESET_MEDIUM},
+        {"fast",        PRESET_FAST},
+        {"hp",         PRESET_HP},
+        {"hq",         PRESET_HQ},
+        {"bd",         PRESET_BD},
+        {"ll",         PRESET_LOW_LATENCY_DEFAULT},
+        {"llhq",       PRESET_LOW_LATENCY_HQ},
+        {"llhp",       PRESET_LOW_LATENCY_HP},
+        {"lossless",   PRESET_LOSSLESS_DEFAULT},
+        {"losslesshp", PRESET_LOSSLESS_HP},
+    };
+    static const struct strtab rctab[] = {
+        {"constqp",          NV_ENC_PARAMS_RC_CONSTQP},
+        {"vbr",               NV_ENC_PARAMS_RC_VBR},
+        {"cbr",               NV_ENC_PARAMS_RC_CBR},
+        {"vbr_minqp",         NV_ENC_PARAMS_RC_VBR_MINQP},
+        {"ll_2pass_quality",  NV_ENC_PARAMS_RC_2_PASS_QUALITY},
+        {"ll_2pass_size",     NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP},
+        {"vbr_2pass",         NV_ENC_PARAMS_RC_2_PASS_VBR},
+    };
+    const char *s;
+
+    AV_DICT_SET_INT(opts, "gpu", MINMAX(self->devicenum, 0, 15), 0);
+    if (self->preset != PRESET_DEFAULT &&
+        (s = val2str(self->profile, presettab)) != NULL) {
+        AV_DICT_SET(opts, "preset", s, 0);
+    }
+    if (self->rc != NV_ENC_PARAMS_RC_AUTO &&
+        (s = val2str(self->rc, rctab)) != NULL) {
+        AV_DICT_SET(opts, "rc", s, 0);
+    }
+    if (self->bit_rate) {
+        AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
+    }
+    AV_DICT_SET_INT(opts, "quality", self->quality, 0);
+    return 0;
+}
+
+static htsmsg_t *
+codec_profile_nvenc_class_profile_list(void *obj, const char *lang)
+{
+    TVHCodec *codec = tvh_codec_profile_get_codec(obj);
+    return tvh_codec_get_list(codec, profiles);
+}
+
+static htsmsg_t *
+codec_profile_nvenc_class_preset_list(void *obj, const char *lang)
+{
+    static const struct strtab tab[] = {
+        {N_("Default"),                PRESET_DEFAULT},
+        {N_("Slow"),           PRESET_SLOW},
+        {N_("Medium"),         PRESET_MEDIUM},
+        {N_("Fast"),           PRESET_FAST},
+        {N_("HP"),             PRESET_HP},
+        {N_("HQ"),             PRESET_HQ},
+        {N_("BD"),             PRESET_BD},
+        {N_("Low latency"),    PRESET_LOW_LATENCY_DEFAULT},
+        {N_("Low latency HQ"), PRESET_LOW_LATENCY_HQ},
+        {N_("Low latency HP"), PRESET_LOW_LATENCY_HP},
+        {N_("Lossless"),       PRESET_LOSSLESS_DEFAULT},
+        {N_("Lossless HP"),    PRESET_LOSSLESS_HP},
+    };
+    return strtab2htsmsg(tab, 1, lang);
+}
+
+static htsmsg_t *
+codec_profile_nvenc_class_rc_list(void *obj, const char *lang)
+{
+    static const struct strtab tab[] = {
+        {N_("Auto"),                             NV_ENC_PARAMS_RC_AUTO},
+        {N_("Constant QP mode"),                 NV_ENC_PARAMS_RC_CONSTQP},
+        {N_("VBR mode"),                         NV_ENC_PARAMS_RC_VBR},
+        {N_("CBR mode"),                         NV_ENC_PARAMS_RC_CBR},
+        {N_("VBR mode with MinQP"),              NV_ENC_PARAMS_RC_VBR_MINQP},
+        {N_("VBR multi-pass LL quality mode"),           NV_ENC_PARAMS_RC_2_PASS_QUALITY},
+        {N_("VBR multi-pass LL frame size mode"), NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP},
+        {N_("VBR multi-pass mode"),              NV_ENC_PARAMS_RC_2_PASS_VBR},
+    };
+    return strtab2htsmsg(tab, 1, lang);
+}
+
+static const codec_profile_class_t codec_profile_nvenc_class = {
+    {
+        .ic_super      = (idclass_t *)&codec_profile_video_class,
+        .ic_class      = "codec_profile_nvenc",
+        .ic_caption    = N_("nvenc"),
+        .ic_properties = (const property_t[]){
+            {
+                .type     = PT_INT,
+                .id       = "devicenum",
+                .name     = N_("GPU number"),
+                .group    = 3,
+                .desc     = N_("GPU number (starts with zero)."),
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_nvenc_t, devicenum),
+            },
+            {
+                .type     = PT_INT,
+                .id       = "profile",
+                .name     = N_("Profile"),
+                .desc     = N_("Profile."),
+                .group    = 4,
+                .opts     = PO_ADVANCED | PO_PHIDDEN,
+                .get_opts = codec_profile_class_profile_get_opts,
+                .off      = offsetof(tvh_codec_profile_nvenc_t, nvenc_profile),
+                .list     = codec_profile_nvenc_class_profile_list,
+                .def.i    = FF_PROFILE_UNKNOWN,
+            },
+            {
+                .type     = PT_INT,
+                .id       = "preset",
+                .name     = N_("Preset"),
+                .group    = 3,
+                .desc     = N_("Override the preset rate control."),
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_nvenc_t, preset),
+                .list     = codec_profile_nvenc_class_preset_list,
+                .def.i    = PRESET_DEFAULT,
+            },
+            {
+                .type     = PT_DBL,
+                .id       = "bit_rate",
+                .name     = N_("Bitrate (kb/s) (0=auto)"),
+                .desc     = N_("Target bitrate."),
+                .group    = 3,
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(TVHCodecProfile, bit_rate),
+                .def.d    = 0,
+            },
+            {
+                .type     = PT_INT,
+                .id       = "quality",
+                .name     = N_("Quality (0=auto)"),
+                .desc     = N_("Set encode quality (trades off against speed, "
+                               "higher is faster) [0-51]."),
+                .group    = 5,
+                .opts     = PO_EXPERT,
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_nvenc_t, quality),
+                .intextra = INTEXTRA_RANGE(0, 51, 1),
+                .def.i    = 0,
+            },
+            {
+                .type     = PT_INT,
+                .id       = "rc",
+                .name     = N_("Rate control"),
+                .group    = 3,
+                .desc     = N_("Override the preset rate control."),
+                .opts     = PO_EXPERT,
+                .off      = offsetof(tvh_codec_profile_nvenc_t, rc),
+                .list     = codec_profile_nvenc_class_rc_list,
+                .def.i    = NV_ENC_PARAMS_RC_AUTO,
+            },
+            {}
+        }
+    },
+    .open = (codec_profile_open_meth)tvh_codec_profile_nvenc_open,
+};
+
+
+/* h264_nvenc =============================================================== */
+
+static const AVProfile nvenc_h264_profiles[] = {
+    { FF_PROFILE_H264_BASELINE,             "Baseline" },
+    { FF_PROFILE_H264_MAIN,                 "Main" },
+    { FF_PROFILE_H264_HIGH,                 "High" },
+    { FF_PROFILE_H264_HIGH_444_PREDICTIVE,  "High 444P" },
+    { FF_PROFILE_UNKNOWN },
+};
+
+static int
+tvh_codec_profile_nvenc_h264_open(tvh_codec_profile_nvenc_t *self,
+                                  AVDictionary **opts)
+{
+    static const struct strtab profiletab[] = {
+        {"baseline",    FF_PROFILE_H264_BASELINE},
+        {"main",        FF_PROFILE_H264_MAIN},
+        {"high",        FF_PROFILE_H264_HIGH,},
+        {"high444p",    FF_PROFILE_H264_HIGH_444_PREDICTIVE},
+    };
+    const char *s;
+
+    if (self->nvenc_profile != FF_PROFILE_UNKNOWN &&
+        (s = val2str(self->nvenc_profile, profiletab)) != NULL)
+      AV_DICT_SET(opts, "profile", s, 0);
+    return 0;
+}
+
+
+static const codec_profile_class_t codec_profile_nvenc_h264_class = {
+    {
+        .ic_super      = (idclass_t *)&codec_profile_nvenc_class,
+        .ic_class      = "codec_profile_nvenc_h264",
+        .ic_caption    = N_("nvenc_h264"),
+        .ic_properties = (const property_t[]){
+            {}
+        }
+    },
+    .open = (codec_profile_open_meth)tvh_codec_profile_nvenc_h264_open,
+};
+
+
+TVHVideoCodec tvh_codec_nvenc_h264 = {
+    .name     = "h264_nvenc",
+    .size     = sizeof(tvh_codec_profile_nvenc_t),
+    .idclass  = &codec_profile_nvenc_h264_class,
+    .profiles = nvenc_h264_profiles,
+};
+
+
+/* hevc_nvenc =============================================================== */
+
+static const AVProfile nvenc_hevc_profiles[] = {
+    { FF_PROFILE_HEVC_MAIN,    "Main" },
+    { FF_PROFILE_HEVC_MAIN_10, "Main 10" },
+    { FF_PROFILE_UNKNOWN },
+};
+
+static int
+tvh_codec_profile_nvenc_hevc_open(tvh_codec_profile_nvenc_t *self,
+                                  AVDictionary **opts)
+{
+    static const struct strtab profiletab[] = {
+        {"main",        FF_PROFILE_HEVC_MAIN},
+        {"main10",      FF_PROFILE_HEVC_MAIN_10,},
+    };
+    const char *s;
+
+    if (self->nvenc_profile != FF_PROFILE_UNKNOWN &&
+        (s = val2str(self->nvenc_profile, profiletab)) != NULL)
+      AV_DICT_SET(opts, "profile", s, 0);
+    return 0;
+}
+
+
+static const codec_profile_class_t codec_profile_nvenc_hevc_class = {
+    {
+        .ic_super      = (idclass_t *)&codec_profile_nvenc_class,
+        .ic_class      = "codec_profile_nvenc_hevc",
+        .ic_caption    = N_("nvenc_hevc")
+    },
+    .open = (codec_profile_open_meth)tvh_codec_profile_nvenc_hevc_open,
+};
+
+
+TVHVideoCodec tvh_codec_nvenc_hevc = {
+    .name     = "hevc_nvenc",
+    .size     = sizeof(tvh_codec_profile_nvenc_t),
+    .idclass  = &codec_profile_nvenc_hevc_class,
+    .profiles = nvenc_hevc_profiles,
+    .profile_init = tvh_codec_profile_video_init,
+};