jim-nvenc.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. #include "jim-nvenc.h"
  2. #include <util/circlebuf.h>
  3. #include <util/darray.h>
  4. #include <util/dstr.h>
  5. #include <obs-avc.h>
  6. #include <libavutil/rational.h>
  7. #define INITGUID
  8. #include <dxgi.h>
  9. #include <d3d11.h>
  10. #include <d3d11_1.h>
  11. #include <obs-hevc.h>
  12. /* ========================================================================= */
  13. #define EXTRA_BUFFERS 5
  14. #define do_log(level, format, ...) \
  15. blog(level, "[jim-nvenc: '%s'] " format, \
  16. obs_encoder_get_name(enc->encoder), ##__VA_ARGS__)
  17. #define error(format, ...) do_log(LOG_ERROR, format, ##__VA_ARGS__)
  18. #define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
  19. #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
  20. #define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
  21. #define error_hr(msg) error("%s: %s: 0x%08lX", __FUNCTION__, msg, (uint32_t)hr);
  22. struct nv_bitstream;
  23. struct nv_texture;
  24. struct handle_tex {
  25. uint32_t handle;
  26. ID3D11Texture2D *tex;
  27. IDXGIKeyedMutex *km;
  28. };
  29. /* ------------------------------------------------------------------------- */
  30. /* Main Implementation Structure */
  31. enum codec_type {
  32. CODEC_H264,
  33. CODEC_HEVC,
  34. };
  35. static const char *get_codec_name(enum codec_type type)
  36. {
  37. switch (type) {
  38. case CODEC_H264:
  39. return "H264";
  40. case CODEC_HEVC:
  41. return "HEVC";
  42. }
  43. return "Unknown";
  44. }
  45. struct nvenc_data {
  46. obs_encoder_t *encoder;
  47. enum codec_type codec;
  48. GUID codec_guid;
  49. void *session;
  50. NV_ENC_INITIALIZE_PARAMS params;
  51. NV_ENC_CONFIG config;
  52. int rc_lookahead;
  53. int buf_count;
  54. int output_delay;
  55. int buffers_queued;
  56. size_t next_bitstream;
  57. size_t cur_bitstream;
  58. bool encode_started;
  59. bool first_packet;
  60. bool can_change_bitrate;
  61. int32_t bframes;
  62. DARRAY(struct nv_bitstream) bitstreams;
  63. DARRAY(struct nv_texture) textures;
  64. DARRAY(struct handle_tex) input_textures;
  65. struct circlebuf dts_list;
  66. DARRAY(uint8_t) packet_data;
  67. int64_t packet_pts;
  68. bool packet_keyframe;
  69. ID3D11Device *device;
  70. ID3D11DeviceContext *context;
  71. uint32_t cx;
  72. uint32_t cy;
  73. uint8_t *header;
  74. size_t header_size;
  75. uint8_t *sei;
  76. size_t sei_size;
  77. };
  78. /* ------------------------------------------------------------------------- */
  79. /* Bitstream Buffer */
  80. struct nv_bitstream {
  81. void *ptr;
  82. };
  83. #define NV_FAIL(format, ...) nv_fail(enc->encoder, format, __VA_ARGS__)
  84. #define NV_FAILED(x) nv_failed(enc->encoder, x, __FUNCTION__, #x)
  85. static bool nv_bitstream_init(struct nvenc_data *enc, struct nv_bitstream *bs)
  86. {
  87. NV_ENC_CREATE_BITSTREAM_BUFFER buf = {
  88. NV_ENC_CREATE_BITSTREAM_BUFFER_VER};
  89. if (NV_FAILED(nv.nvEncCreateBitstreamBuffer(enc->session, &buf))) {
  90. return false;
  91. }
  92. bs->ptr = buf.bitstreamBuffer;
  93. return true;
  94. }
  95. static void nv_bitstream_free(struct nvenc_data *enc, struct nv_bitstream *bs)
  96. {
  97. if (bs->ptr) {
  98. nv.nvEncDestroyBitstreamBuffer(enc->session, bs->ptr);
  99. }
  100. }
  101. /* ------------------------------------------------------------------------- */
  102. /* Texture Resource */
  103. struct nv_texture {
  104. void *res;
  105. ID3D11Texture2D *tex;
  106. void *mapped_res;
  107. };
  108. static bool nv_texture_init(struct nvenc_data *enc, struct nv_texture *nvtex)
  109. {
  110. const bool p010 = obs_p010_tex_active();
  111. D3D11_TEXTURE2D_DESC desc = {0};
  112. desc.Width = enc->cx;
  113. desc.Height = enc->cy;
  114. desc.MipLevels = 1;
  115. desc.ArraySize = 1;
  116. desc.Format = p010 ? DXGI_FORMAT_P010 : DXGI_FORMAT_NV12;
  117. desc.SampleDesc.Count = 1;
  118. desc.BindFlags = D3D11_BIND_RENDER_TARGET;
  119. ID3D11Device *const device = enc->device;
  120. ID3D11Texture2D *tex;
  121. HRESULT hr = device->lpVtbl->CreateTexture2D(device, &desc, NULL, &tex);
  122. if (FAILED(hr)) {
  123. error_hr("Failed to create texture");
  124. return false;
  125. }
  126. tex->lpVtbl->SetEvictionPriority(tex, DXGI_RESOURCE_PRIORITY_MAXIMUM);
  127. NV_ENC_REGISTER_RESOURCE res = {NV_ENC_REGISTER_RESOURCE_VER};
  128. res.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX;
  129. res.resourceToRegister = tex;
  130. res.width = enc->cx;
  131. res.height = enc->cy;
  132. res.bufferFormat = p010 ? NV_ENC_BUFFER_FORMAT_YUV420_10BIT
  133. : NV_ENC_BUFFER_FORMAT_NV12;
  134. if (NV_FAILED(nv.nvEncRegisterResource(enc->session, &res))) {
  135. tex->lpVtbl->Release(tex);
  136. return false;
  137. }
  138. nvtex->res = res.registeredResource;
  139. nvtex->tex = tex;
  140. nvtex->mapped_res = NULL;
  141. return true;
  142. }
  143. static void nv_texture_free(struct nvenc_data *enc, struct nv_texture *nvtex)
  144. {
  145. if (nvtex->res) {
  146. if (nvtex->mapped_res) {
  147. nv.nvEncUnmapInputResource(enc->session,
  148. nvtex->mapped_res);
  149. }
  150. nv.nvEncUnregisterResource(enc->session, nvtex->res);
  151. nvtex->tex->lpVtbl->Release(nvtex->tex);
  152. }
  153. }
  154. /* ------------------------------------------------------------------------- */
  155. /* Implementation */
  156. static const char *h264_nvenc_get_name(void *type_data)
  157. {
  158. UNUSED_PARAMETER(type_data);
  159. return "NVIDIA NVENC H.264";
  160. }
  161. #ifdef ENABLE_HEVC
  162. static const char *hevc_nvenc_get_name(void *type_data)
  163. {
  164. UNUSED_PARAMETER(type_data);
  165. return "NVIDIA NVENC HEVC";
  166. }
  167. #endif
  168. static inline int nv_get_cap(struct nvenc_data *enc, NV_ENC_CAPS cap)
  169. {
  170. if (!enc->session)
  171. return 0;
  172. NV_ENC_CAPS_PARAM param = {NV_ENC_CAPS_PARAM_VER};
  173. int v;
  174. param.capsToQuery = cap;
  175. nv.nvEncGetEncodeCaps(enc->session, enc->codec_guid, &param, &v);
  176. return v;
  177. }
  178. static bool nvenc_update(void *data, obs_data_t *settings)
  179. {
  180. struct nvenc_data *enc = data;
  181. /* Only support reconfiguration of CBR bitrate */
  182. if (enc->can_change_bitrate) {
  183. int bitrate = (int)obs_data_get_int(settings, "bitrate");
  184. enc->config.rcParams.averageBitRate = bitrate * 1000;
  185. enc->config.rcParams.maxBitRate = bitrate * 1000;
  186. NV_ENC_RECONFIGURE_PARAMS params = {0};
  187. params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
  188. params.reInitEncodeParams = enc->params;
  189. params.resetEncoder = 1;
  190. params.forceIDR = 1;
  191. if (NV_FAILED(nv.nvEncReconfigureEncoder(enc->session,
  192. &params))) {
  193. return false;
  194. }
  195. }
  196. return true;
  197. }
  198. static HANDLE get_lib(struct nvenc_data *enc, const char *lib)
  199. {
  200. HMODULE mod = GetModuleHandleA(lib);
  201. if (mod)
  202. return mod;
  203. mod = LoadLibraryA(lib);
  204. if (!mod)
  205. error("Failed to load %s", lib);
  206. return mod;
  207. }
  208. typedef HRESULT(WINAPI *CREATEDXGIFACTORY1PROC)(REFIID, void **);
  209. static bool init_d3d11(struct nvenc_data *enc, obs_data_t *settings)
  210. {
  211. HMODULE dxgi = get_lib(enc, "DXGI.dll");
  212. HMODULE d3d11 = get_lib(enc, "D3D11.dll");
  213. CREATEDXGIFACTORY1PROC create_dxgi;
  214. PFN_D3D11_CREATE_DEVICE create_device;
  215. IDXGIFactory1 *factory;
  216. IDXGIAdapter *adapter;
  217. ID3D11Device *device;
  218. ID3D11DeviceContext *context;
  219. HRESULT hr;
  220. if (!dxgi || !d3d11) {
  221. return false;
  222. }
  223. create_dxgi = (CREATEDXGIFACTORY1PROC)GetProcAddress(
  224. dxgi, "CreateDXGIFactory1");
  225. create_device = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(
  226. d3d11, "D3D11CreateDevice");
  227. if (!create_dxgi || !create_device) {
  228. error("Failed to load D3D11/DXGI procedures");
  229. return false;
  230. }
  231. hr = create_dxgi(&IID_IDXGIFactory1, &factory);
  232. if (FAILED(hr)) {
  233. error_hr("CreateDXGIFactory1 failed");
  234. return false;
  235. }
  236. hr = factory->lpVtbl->EnumAdapters(factory, 0, &adapter);
  237. factory->lpVtbl->Release(factory);
  238. if (FAILED(hr)) {
  239. error_hr("EnumAdapters failed");
  240. return false;
  241. }
  242. hr = create_device(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, NULL, 0,
  243. D3D11_SDK_VERSION, &device, NULL, &context);
  244. adapter->lpVtbl->Release(adapter);
  245. if (FAILED(hr)) {
  246. error_hr("D3D11CreateDevice failed");
  247. return false;
  248. }
  249. enc->device = device;
  250. enc->context = context;
  251. return true;
  252. }
  253. static bool init_session(struct nvenc_data *enc)
  254. {
  255. NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = {
  256. NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER};
  257. params.device = enc->device;
  258. params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX;
  259. params.apiVersion = NVENCAPI_VERSION;
  260. if (NV_FAILED(nv.nvEncOpenEncodeSessionEx(&params, &enc->session))) {
  261. return false;
  262. }
  263. return true;
  264. }
  265. static void initialize_params(NV_ENC_INITIALIZE_PARAMS *params,
  266. const GUID *nv_encode, const GUID *nv_preset,
  267. NV_ENC_TUNING_INFO nv_tuning, uint32_t width,
  268. uint32_t height, uint32_t fps_num,
  269. uint32_t fps_den, NV_ENC_CONFIG *config)
  270. {
  271. int darWidth, darHeight;
  272. av_reduce(&darWidth, &darHeight, width, height, 1024 * 1024);
  273. memset(params, 0, sizeof(*params));
  274. params->version = NV_ENC_INITIALIZE_PARAMS_VER;
  275. params->encodeGUID = *nv_encode;
  276. params->presetGUID = *nv_preset;
  277. params->encodeWidth = width;
  278. params->encodeHeight = height;
  279. params->darWidth = darWidth;
  280. params->darHeight = darHeight;
  281. params->frameRateNum = fps_num;
  282. params->frameRateDen = fps_den;
  283. params->enableEncodeAsync = 0;
  284. params->enablePTD = 1;
  285. params->encodeConfig = config;
  286. params->tuningInfo = nv_tuning;
  287. }
  288. static inline GUID get_nv_preset2(const char *preset2)
  289. {
  290. if (astrcmpi(preset2, "p1") == 0) {
  291. return NV_ENC_PRESET_P1_GUID;
  292. } else if (astrcmpi(preset2, "p2") == 0) {
  293. return NV_ENC_PRESET_P2_GUID;
  294. } else if (astrcmpi(preset2, "p3") == 0) {
  295. return NV_ENC_PRESET_P3_GUID;
  296. } else if (astrcmpi(preset2, "p4") == 0) {
  297. return NV_ENC_PRESET_P4_GUID;
  298. } else if (astrcmpi(preset2, "p6") == 0) {
  299. return NV_ENC_PRESET_P6_GUID;
  300. } else if (astrcmpi(preset2, "p7") == 0) {
  301. return NV_ENC_PRESET_P7_GUID;
  302. } else {
  303. return NV_ENC_PRESET_P5_GUID;
  304. }
  305. }
  306. static inline NV_ENC_TUNING_INFO get_nv_tuning(const char *tuning)
  307. {
  308. if (astrcmpi(tuning, "ll") == 0) {
  309. return NV_ENC_TUNING_INFO_LOW_LATENCY;
  310. } else if (astrcmpi(tuning, "ull") == 0) {
  311. return NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY;
  312. } else {
  313. return NV_ENC_TUNING_INFO_HIGH_QUALITY;
  314. }
  315. }
  316. static inline NV_ENC_MULTI_PASS get_nv_multipass(const char *multipass)
  317. {
  318. if (astrcmpi(multipass, "qres") == 0) {
  319. return NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
  320. } else if (astrcmpi(multipass, "fullres") == 0) {
  321. return NV_ENC_TWO_PASS_FULL_RESOLUTION;
  322. } else {
  323. return NV_ENC_MULTI_PASS_DISABLED;
  324. }
  325. }
  326. static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
  327. int bf, bool psycho_aq, bool *lossless)
  328. {
  329. const char *rc = obs_data_get_string(settings, "rate_control");
  330. int bitrate = (int)obs_data_get_int(settings, "bitrate");
  331. int max_bitrate = (int)obs_data_get_int(settings, "max_bitrate");
  332. int cqp = (int)obs_data_get_int(settings, "cqp");
  333. int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
  334. const char *preset = obs_data_get_string(settings, "preset");
  335. const char *preset2 = obs_data_get_string(settings, "preset2");
  336. const char *tuning = obs_data_get_string(settings, "tune");
  337. const char *multipass = obs_data_get_string(settings, "multipass");
  338. const char *profile = obs_data_get_string(settings, "profile");
  339. bool lookahead = obs_data_get_bool(settings, "lookahead");
  340. bool vbr = astrcmpi(rc, "VBR") == 0;
  341. NVENCSTATUS err;
  342. video_t *video = obs_encoder_video(enc->encoder);
  343. const struct video_output_info *voi = video_output_get_info(video);
  344. enc->cx = voi->width;
  345. enc->cy = voi->height;
  346. /* -------------------------- */
  347. /* get preset */
  348. GUID nv_preset = get_nv_preset2(preset2);
  349. NV_ENC_TUNING_INFO nv_tuning = get_nv_tuning(tuning);
  350. NV_ENC_MULTI_PASS nv_multipass = get_nv_multipass(multipass);
  351. if (obs_data_has_user_value(settings, "preset") &&
  352. !obs_data_has_user_value(settings, "preset2")) {
  353. if (astrcmpi(preset, "hq") == 0) {
  354. nv_preset = NV_ENC_PRESET_P5_GUID;
  355. nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
  356. nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
  357. } else if (astrcmpi(preset, "mq") == 0) {
  358. nv_preset = NV_ENC_PRESET_P4_GUID;
  359. nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
  360. nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
  361. } else if (astrcmpi(preset, "hp") == 0) {
  362. nv_preset = NV_ENC_PRESET_P1_GUID;
  363. nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
  364. nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
  365. } else if (astrcmpi(preset, "ll") == 0) {
  366. nv_preset = NV_ENC_PRESET_P3_GUID;
  367. nv_tuning = NV_ENC_TUNING_INFO_LOW_LATENCY;
  368. nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
  369. } else if (astrcmpi(preset, "llhq") == 0) {
  370. nv_preset = NV_ENC_PRESET_P4_GUID;
  371. nv_tuning = NV_ENC_TUNING_INFO_LOW_LATENCY;
  372. nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
  373. } else if (astrcmpi(preset, "llhp") == 0) {
  374. nv_preset = NV_ENC_PRESET_P2_GUID;
  375. nv_tuning = NV_ENC_TUNING_INFO_LOW_LATENCY;
  376. nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
  377. }
  378. }
  379. const bool rc_lossless = astrcmpi(rc, "lossless") == 0;
  380. *lossless = rc_lossless;
  381. if (rc_lossless) {
  382. *lossless =
  383. nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
  384. if (*lossless) {
  385. nv_tuning = NV_ENC_TUNING_INFO_LOSSLESS;
  386. nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
  387. } else {
  388. warn("lossless encode is not supported, ignoring");
  389. nv_preset = NV_ENC_PRESET_P5_GUID;
  390. nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
  391. nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
  392. }
  393. }
  394. /* -------------------------- */
  395. /* get preset default config */
  396. NV_ENC_PRESET_CONFIG preset_config = {NV_ENC_PRESET_CONFIG_VER,
  397. {NV_ENC_CONFIG_VER}};
  398. err = nv.nvEncGetEncodePresetConfigEx(enc->session, enc->codec_guid,
  399. nv_preset, nv_tuning,
  400. &preset_config);
  401. if (nv_failed(enc->encoder, err, __FUNCTION__,
  402. "nvEncGetEncodePresetConfig")) {
  403. return false;
  404. }
  405. /* -------------------------- */
  406. /* main configuration */
  407. enc->config = preset_config.presetCfg;
  408. uint32_t gop_size =
  409. (keyint_sec) ? keyint_sec * voi->fps_num / voi->fps_den : 250;
  410. NV_ENC_CONFIG *config = &enc->config;
  411. initialize_params(&enc->params, &enc->codec_guid, &nv_preset, nv_tuning,
  412. voi->width, voi->height, voi->fps_num, voi->fps_den,
  413. &enc->config);
  414. config->gopLength = gop_size;
  415. config->frameIntervalP = 1 + bf;
  416. enc->bframes = bf;
  417. /* lookahead */
  418. const bool use_profile_lookahead = config->rcParams.enableLookahead;
  419. lookahead = nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_LOOKAHEAD) &&
  420. (lookahead || use_profile_lookahead);
  421. if (lookahead) {
  422. enc->rc_lookahead = use_profile_lookahead
  423. ? config->rcParams.lookaheadDepth
  424. : 8;
  425. }
  426. int buf_count = max(4, config->frameIntervalP * 2 * 2);
  427. if (lookahead) {
  428. buf_count = max(buf_count, config->frameIntervalP +
  429. enc->rc_lookahead +
  430. EXTRA_BUFFERS);
  431. }
  432. buf_count = min(64, buf_count);
  433. enc->buf_count = buf_count;
  434. const int output_delay = buf_count - 1;
  435. enc->output_delay = output_delay;
  436. if (lookahead) {
  437. const int lkd_bound = output_delay - config->frameIntervalP - 4;
  438. if (lkd_bound >= 0) {
  439. config->rcParams.enableLookahead = 1;
  440. config->rcParams.lookaheadDepth =
  441. max(enc->rc_lookahead, lkd_bound);
  442. config->rcParams.disableIadapt = 0;
  443. config->rcParams.disableBadapt = 0;
  444. } else {
  445. lookahead = false;
  446. }
  447. }
  448. /* psycho aq */
  449. if (nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ)) {
  450. config->rcParams.enableAQ = psycho_aq;
  451. config->rcParams.aqStrength = 8;
  452. config->rcParams.enableTemporalAQ = psycho_aq;
  453. } else if (psycho_aq) {
  454. warn("Ignoring Psycho Visual Tuning request since GPU is not capable");
  455. }
  456. /* -------------------------- */
  457. /* rate control */
  458. enc->can_change_bitrate =
  459. nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE) &&
  460. !lookahead;
  461. config->rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
  462. if (astrcmpi(rc, "cqp") == 0 || rc_lossless) {
  463. if (*lossless)
  464. cqp = 0;
  465. config->rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
  466. config->rcParams.constQP.qpInterP = cqp;
  467. config->rcParams.constQP.qpInterB = cqp;
  468. config->rcParams.constQP.qpIntra = cqp;
  469. enc->can_change_bitrate = false;
  470. bitrate = 0;
  471. max_bitrate = 0;
  472. } else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
  473. config->rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;
  474. }
  475. config->rcParams.averageBitRate = bitrate * 1000;
  476. config->rcParams.maxBitRate = vbr ? max_bitrate * 1000 : bitrate * 1000;
  477. config->rcParams.vbvBufferSize = bitrate * 1000;
  478. config->rcParams.multiPass = nv_multipass;
  479. /* -------------------------- */
  480. /* initialize */
  481. info("settings:\n"
  482. "\tcodec: %s\n"
  483. "\trate_control: %s\n"
  484. "\tbitrate: %d\n"
  485. "\tcqp: %d\n"
  486. "\tkeyint: %d\n"
  487. "\tpreset: %s\n"
  488. "\ttuning: %s\n"
  489. "\tmultipass: %s\n"
  490. "\tprofile: %s\n"
  491. "\twidth: %d\n"
  492. "\theight: %d\n"
  493. "\tb-frames: %d\n"
  494. "\tlookahead: %s\n"
  495. "\tpsycho_aq: %s\n",
  496. get_codec_name(enc->codec), rc, bitrate, cqp, gop_size, preset2,
  497. tuning, multipass, profile, enc->cx, enc->cy, bf,
  498. lookahead ? "true" : "false", psycho_aq ? "true" : "false");
  499. return true;
  500. }
  501. static bool init_encoder_h264(struct nvenc_data *enc, obs_data_t *settings,
  502. int bf, bool psycho_aq)
  503. {
  504. const char *rc = obs_data_get_string(settings, "rate_control");
  505. int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
  506. const char *profile = obs_data_get_string(settings, "profile");
  507. bool lossless;
  508. if (!init_encoder_base(enc, settings, bf, psycho_aq, &lossless)) {
  509. return false;
  510. }
  511. NV_ENC_CONFIG *config = &enc->config;
  512. NV_ENC_CONFIG_H264 *h264_config = &config->encodeCodecConfig.h264Config;
  513. NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui_params =
  514. &h264_config->h264VUIParameters;
  515. video_t *video = obs_encoder_video(enc->encoder);
  516. const struct video_output_info *voi = video_output_get_info(video);
  517. uint32_t gop_size =
  518. (keyint_sec) ? keyint_sec * voi->fps_num / voi->fps_den : 250;
  519. h264_config->idrPeriod = gop_size;
  520. bool repeat_headers = obs_data_get_bool(settings, "repeat_headers");
  521. if (repeat_headers) {
  522. h264_config->repeatSPSPPS = 1;
  523. h264_config->disableSPSPPS = 0;
  524. h264_config->outputAUD = 1;
  525. }
  526. h264_config->sliceMode = 3;
  527. h264_config->sliceModeData = 1;
  528. h264_config->useBFramesAsRef = NV_ENC_BFRAME_REF_MODE_DISABLED;
  529. vui_params->videoSignalTypePresentFlag = 1;
  530. vui_params->videoFullRangeFlag = (voi->range == VIDEO_RANGE_FULL);
  531. vui_params->colourDescriptionPresentFlag = 1;
  532. switch (voi->colorspace) {
  533. case VIDEO_CS_601:
  534. vui_params->colourPrimaries = 6;
  535. vui_params->transferCharacteristics = 6;
  536. vui_params->colourMatrix = 6;
  537. break;
  538. case VIDEO_CS_DEFAULT:
  539. case VIDEO_CS_709:
  540. vui_params->colourPrimaries = 1;
  541. vui_params->transferCharacteristics = 1;
  542. vui_params->colourMatrix = 1;
  543. break;
  544. case VIDEO_CS_SRGB:
  545. vui_params->colourPrimaries = 1;
  546. vui_params->transferCharacteristics = 13;
  547. vui_params->colourMatrix = 1;
  548. break;
  549. }
  550. if (astrcmpi(rc, "lossless") == 0) {
  551. h264_config->qpPrimeYZeroTransformBypassFlag = 1;
  552. } else if (astrcmpi(rc, "vbr") != 0) { /* CBR */
  553. h264_config->outputBufferingPeriodSEI = 1;
  554. }
  555. h264_config->outputPictureTimingSEI = 1;
  556. /* -------------------------- */
  557. /* profile */
  558. if (astrcmpi(profile, "main") == 0) {
  559. config->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
  560. } else if (astrcmpi(profile, "baseline") == 0) {
  561. config->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
  562. } else if (!lossless) {
  563. config->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
  564. }
  565. if (NV_FAILED(nv.nvEncInitializeEncoder(enc->session, &enc->params))) {
  566. return false;
  567. }
  568. return true;
  569. }
  570. static bool init_encoder_hevc(struct nvenc_data *enc, obs_data_t *settings,
  571. int bf, bool psycho_aq)
  572. {
  573. const char *rc = obs_data_get_string(settings, "rate_control");
  574. int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
  575. const char *profile = obs_data_get_string(settings, "profile");
  576. bool lossless;
  577. if (!init_encoder_base(enc, settings, bf, psycho_aq, &lossless)) {
  578. return false;
  579. }
  580. NV_ENC_CONFIG *config = &enc->config;
  581. NV_ENC_CONFIG_HEVC *hevc_config = &config->encodeCodecConfig.hevcConfig;
  582. NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui_params =
  583. &hevc_config->hevcVUIParameters;
  584. video_t *video = obs_encoder_video(enc->encoder);
  585. const struct video_output_info *voi = video_output_get_info(video);
  586. uint32_t gop_size =
  587. (keyint_sec) ? keyint_sec * voi->fps_num / voi->fps_den : 250;
  588. hevc_config->idrPeriod = gop_size;
  589. bool repeat_headers = obs_data_get_bool(settings, "repeat_headers");
  590. if (repeat_headers) {
  591. hevc_config->repeatSPSPPS = 1;
  592. hevc_config->disableSPSPPS = 0;
  593. hevc_config->outputAUD = 1;
  594. }
  595. hevc_config->sliceMode = 3;
  596. hevc_config->sliceModeData = 1;
  597. hevc_config->useBFramesAsRef = NV_ENC_BFRAME_REF_MODE_DISABLED;
  598. vui_params->videoSignalTypePresentFlag = 1;
  599. vui_params->videoFullRangeFlag = (voi->range == VIDEO_RANGE_FULL);
  600. vui_params->colourDescriptionPresentFlag = 1;
  601. switch (voi->colorspace) {
  602. case VIDEO_CS_601:
  603. vui_params->colourPrimaries = 6;
  604. vui_params->transferCharacteristics = 6;
  605. vui_params->colourMatrix = 6;
  606. break;
  607. case VIDEO_CS_DEFAULT:
  608. case VIDEO_CS_709:
  609. vui_params->colourPrimaries = 1;
  610. vui_params->transferCharacteristics = 1;
  611. vui_params->colourMatrix = 1;
  612. break;
  613. case VIDEO_CS_SRGB:
  614. vui_params->colourPrimaries = 1;
  615. vui_params->transferCharacteristics = 13;
  616. vui_params->colourMatrix = 1;
  617. break;
  618. case VIDEO_CS_2100_PQ:
  619. vui_params->colourPrimaries = 9;
  620. vui_params->transferCharacteristics = 16;
  621. vui_params->colourMatrix = 9;
  622. vui_params->chromaSampleLocationFlag = 1;
  623. vui_params->chromaSampleLocationTop = 2;
  624. vui_params->chromaSampleLocationBot = 2;
  625. break;
  626. case VIDEO_CS_2100_HLG:
  627. vui_params->colourPrimaries = 9;
  628. vui_params->transferCharacteristics = 18;
  629. vui_params->colourMatrix = 9;
  630. vui_params->chromaSampleLocationFlag = 1;
  631. vui_params->chromaSampleLocationTop = 2;
  632. vui_params->chromaSampleLocationBot = 2;
  633. }
  634. hevc_config->pixelBitDepthMinus8 = obs_p010_tex_active() ? 2 : 0;
  635. if (astrcmpi(rc, "cbr") == 0) {
  636. hevc_config->outputBufferingPeriodSEI = 1;
  637. }
  638. hevc_config->outputPictureTimingSEI = 1;
  639. /* -------------------------- */
  640. /* profile */
  641. if (astrcmpi(profile, "main10") == 0) {
  642. config->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
  643. } else if (obs_p010_tex_active()) {
  644. blog(LOG_WARNING, "[jim-nvenc] Forcing main10 for P010");
  645. config->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
  646. } else {
  647. config->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
  648. }
  649. if (NV_FAILED(nv.nvEncInitializeEncoder(enc->session, &enc->params))) {
  650. return false;
  651. }
  652. return true;
  653. }
  654. static bool init_bitstreams(struct nvenc_data *enc)
  655. {
  656. da_reserve(enc->bitstreams, enc->buf_count);
  657. for (int i = 0; i < enc->buf_count; i++) {
  658. struct nv_bitstream bitstream;
  659. if (!nv_bitstream_init(enc, &bitstream)) {
  660. return false;
  661. }
  662. da_push_back(enc->bitstreams, &bitstream);
  663. }
  664. return true;
  665. }
  666. static bool init_textures(struct nvenc_data *enc)
  667. {
  668. da_reserve(enc->textures, enc->buf_count);
  669. for (int i = 0; i < enc->buf_count; i++) {
  670. struct nv_texture texture;
  671. if (!nv_texture_init(enc, &texture)) {
  672. return false;
  673. }
  674. da_push_back(enc->textures, &texture);
  675. }
  676. return true;
  677. }
  678. static void nvenc_destroy(void *data);
  679. static bool init_specific_encoder(struct nvenc_data *enc, obs_data_t *settings,
  680. int bf, bool psycho_aq)
  681. {
  682. switch (enc->codec) {
  683. case CODEC_HEVC:
  684. return init_encoder_hevc(enc, settings, bf, psycho_aq);
  685. case CODEC_H264:
  686. return init_encoder_h264(enc, settings, bf, psycho_aq);
  687. }
  688. return false;
  689. }
  690. static bool init_encoder(struct nvenc_data *enc, enum codec_type codec,
  691. obs_data_t *settings, obs_encoder_t *encoder)
  692. {
  693. const int bf = (int)obs_data_get_int(settings, "bf");
  694. const bool psycho_aq = obs_data_get_bool(settings, "psycho_aq");
  695. const bool support_10bit =
  696. nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE);
  697. const int bf_max = nv_get_cap(enc, NV_ENC_CAPS_NUM_MAX_BFRAMES);
  698. if (obs_p010_tex_active() && !support_10bit) {
  699. NV_FAIL(obs_module_text("NVENC.10bitUnsupported"));
  700. return false;
  701. }
  702. video_t *video = obs_encoder_video(enc->encoder);
  703. const struct video_output_info *voi = video_output_get_info(video);
  704. switch (voi->format) {
  705. case VIDEO_FORMAT_I010:
  706. case VIDEO_FORMAT_P010:
  707. break;
  708. default:
  709. switch (voi->colorspace) {
  710. case VIDEO_CS_2100_PQ:
  711. case VIDEO_CS_2100_HLG:
  712. NV_FAIL(obs_module_text("NVENC.8bitUnsupportedHdr"));
  713. return false;
  714. }
  715. }
  716. if (bf > bf_max) {
  717. NV_FAIL(obs_module_text("NVENC.TooManyBFrames"), bf, bf_max);
  718. return false;
  719. }
  720. if (!init_specific_encoder(enc, settings, bf, psycho_aq)) {
  721. if (!psycho_aq)
  722. return false;
  723. blog(LOG_WARNING, "[jim-nvenc] init_specific_encoder failed, "
  724. "trying again without Psycho Visual Tuning");
  725. nv.nvEncDestroyEncoder(enc->session);
  726. enc->session = NULL;
  727. if (!init_session(enc)) {
  728. return false;
  729. }
  730. if (!init_specific_encoder(enc, settings, bf, false)) {
  731. return false;
  732. }
  733. }
  734. return true;
  735. }
  736. static void *nvenc_create_internal(enum codec_type codec, obs_data_t *settings,
  737. obs_encoder_t *encoder)
  738. {
  739. NV_ENCODE_API_FUNCTION_LIST init = {NV_ENCODE_API_FUNCTION_LIST_VER};
  740. struct nvenc_data *enc = bzalloc(sizeof(*enc));
  741. enc->encoder = encoder;
  742. enc->codec = codec;
  743. enc->first_packet = true;
  744. switch (enc->codec) {
  745. case CODEC_H264:
  746. enc->codec_guid = NV_ENC_CODEC_H264_GUID;
  747. break;
  748. case CODEC_HEVC:
  749. enc->codec_guid = NV_ENC_CODEC_HEVC_GUID;
  750. break;
  751. }
  752. if (!init_nvenc(encoder)) {
  753. goto fail;
  754. }
  755. if (NV_FAILED(nv_create_instance(&init))) {
  756. goto fail;
  757. }
  758. if (!init_d3d11(enc, settings)) {
  759. goto fail;
  760. }
  761. if (!init_session(enc)) {
  762. goto fail;
  763. }
  764. if (!init_encoder(enc, codec, settings, encoder)) {
  765. goto fail;
  766. }
  767. if (!init_bitstreams(enc)) {
  768. goto fail;
  769. }
  770. if (!init_textures(enc)) {
  771. goto fail;
  772. }
  773. #ifdef ENABLE_HEVC
  774. enc->codec = codec;
  775. #endif
  776. return enc;
  777. fail:
  778. nvenc_destroy(enc);
  779. return NULL;
  780. }
  781. static void *nvenc_create_base(enum codec_type codec, obs_data_t *settings,
  782. obs_encoder_t *encoder)
  783. {
  784. /* this encoder requires shared textures, this cannot be used on a
  785. * gpu other than the one OBS is currently running on. */
  786. const int gpu = (int)obs_data_get_int(settings, "gpu");
  787. if (gpu != 0) {
  788. blog(LOG_INFO,
  789. "[jim-nvenc] different GPU selected by user, falling back to ffmpeg");
  790. goto reroute;
  791. }
  792. if (obs_encoder_scaling_enabled(encoder)) {
  793. blog(LOG_INFO,
  794. "[jim-nvenc] scaling enabled, falling back to ffmpeg");
  795. goto reroute;
  796. }
  797. if (!obs_p010_tex_active() && !obs_nv12_tex_active()) {
  798. blog(LOG_INFO,
  799. "[jim-nvenc] nv12/p010 not active, falling back to ffmpeg");
  800. goto reroute;
  801. }
  802. struct nvenc_data *enc =
  803. nvenc_create_internal(codec, settings, encoder);
  804. if (enc) {
  805. return enc;
  806. }
  807. reroute:
  808. switch (codec) {
  809. case CODEC_H264:
  810. return obs_encoder_create_rerouted(encoder, "ffmpeg_nvenc");
  811. case CODEC_HEVC:
  812. return obs_encoder_create_rerouted(encoder,
  813. "ffmpeg_hevc_nvenc");
  814. }
  815. return NULL;
  816. }
  817. static void *h264_nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
  818. {
  819. return nvenc_create_base(CODEC_H264, settings, encoder);
  820. }
  821. #ifdef ENABLE_HEVC
  822. static void *hevc_nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
  823. {
  824. return nvenc_create_base(CODEC_HEVC, settings, encoder);
  825. }
  826. #endif
  827. static bool get_encoded_packet(struct nvenc_data *enc, bool finalize);
  828. static void nvenc_destroy(void *data)
  829. {
  830. struct nvenc_data *enc = data;
  831. if (enc->encode_started) {
  832. size_t next_bitstream = enc->next_bitstream;
  833. NV_ENC_PIC_PARAMS params = {NV_ENC_PIC_PARAMS_VER};
  834. params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
  835. nv.nvEncEncodePicture(enc->session, &params);
  836. get_encoded_packet(enc, true);
  837. }
  838. for (size_t i = 0; i < enc->textures.num; i++) {
  839. nv_texture_free(enc, &enc->textures.array[i]);
  840. }
  841. for (size_t i = 0; i < enc->bitstreams.num; i++) {
  842. nv_bitstream_free(enc, &enc->bitstreams.array[i]);
  843. }
  844. if (enc->session) {
  845. nv.nvEncDestroyEncoder(enc->session);
  846. }
  847. for (size_t i = 0; i < enc->input_textures.num; i++) {
  848. ID3D11Texture2D *tex = enc->input_textures.array[i].tex;
  849. IDXGIKeyedMutex *km = enc->input_textures.array[i].km;
  850. tex->lpVtbl->Release(tex);
  851. km->lpVtbl->Release(km);
  852. }
  853. if (enc->context) {
  854. enc->context->lpVtbl->Release(enc->context);
  855. }
  856. if (enc->device) {
  857. enc->device->lpVtbl->Release(enc->device);
  858. }
  859. bfree(enc->header);
  860. bfree(enc->sei);
  861. circlebuf_free(&enc->dts_list);
  862. da_free(enc->textures);
  863. da_free(enc->bitstreams);
  864. da_free(enc->input_textures);
  865. da_free(enc->packet_data);
  866. bfree(enc);
  867. }
  868. static ID3D11Texture2D *get_tex_from_handle(struct nvenc_data *enc,
  869. uint32_t handle,
  870. IDXGIKeyedMutex **km_out)
  871. {
  872. ID3D11Device *device = enc->device;
  873. IDXGIKeyedMutex *km;
  874. ID3D11Texture2D *input_tex;
  875. HRESULT hr;
  876. for (size_t i = 0; i < enc->input_textures.num; i++) {
  877. struct handle_tex *ht = &enc->input_textures.array[i];
  878. if (ht->handle == handle) {
  879. *km_out = ht->km;
  880. return ht->tex;
  881. }
  882. }
  883. hr = device->lpVtbl->OpenSharedResource(device,
  884. (HANDLE)(uintptr_t)handle,
  885. &IID_ID3D11Texture2D,
  886. &input_tex);
  887. if (FAILED(hr)) {
  888. error_hr("OpenSharedResource failed");
  889. return NULL;
  890. }
  891. hr = input_tex->lpVtbl->QueryInterface(input_tex, &IID_IDXGIKeyedMutex,
  892. &km);
  893. if (FAILED(hr)) {
  894. error_hr("QueryInterface(IDXGIKeyedMutex) failed");
  895. input_tex->lpVtbl->Release(input_tex);
  896. return NULL;
  897. }
  898. input_tex->lpVtbl->SetEvictionPriority(input_tex,
  899. DXGI_RESOURCE_PRIORITY_MAXIMUM);
  900. *km_out = km;
  901. struct handle_tex new_ht = {handle, input_tex, km};
  902. da_push_back(enc->input_textures, &new_ht);
  903. return input_tex;
  904. }
  905. static bool get_encoded_packet(struct nvenc_data *enc, bool finalize)
  906. {
  907. void *s = enc->session;
  908. da_resize(enc->packet_data, 0);
  909. if (!enc->buffers_queued)
  910. return true;
  911. if (!finalize && enc->buffers_queued < enc->output_delay)
  912. return true;
  913. size_t count = finalize ? enc->buffers_queued : 1;
  914. for (size_t i = 0; i < count; i++) {
  915. size_t cur_bs_idx = enc->cur_bitstream;
  916. struct nv_bitstream *bs = &enc->bitstreams.array[cur_bs_idx];
  917. struct nv_texture *nvtex = &enc->textures.array[cur_bs_idx];
  918. /* ---------------- */
  919. NV_ENC_LOCK_BITSTREAM lock = {NV_ENC_LOCK_BITSTREAM_VER};
  920. lock.outputBitstream = bs->ptr;
  921. lock.doNotWait = false;
  922. if (NV_FAILED(nv.nvEncLockBitstream(s, &lock))) {
  923. return false;
  924. }
  925. if (enc->first_packet) {
  926. NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = {0};
  927. uint8_t buf[256];
  928. uint32_t size = 0;
  929. payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
  930. payload.spsppsBuffer = buf;
  931. payload.inBufferSize = sizeof(buf);
  932. payload.outSPSPPSPayloadSize = &size;
  933. nv.nvEncGetSequenceParams(s, &payload);
  934. enc->header = bmemdup(buf, size);
  935. enc->header_size = size;
  936. enc->first_packet = false;
  937. }
  938. da_copy_array(enc->packet_data, lock.bitstreamBufferPtr,
  939. lock.bitstreamSizeInBytes);
  940. enc->packet_pts = (int64_t)lock.outputTimeStamp;
  941. enc->packet_keyframe = lock.pictureType == NV_ENC_PIC_TYPE_IDR;
  942. if (NV_FAILED(nv.nvEncUnlockBitstream(s, bs->ptr))) {
  943. return false;
  944. }
  945. /* ---------------- */
  946. if (nvtex->mapped_res) {
  947. NVENCSTATUS err;
  948. err = nv.nvEncUnmapInputResource(s, nvtex->mapped_res);
  949. if (nv_failed(enc->encoder, err, __FUNCTION__,
  950. "unmap")) {
  951. return false;
  952. }
  953. nvtex->mapped_res = NULL;
  954. }
  955. /* ---------------- */
  956. if (++enc->cur_bitstream == enc->buf_count)
  957. enc->cur_bitstream = 0;
  958. enc->buffers_queued--;
  959. }
  960. return true;
  961. }
  962. static bool nvenc_encode_tex(void *data, uint32_t handle, int64_t pts,
  963. uint64_t lock_key, uint64_t *next_key,
  964. struct encoder_packet *packet,
  965. bool *received_packet)
  966. {
  967. struct nvenc_data *enc = data;
  968. ID3D11Device *device = enc->device;
  969. ID3D11DeviceContext *context = enc->context;
  970. ID3D11Texture2D *input_tex;
  971. ID3D11Texture2D *output_tex;
  972. IDXGIKeyedMutex *km;
  973. struct nv_texture *nvtex;
  974. struct nv_bitstream *bs;
  975. NVENCSTATUS err;
  976. if (handle == GS_INVALID_HANDLE) {
  977. error("Encode failed: bad texture handle");
  978. *next_key = lock_key;
  979. return false;
  980. }
  981. bs = &enc->bitstreams.array[enc->next_bitstream];
  982. nvtex = &enc->textures.array[enc->next_bitstream];
  983. input_tex = get_tex_from_handle(enc, handle, &km);
  984. output_tex = nvtex->tex;
  985. if (!input_tex) {
  986. *next_key = lock_key;
  987. return false;
  988. }
  989. circlebuf_push_back(&enc->dts_list, &pts, sizeof(pts));
  990. /* ------------------------------------ */
  991. /* copy to output tex */
  992. km->lpVtbl->AcquireSync(km, lock_key, INFINITE);
  993. context->lpVtbl->CopyResource(context, (ID3D11Resource *)output_tex,
  994. (ID3D11Resource *)input_tex);
  995. km->lpVtbl->ReleaseSync(km, *next_key);
  996. /* ------------------------------------ */
  997. /* map output tex so nvenc can use it */
  998. NV_ENC_MAP_INPUT_RESOURCE map = {NV_ENC_MAP_INPUT_RESOURCE_VER};
  999. map.registeredResource = nvtex->res;
  1000. if (NV_FAILED(nv.nvEncMapInputResource(enc->session, &map))) {
  1001. return false;
  1002. }
  1003. nvtex->mapped_res = map.mappedResource;
  1004. /* ------------------------------------ */
  1005. /* do actual encode call */
  1006. NV_ENC_PIC_PARAMS params = {0};
  1007. params.version = NV_ENC_PIC_PARAMS_VER;
  1008. params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
  1009. params.inputBuffer = nvtex->mapped_res;
  1010. params.bufferFmt = obs_p010_tex_active()
  1011. ? NV_ENC_BUFFER_FORMAT_YUV420_10BIT
  1012. : NV_ENC_BUFFER_FORMAT_NV12;
  1013. params.inputTimeStamp = (uint64_t)pts;
  1014. params.inputWidth = enc->cx;
  1015. params.inputHeight = enc->cy;
  1016. params.inputPitch = enc->cx;
  1017. params.outputBitstream = bs->ptr;
  1018. err = nv.nvEncEncodePicture(enc->session, &params);
  1019. if (err != NV_ENC_SUCCESS && err != NV_ENC_ERR_NEED_MORE_INPUT) {
  1020. nv_failed(enc->encoder, err, __FUNCTION__,
  1021. "nvEncEncodePicture");
  1022. return false;
  1023. }
  1024. enc->encode_started = true;
  1025. enc->buffers_queued++;
  1026. if (++enc->next_bitstream == enc->buf_count) {
  1027. enc->next_bitstream = 0;
  1028. }
  1029. /* ------------------------------------ */
  1030. /* check for encoded packet and parse */
  1031. if (!get_encoded_packet(enc, false)) {
  1032. return false;
  1033. }
  1034. /* ------------------------------------ */
  1035. /* output encoded packet */
  1036. if (enc->packet_data.num) {
  1037. int64_t dts;
  1038. circlebuf_pop_front(&enc->dts_list, &dts, sizeof(dts));
  1039. /* subtract bframe delay from dts */
  1040. dts -= (int64_t)enc->bframes * packet->timebase_num;
  1041. *received_packet = true;
  1042. packet->data = enc->packet_data.array;
  1043. packet->size = enc->packet_data.num;
  1044. packet->type = OBS_ENCODER_VIDEO;
  1045. packet->pts = enc->packet_pts;
  1046. packet->dts = dts;
  1047. packet->keyframe = enc->packet_keyframe;
  1048. } else {
  1049. *received_packet = false;
  1050. }
  1051. return true;
  1052. }
  1053. extern void h264_nvenc_defaults(obs_data_t *settings);
  1054. extern obs_properties_t *h264_nvenc_properties(void *unused);
  1055. #ifdef ENABLE_HEVC
  1056. extern void hevc_nvenc_defaults(obs_data_t *settings);
  1057. extern obs_properties_t *hevc_nvenc_properties(void *unused);
  1058. #endif
  1059. static bool nvenc_extra_data(void *data, uint8_t **header, size_t *size)
  1060. {
  1061. struct nvenc_data *enc = data;
  1062. if (!enc->header) {
  1063. return false;
  1064. }
  1065. *header = enc->header;
  1066. *size = enc->header_size;
  1067. return true;
  1068. }
  1069. static bool nvenc_sei_data(void *data, uint8_t **sei, size_t *size)
  1070. {
  1071. struct nvenc_data *enc = data;
  1072. if (!enc->sei) {
  1073. return false;
  1074. }
  1075. *sei = enc->sei;
  1076. *size = enc->sei_size;
  1077. return true;
  1078. }
  1079. struct obs_encoder_info h264_nvenc_info = {
  1080. .id = "jim_nvenc",
  1081. .codec = "h264",
  1082. .type = OBS_ENCODER_VIDEO,
  1083. .caps = OBS_ENCODER_CAP_PASS_TEXTURE | OBS_ENCODER_CAP_DYN_BITRATE,
  1084. .get_name = h264_nvenc_get_name,
  1085. .create = h264_nvenc_create,
  1086. .destroy = nvenc_destroy,
  1087. .update = nvenc_update,
  1088. .encode_texture = nvenc_encode_tex,
  1089. .get_defaults = h264_nvenc_defaults,
  1090. .get_properties = h264_nvenc_properties,
  1091. .get_extra_data = nvenc_extra_data,
  1092. .get_sei_data = nvenc_sei_data,
  1093. };
  1094. #ifdef ENABLE_HEVC
  1095. struct obs_encoder_info hevc_nvenc_info = {
  1096. .id = "jim_hevc_nvenc",
  1097. .codec = "hevc",
  1098. .type = OBS_ENCODER_VIDEO,
  1099. .caps = OBS_ENCODER_CAP_PASS_TEXTURE | OBS_ENCODER_CAP_DYN_BITRATE,
  1100. .get_name = hevc_nvenc_get_name,
  1101. .create = hevc_nvenc_create,
  1102. .destroy = nvenc_destroy,
  1103. .update = nvenc_update,
  1104. .encode_texture = nvenc_encode_tex,
  1105. .get_defaults = hevc_nvenc_defaults,
  1106. .get_properties = hevc_nvenc_properties,
  1107. .get_extra_data = nvenc_extra_data,
  1108. .get_sei_data = nvenc_sei_data,
  1109. };
  1110. #endif