nvenc-properties.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "nvenc-internal.h"
  2. void nvenc_properties_read(struct nvenc_properties *props, obs_data_t *settings)
  3. {
  4. props->bitrate = obs_data_get_int(settings, "bitrate");
  5. props->max_bitrate = obs_data_get_int(settings, "max_bitrate");
  6. props->keyint_sec = obs_data_get_int(settings, "keyint_sec");
  7. props->cqp = obs_data_get_int(settings, "cqp");
  8. props->device = obs_data_get_int(settings, "device");
  9. props->bf = obs_data_get_int(settings, "bf");
  10. props->bframe_ref_mode = obs_data_get_int(settings, "bframe_ref_mode");
  11. props->split_encode = obs_data_get_int(settings, "split_encode");
  12. props->target_quality = obs_data_get_int(settings, "target_quality");
  13. props->rate_control = obs_data_get_string(settings, "rate_control");
  14. props->preset = obs_data_get_string(settings, "preset");
  15. props->profile = obs_data_get_string(settings, "profile");
  16. props->tune = obs_data_get_string(settings, "tune");
  17. props->multipass = obs_data_get_string(settings, "multipass");
  18. props->adaptive_quantization = obs_data_get_bool(settings, "adaptive_quantization");
  19. props->lookahead = obs_data_get_bool(settings, "lookahead");
  20. props->disable_scenecut = obs_data_get_bool(settings, "disable_scenecut");
  21. props->repeat_headers = obs_data_get_bool(settings, "repeat_headers");
  22. props->force_cuda_tex = obs_data_get_bool(settings, "force_cuda_tex");
  23. if (obs_data_has_user_value(settings, "opts")) {
  24. props->opts_str = obs_data_get_string(settings, "opts");
  25. props->opts = obs_parse_options(props->opts_str);
  26. }
  27. /* Retain settings object until destroyed since we use its strings. */
  28. obs_data_addref(settings);
  29. props->data = settings;
  30. }
  31. static void nvenc_defaults_base(enum codec_type codec, obs_data_t *settings)
  32. {
  33. struct encoder_caps *caps = get_encoder_caps(codec);
  34. obs_data_set_default_int(settings, "bitrate", 10000);
  35. obs_data_set_default_int(settings, "max_bitrate", 10000);
  36. obs_data_set_default_int(settings, "target_quality", 20);
  37. obs_data_set_default_int(settings, "keyint_sec", 0);
  38. obs_data_set_default_int(settings, "cqp", 20);
  39. obs_data_set_default_int(settings, "device", -1);
  40. obs_data_set_default_int(settings, "bf", caps->bframes > 0 ? 2 : 0);
  41. obs_data_set_default_string(settings, "rate_control", "cbr");
  42. obs_data_set_default_string(settings, "preset", "p5");
  43. obs_data_set_default_string(settings, "multipass", "qres");
  44. obs_data_set_default_string(settings, "tune", "hq");
  45. obs_data_set_default_string(settings, "profile", codec != CODEC_H264 ? "main" : "high");
  46. obs_data_set_default_bool(settings, "adaptive_quantization", true);
  47. obs_data_set_default_bool(settings, "lookahead", caps->lookahead);
  48. /* Hidden options */
  49. obs_data_set_default_bool(settings, "repeat_headers", false);
  50. obs_data_set_default_bool(settings, "force_cuda_tex", false);
  51. obs_data_set_default_bool(settings, "disable_scenecut", false);
  52. }
  53. void h264_nvenc_defaults(obs_data_t *settings)
  54. {
  55. nvenc_defaults_base(CODEC_H264, settings);
  56. }
  57. #ifdef ENABLE_HEVC
  58. void hevc_nvenc_defaults(obs_data_t *settings)
  59. {
  60. nvenc_defaults_base(CODEC_HEVC, settings);
  61. }
  62. #endif
  63. void av1_nvenc_defaults(obs_data_t *settings)
  64. {
  65. nvenc_defaults_base(CODEC_AV1, settings);
  66. }
  67. static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, obs_data_t *settings)
  68. {
  69. const char *rc = obs_data_get_string(settings, "rate_control");
  70. bool cqp = strcmp(rc, "CQP") == 0;
  71. bool vbr = strcmp(rc, "VBR") == 0;
  72. bool cqvbr = strcmp(rc, "CQVBR") == 0;
  73. bool lossless = strcmp(rc, "lossless") == 0;
  74. p = obs_properties_get(ppts, "bitrate");
  75. obs_property_set_visible(p, !cqp && !lossless && !cqvbr);
  76. p = obs_properties_get(ppts, "max_bitrate");
  77. obs_property_set_visible(p, vbr || cqvbr);
  78. p = obs_properties_get(ppts, "target_quality");
  79. obs_property_set_visible(p, cqvbr);
  80. p = obs_properties_get(ppts, "cqp");
  81. obs_property_set_visible(p, cqp);
  82. p = obs_properties_get(ppts, "preset");
  83. obs_property_set_visible(p, !lossless);
  84. p = obs_properties_get(ppts, "tune");
  85. obs_property_set_visible(p, !lossless);
  86. p = obs_properties_get(ppts, "adaptive_quantization");
  87. obs_property_set_visible(p, !lossless);
  88. return true;
  89. }
  90. obs_properties_t *nvenc_properties_internal(enum codec_type codec)
  91. {
  92. obs_properties_t *props = obs_properties_create();
  93. obs_property_t *p;
  94. struct encoder_caps *caps = get_encoder_caps(codec);
  95. p = obs_properties_add_list(props, "rate_control", obs_module_text("RateControl"), OBS_COMBO_TYPE_LIST,
  96. OBS_COMBO_FORMAT_STRING);
  97. obs_property_list_add_string(p, obs_module_text("CBR"), "CBR");
  98. obs_property_list_add_string(p, obs_module_text("CQP"), "CQP");
  99. obs_property_list_add_string(p, obs_module_text("VBR"), "VBR");
  100. obs_property_list_add_string(p, obs_module_text("CQVBR"), "CQVBR");
  101. if (caps->lossless) {
  102. obs_property_list_add_string(p, obs_module_text("Lossless"), "lossless");
  103. }
  104. obs_property_set_modified_callback(p, rate_control_modified);
  105. p = obs_properties_add_int(props, "bitrate", obs_module_text("Bitrate"), 50, UINT32_MAX / 1000, 50);
  106. obs_property_int_set_suffix(p, " Kbps");
  107. obs_properties_add_int(props, "target_quality", obs_module_text("TargetQuality"), 1,
  108. codec == CODEC_AV1 ? 63 : 51, 1);
  109. p = obs_properties_add_int(props, "max_bitrate", obs_module_text("MaxBitrate"), 0, UINT32_MAX / 1000, 50);
  110. obs_property_int_set_suffix(p, " Kbps");
  111. /* AV1 uses 0-255 instead of 0-51 for QP, and most implementations just
  112. * multiply the value by 4 to keep the range smaller. */
  113. obs_properties_add_int(props, "cqp", obs_module_text("CQP"), 1, codec == CODEC_AV1 ? 63 : 51, 1);
  114. p = obs_properties_add_int(props, "keyint_sec", obs_module_text("KeyframeIntervalSec"), 0, 10, 1);
  115. obs_property_int_set_suffix(p, " s");
  116. p = obs_properties_add_list(props, "preset", obs_module_text("Preset"), OBS_COMBO_TYPE_LIST,
  117. OBS_COMBO_FORMAT_STRING);
  118. #define add_preset(val) obs_property_list_add_string(p, obs_module_text("Preset." val), val)
  119. add_preset("p1");
  120. add_preset("p2");
  121. add_preset("p3");
  122. add_preset("p4");
  123. add_preset("p5");
  124. add_preset("p6");
  125. add_preset("p7");
  126. #undef add_preset
  127. p = obs_properties_add_list(props, "tune", obs_module_text("Tuning"), OBS_COMBO_TYPE_LIST,
  128. OBS_COMBO_FORMAT_STRING);
  129. #define add_tune(val) obs_property_list_add_string(p, obs_module_text("Tuning." val), val)
  130. /* The UHQ tune is only supported on Turing or later. */
  131. if (caps->uhq)
  132. add_tune("uhq");
  133. add_tune("hq");
  134. add_tune("ll");
  135. add_tune("ull");
  136. #undef add_tune
  137. p = obs_properties_add_list(props, "multipass", obs_module_text("Multipass"), OBS_COMBO_TYPE_LIST,
  138. OBS_COMBO_FORMAT_STRING);
  139. #define add_multipass(val) obs_property_list_add_string(p, obs_module_text("Multipass." val), val)
  140. add_multipass("disabled");
  141. add_multipass("qres");
  142. add_multipass("fullres");
  143. #undef add_multipass
  144. p = obs_properties_add_list(props, "profile", obs_module_text("Profile"), OBS_COMBO_TYPE_LIST,
  145. OBS_COMBO_FORMAT_STRING);
  146. #define add_profile(val) obs_property_list_add_string(p, val, val)
  147. if (codec == CODEC_HEVC) {
  148. if (caps->ten_bit)
  149. add_profile("main10");
  150. add_profile("main");
  151. } else if (codec == CODEC_AV1) {
  152. add_profile("main");
  153. } else {
  154. #ifdef NVENC_13_0_OR_LATER
  155. if (caps->ten_bit)
  156. add_profile("high10");
  157. #endif
  158. add_profile("high");
  159. add_profile("main");
  160. add_profile("baseline");
  161. }
  162. #undef add_profile
  163. p = obs_properties_add_bool(props, "lookahead", obs_module_text("LookAhead"));
  164. obs_property_set_long_description(p, obs_module_text("LookAhead.ToolTip"));
  165. p = obs_properties_add_bool(props, "adaptive_quantization", obs_module_text("AdaptiveQuantization"));
  166. obs_property_set_long_description(p, obs_module_text("AdaptiveQuantization.ToolTip"));
  167. if (num_encoder_devices() > 1) {
  168. obs_properties_add_int(props, "device", obs_module_text("GPU"), -1, num_encoder_devices(), 1);
  169. }
  170. if (caps->bframes > 0) {
  171. obs_properties_add_int(props, "bf", obs_module_text("BFrames"), 0, caps->bframes, 1);
  172. }
  173. /* H.264 supports this, but seems to cause issues with some decoders,
  174. * so restrict it to the custom options field for now. */
  175. if (caps->bref_modes && codec != CODEC_H264) {
  176. p = obs_properties_add_list(props, "bframe_ref_mode", obs_module_text("BFrameRefMode"),
  177. OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
  178. obs_property_list_add_int(p, obs_module_text("BframeRefMode.Disabled"),
  179. NV_ENC_BFRAME_REF_MODE_DISABLED);
  180. if (caps->bref_modes & 1) {
  181. obs_property_list_add_int(p, obs_module_text("BframeRefMode.Each"),
  182. NV_ENC_BFRAME_REF_MODE_EACH);
  183. }
  184. if (caps->bref_modes & 2) {
  185. obs_property_list_add_int(p, obs_module_text("BframeRefMode.Middle"),
  186. NV_ENC_BFRAME_REF_MODE_MIDDLE);
  187. }
  188. }
  189. #ifdef NVENC_12_1_OR_LATER
  190. /* Some older GPUs such as the 1080 Ti have 2 NVENC chips, but do not
  191. * support split encoding. Therefore, we check for AV1 support here to
  192. * make sure this option is only presented on 40-series and later. */
  193. if (is_codec_supported(CODEC_AV1) && caps->engines > 1 && !has_broken_split_encoding() &&
  194. (codec == CODEC_HEVC || codec == CODEC_AV1)) {
  195. p = obs_properties_add_list(props, "split_encode", obs_module_text("SplitEncode"), OBS_COMBO_TYPE_LIST,
  196. OBS_COMBO_FORMAT_INT);
  197. obs_property_list_add_int(p, obs_module_text("SplitEncode.Auto"), NV_ENC_SPLIT_AUTO_MODE);
  198. obs_property_list_add_int(p, obs_module_text("SplitEncode.Disabled"), NV_ENC_SPLIT_DISABLE_MODE);
  199. obs_property_list_add_int(p, obs_module_text("SplitEncode.Enabled"), NV_ENC_SPLIT_TWO_FORCED_MODE);
  200. if (caps->engines > 2) {
  201. obs_property_list_add_int(p, obs_module_text("SplitEncode.ThreeWay"),
  202. NV_ENC_SPLIT_THREE_FORCED_MODE);
  203. }
  204. #ifdef NVENC_13_0_OR_LATER
  205. if (caps->engines > 3) {
  206. obs_property_list_add_int(p, obs_module_text("SplitEncode.FourWay"),
  207. NV_ENC_SPLIT_FOUR_FORCED_MODE);
  208. }
  209. #endif
  210. }
  211. #endif
  212. p = obs_properties_add_text(props, "opts", obs_module_text("Opts"), OBS_TEXT_DEFAULT);
  213. obs_property_set_long_description(p, obs_module_text("Opts.TT"));
  214. /* Invisible properties */
  215. p = obs_properties_add_bool(props, "repeat_headers", "repeat_headers");
  216. obs_property_set_visible(p, false);
  217. p = obs_properties_add_bool(props, "force_cuda_tex", "force_cuda_tex");
  218. obs_property_set_visible(p, false);
  219. p = obs_properties_add_bool(props, "disable_scenecut", "disable_scenecut");
  220. obs_property_set_visible(p, false);
  221. return props;
  222. }
  223. obs_properties_t *h264_nvenc_properties(void *unused)
  224. {
  225. UNUSED_PARAMETER(unused);
  226. return nvenc_properties_internal(CODEC_H264);
  227. }
  228. #ifdef ENABLE_HEVC
  229. obs_properties_t *hevc_nvenc_properties(void *unused)
  230. {
  231. UNUSED_PARAMETER(unused);
  232. return nvenc_properties_internal(CODEC_HEVC);
  233. }
  234. #endif
  235. obs_properties_t *av1_nvenc_properties(void *unused)
  236. {
  237. UNUSED_PARAMETER(unused);
  238. return nvenc_properties_internal(CODEC_AV1);
  239. }