Advertisement
Guest User

Untitled

a guest
Jun 23rd, 2019
696
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.77 KB | None | 0 0
  1. /*!
  2. * \brief
  3. * Demonstrates how to use NvFBC to synchronously grab and encode the
  4. * desktop or a fullscreen application with the hardware encoder.
  5. *
  6. * \file
  7. * This sample demonstrates the following features:
  8. * - Capture to H.264 or H.265/HEVC compressed frames in system memory;
  9. * - Select an output (monitor) to track;
  10. * - Frame scaling;
  11. * - Synchronous (blocking) capture.
  12. *
  13. * The sample demonstrates how to use NvFBC to grab and encode with the
  14. * hardware encoder. The program show how to initialize the NvFBCHwEnc
  15. * encoder class, set up the grab and encode, and grab the full-screen
  16. * framebuffer, compress it, and copy it to system memory.
  17. * Because of this, the NvFBCHwEnc class requires a Kepler GPU or better
  18. * to work. Attempting to create an instance of that class on earlier cards
  19. * will result in the create call failing.
  20. *
  21. *
  22. * \copyright
  23. * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
  24. *
  25. * Permission is hereby granted, free of charge, to any person obtaining a
  26. * copy of this software and associated documentation files (the "Software"),
  27. * to deal in the Software without restriction, including without limitation
  28. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  29. * and/or sell copies of the Software, and to permit persons to whom the
  30. * Software is furnished to do so, subject to the following conditions:
  31. *
  32. * The above copyright notice and this permission notice shall be included in
  33. * all copies or substantial portions of the Software.
  34. *
  35. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  36. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  37. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  38. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  39. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  40. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  41. * DEALINGS IN THE SOFTWARE.
  42. */
  43.  
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <stdint.h>
  47. #include <dlfcn.h>
  48. #include <string.h>
  49. #include <getopt.h>
  50.  
  51. #include <NvFBC.h>
  52.  
  53. #include "NvFBCUtils.h"
  54.  
  55. #define APP_VERSION 4
  56.  
  57. #define LIB_NVFBC_NAME "libnvidia-fbc.so.1"
  58.  
  59. #define N_FRAMES 1000
  60.  
  61. /**
  62. * Prints usage information.
  63. */
  64. static void usage(const char *pname)
  65. {
  66. printf("Usage: %s [options]\n", pname);
  67. printf("\n");
  68. printf("Options:\n");
  69. printf(" --help|-h This message\n");
  70. printf(" --get-status|-g Print status and exit\n");
  71. printf(" --track|-t <str> Region of the screen to track\n");
  72. printf(" Can be 'default', 'screen' or '<output name>'\n");
  73. printf(" as returned by --get-status\n");
  74. printf(" --frames|-f <n> Number of frames to capture (default: %u)\n",
  75. N_FRAMES);
  76. printf(" --size|-s <w>x<h> Size of the captured frames\n");
  77. printf(" (default: size of the framebuffer)\n");
  78. printf(" --codec|-c <str> Codec to use\n");
  79. printf(" Can be 'h264' or 'hevc'\n");
  80. printf(" (default: 'h264')\n");
  81. }
  82.  
  83.  
  84. /**
  85. * Initializes the NvFBC library and creates an NvFBC instance.
  86. *
  87. * Creates and sets up a capture session to HW compressed frames in system
  88. * memory.
  89. *
  90. * Captures a bunch of frames and saves them to the disk.
  91. */
  92. int main(int argc, char *argv[])
  93. {
  94. static struct option longopts[] = {
  95. { "get-status", no_argument, NULL, 'g' },
  96. { "track", required_argument, NULL, 't' },
  97. { "frames", required_argument, NULL, 'f' },
  98. { "size", required_argument, NULL, 's' },
  99. { "codec", required_argument, NULL, 'c' },
  100. { NULL, 0, NULL, 0 }
  101. };
  102.  
  103. char filename[64];
  104.  
  105. int opt, ret;
  106. unsigned int i, nFrames = N_FRAMES;
  107. NVFBC_SIZE frameSize = { 0, 0 };
  108. NVFBC_BOOL printStatusOnly = NVFBC_FALSE;
  109.  
  110. NVFBC_TRACKING_TYPE trackingType = NVFBC_TRACKING_DEFAULT;
  111. char outputName[NVFBC_OUTPUT_NAME_LEN];
  112. uint32_t outputId = 0;
  113.  
  114. FILE *fd;
  115.  
  116. void *libNVFBC = NULL;
  117. PNVFBCCREATEINSTANCE NvFBCCreateInstance_ptr = NULL;
  118. NVFBC_API_FUNCTION_LIST pFn;
  119.  
  120. NVFBCSTATUS fbcStatus;
  121.  
  122. NVFBC_SESSION_HANDLE fbcHandle;
  123. NVFBC_CREATE_HANDLE_PARAMS createHandleParams;
  124. NVFBC_GET_STATUS_PARAMS statusParams;
  125. NVFBC_CREATE_CAPTURE_SESSION_PARAMS createCaptureParams;
  126. NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroyCaptureParams;
  127. NVFBC_DESTROY_HANDLE_PARAMS destroyHandleParams;
  128.  
  129. NVFBC_HWENC_CONFIG encoderConfig;
  130. NVFBC_TOHWENC_SETUP_PARAMS setupParams;
  131.  
  132. NVFBC_HWENC_CODEC codec = NVFBC_HWENC_CODEC_H264;
  133.  
  134. /*
  135. * Parse the command line.
  136. */
  137. while ((opt = getopt_long(argc, argv, "hgt:f:s:c:", longopts, NULL)) != -1) {
  138. switch (opt) {
  139. case 'g':
  140. printStatusOnly = NVFBC_TRUE;
  141. break;
  142. case 't':
  143. NvFBCUtilsParseTrackingType(optarg, &trackingType, outputName);
  144. break;
  145. case 'f':
  146. nFrames = (unsigned int) atoi(optarg);
  147. break;
  148. case 's':
  149. ret = sscanf(optarg, "%ux%u", &frameSize.w, &frameSize.h);
  150. if (ret != 2) {
  151. fprintf(stderr, "Invalid size format: '%s'\n", optarg);
  152. return EXIT_FAILURE;
  153. }
  154. break;
  155. case 'c':
  156. if (!strcasecmp(optarg, "h264")) {
  157. codec = NVFBC_HWENC_CODEC_H264;
  158. } else if (!strcasecmp(optarg, "hevc")) {
  159. codec = NVFBC_HWENC_CODEC_HEVC;
  160. } else {
  161. fprintf(stderr, "Invalid codec: '%s'\n", optarg);
  162. return EXIT_FAILURE;
  163. }
  164. break;
  165. case 'h':
  166. default:
  167. usage(argv[0]);
  168. return EXIT_SUCCESS;
  169. }
  170. }
  171.  
  172. NvFBCUtilsPrintVersions(APP_VERSION);
  173.  
  174. if (codec == NVFBC_HWENC_CODEC_H264) {
  175. sprintf(filename, "NvFBCSample.h264");
  176. } else {
  177. sprintf(filename, "NvFBCSample.hevc");
  178. }
  179.  
  180. /*
  181. * Dynamically load the NvFBC library.
  182. */
  183. libNVFBC = dlopen(LIB_NVFBC_NAME, RTLD_NOW);
  184. if (libNVFBC == NULL) {
  185. fprintf(stderr, "Unable to open '%s' (%s)\n", LIB_NVFBC_NAME, dlerror());
  186. return EXIT_FAILURE;
  187. }
  188.  
  189. /*
  190. * Resolve the 'NvFBCCreateInstance' symbol that will allow us to get
  191. * the API function pointers.
  192. */
  193. NvFBCCreateInstance_ptr =
  194. (PNVFBCCREATEINSTANCE) dlsym(libNVFBC, "NvFBCCreateInstance");
  195. if (NvFBCCreateInstance_ptr == NULL) {
  196. fprintf(stderr, "Unable to resolve symbol 'NvFBCCreateInstance'\n");
  197. return EXIT_FAILURE;
  198. }
  199.  
  200. /*
  201. * Create an NvFBC instance.
  202. *
  203. * API function pointers are accessible through pFn.
  204. */
  205. memset(&pFn, 0, sizeof(pFn));
  206.  
  207. pFn.dwVersion = NVFBC_VERSION;
  208.  
  209. fbcStatus = NvFBCCreateInstance_ptr(&pFn);
  210. if (fbcStatus != NVFBC_SUCCESS) {
  211. fprintf(stderr, "Unable to create NvFBC instance (status: %d)\n",
  212. fbcStatus);
  213. return EXIT_FAILURE;
  214. }
  215.  
  216. /*
  217. * Create a session handle that is used to identify the client.
  218. */
  219. memset(&createHandleParams, 0, sizeof(createHandleParams));
  220.  
  221. createHandleParams.dwVersion = NVFBC_CREATE_HANDLE_PARAMS_VER;
  222.  
  223. fbcStatus = pFn.nvFBCCreateHandle(&fbcHandle, &createHandleParams);
  224. if (fbcStatus != NVFBC_SUCCESS) {
  225. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  226. return EXIT_FAILURE;
  227. }
  228.  
  229. /*
  230. * Get information about the state of the display driver.
  231. *
  232. * This call is optional but helps the application decide what it should
  233. * do.
  234. */
  235. memset(&statusParams, 0, sizeof(statusParams));
  236.  
  237. statusParams.dwVersion = NVFBC_GET_STATUS_PARAMS_VER;
  238.  
  239. fbcStatus = pFn.nvFBCGetStatus(fbcHandle, &statusParams);
  240. if (fbcStatus != NVFBC_SUCCESS) {
  241. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  242. return EXIT_FAILURE;
  243. }
  244.  
  245. if (printStatusOnly) {
  246. NvFBCUtilsPrintStatus(&statusParams);
  247. return EXIT_SUCCESS;
  248. }
  249.  
  250. if (statusParams.bCanCreateNow == NVFBC_FALSE) {
  251. fprintf(stderr, "It is not possible to create a capture session "
  252. "on this system.\n");
  253. return EXIT_FAILURE;
  254. }
  255.  
  256. if (trackingType == NVFBC_TRACKING_OUTPUT) {
  257. if (!statusParams.bXRandRAvailable) {
  258. fprintf(stderr, "The XRandR extension is not available.\n");
  259. fprintf(stderr, "It is therefore not possible to track an RandR output.\n");
  260. return EXIT_FAILURE;
  261. }
  262.  
  263. outputId = NvFBCUtilsGetOutputId(statusParams.outputs,
  264. statusParams.dwOutputNum,
  265. outputName);
  266. if (outputId == 0) {
  267. fprintf(stderr, "RandR output '%s' not found.\n", outputName);
  268. return EXIT_FAILURE;
  269. }
  270. }
  271.  
  272. /*
  273. * Create a capture session.
  274. */
  275. printf("Creating a capture session of %u HW compressed frames.\n",
  276. nFrames);
  277.  
  278. memset(&createCaptureParams, 0, sizeof(createCaptureParams));
  279.  
  280. createCaptureParams.dwVersion = NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER;
  281. createCaptureParams.eCaptureType = NVFBC_CAPTURE_TO_HW_ENCODER;
  282. createCaptureParams.bWithCursor = NVFBC_TRUE;
  283. createCaptureParams.frameSize = frameSize;
  284. createCaptureParams.bRoundFrameSize = NVFBC_TRUE;
  285. createCaptureParams.eTrackingType = trackingType;
  286.  
  287. if (trackingType == NVFBC_TRACKING_OUTPUT) {
  288. createCaptureParams.dwOutputId = outputId;
  289. }
  290.  
  291. fbcStatus = pFn.nvFBCCreateCaptureSession(fbcHandle, &createCaptureParams);
  292. if (fbcStatus != NVFBC_SUCCESS) {
  293. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  294. return EXIT_FAILURE;
  295. }
  296.  
  297. /*
  298. * Configure the HW encoder.
  299. *
  300. * Select encoding quality, bitrate, etc.
  301. *
  302. * Here, we are configuring a 60 fps capture at a balanced encode / decode
  303. * time, using a high quality profile.
  304. */
  305. memset(&encoderConfig, 0, sizeof(encoderConfig));
  306.  
  307. encoderConfig.dwVersion = NVFBC_HWENC_CONFIG_VER;
  308. if (codec == NVFBC_HWENC_CODEC_H264) {
  309. encoderConfig.dwProfile = 77;
  310. } else {
  311. encoderConfig.dwProfile = 1;
  312. }
  313. encoderConfig.dwFrameRateNum = 60;
  314. encoderConfig.dwFrameRateDen = 1;
  315. encoderConfig.dwAvgBitRate = 8000000;
  316. encoderConfig.dwPeakBitRate = encoderConfig.dwAvgBitRate * 1.5;
  317. encoderConfig.dwGOPLength = 100;
  318. encoderConfig.eRateControl = NVFBC_HWENC_PARAMS_RC_VBR;
  319. encoderConfig.ePresetConfig = NVFBC_HWENC_PRESET_LOW_LATENCY_HP;
  320. encoderConfig.dwQP = 26;
  321. encoderConfig.eInputBufferFormat = NVFBC_BUFFER_FORMAT_NV12;
  322. encoderConfig.dwVBVBufferSize = encoderConfig.dwAvgBitRate;
  323. encoderConfig.dwVBVInitialDelay = encoderConfig.dwVBVBufferSize;
  324. encoderConfig.codec = codec;
  325.  
  326. /*
  327. * Frame headers are included with the frame. Set this to TRUE for
  328. * outband header fetching. Headers can then be fetched using the
  329. * NvFBCToHwEncGetHeader() API call.
  330. */
  331. encoderConfig.bOutBandSPSPPS = NVFBC_FALSE;
  332.  
  333. /*
  334. * Set up the capture session.
  335. */
  336. memset(&setupParams, 0, sizeof(setupParams));
  337.  
  338. setupParams.dwVersion = NVFBC_TOHWENC_SETUP_PARAMS_VER;
  339. setupParams.pEncodeConfig = &encoderConfig;
  340.  
  341. fbcStatus = pFn.nvFBCToHwEncSetUp(fbcHandle, &setupParams);
  342. if (fbcStatus != NVFBC_SUCCESS) {
  343. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  344. return EXIT_FAILURE;
  345. }
  346.  
  347. /*
  348. * We are now ready to start grabbing frames.
  349. */
  350. printf("Frame capture session started. New frames will be captured when "
  351. "the display is refreshed or when the mouse cursor moves.\n");
  352.  
  353. fd = fopen(filename, "wb");
  354. if (fd == NULL) {
  355. fprintf(stderr,"Unable to create '%s'\n", filename);
  356. return EXIT_FAILURE;
  357. }
  358.  
  359. for (i = 0; i < nFrames; i++) {
  360. static unsigned char *frame = NULL;
  361.  
  362. size_t nBytes;
  363. uint64_t t1, t2;
  364.  
  365. NVFBC_TOHWENC_GRAB_FRAME_PARAMS grabParams;
  366.  
  367. NVFBC_FRAME_GRAB_INFO frameInfo;
  368. NVFBC_HWENC_FRAME_INFO encFrameInfo;
  369.  
  370. t1 = NvFBCUtilsGetTimeInMillis();
  371.  
  372. memset(&grabParams, 0, sizeof(grabParams));
  373. memset(&frameInfo, 0, sizeof(frameInfo));
  374. memset(&encFrameInfo, 0, sizeof(encFrameInfo));
  375.  
  376. grabParams.dwVersion = NVFBC_TOHWENC_GRAB_FRAME_PARAMS_VER;
  377.  
  378. /*
  379. * Use blocking calls.
  380. *
  381. * The application will wait for new frames. New frames are generated
  382. * when the mouse cursor moves or when the screen if refreshed.
  383. */
  384. grabParams.dwFlags = NVFBC_TOHWENC_GRAB_FLAGS_NOFLAGS;
  385.  
  386. /*
  387. * This structure will contain information about the captured frame.
  388. */
  389. grabParams.pFrameGrabInfo = &frameInfo;
  390.  
  391. /*
  392. * This structure will contain information about the encoding of
  393. * the captured frame.
  394. */
  395. grabParams.pEncFrameInfo = &encFrameInfo;
  396.  
  397. /*
  398. * Specify per-frame encoding configuration. Here, keep the defaults.
  399. */
  400. grabParams.pEncodeParams = NULL;
  401.  
  402. /*
  403. * This pointer is allocated by the NvFBC library and will
  404. * contain the captured frame.
  405. *
  406. * Make sure this pointer stays the same during the capture session
  407. * to prevent memory leaks.
  408. */
  409. grabParams.ppBitStreamBuffer = (void **) &frame;
  410.  
  411. /*
  412. * Capture a new frame.
  413. */
  414. fbcStatus = pFn.nvFBCToHwEncGrabFrame(fbcHandle, &grabParams);
  415. if (fbcStatus != NVFBC_SUCCESS) {
  416. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  417. return EXIT_FAILURE;
  418. }
  419.  
  420. /*
  421. * Save frame to the output file.
  422. *
  423. * Information such as dimension and size in bytes is available from
  424. * the frameInfo structure.
  425. */
  426. nBytes = fwrite(frame, 1, frameInfo.dwByteSize, fd);
  427. if (nBytes == 0) {
  428. fprintf(stderr, "Unable to write to '%s'\n", filename);
  429. return EXIT_FAILURE;
  430. }
  431.  
  432. t2 = NvFBCUtilsGetTimeInMillis();
  433.  
  434. printf("New frame id %u grabbed and saved in %llu ms\n",
  435. frameInfo.dwCurrentFrame, (unsigned long long) (t2 - t1));
  436. }
  437.  
  438. /*
  439. * Destroy capture session, tear down resources.
  440. */
  441. memset(&destroyCaptureParams, 0, sizeof(destroyCaptureParams));
  442.  
  443. destroyCaptureParams.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER;
  444.  
  445. fbcStatus = pFn.nvFBCDestroyCaptureSession(fbcHandle, &destroyCaptureParams);
  446. if (fbcStatus != NVFBC_SUCCESS) {
  447. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  448. return EXIT_FAILURE;
  449. }
  450.  
  451. /*
  452. * Destroy session handle, tear down more resources.
  453. */
  454. memset(&destroyHandleParams, 0, sizeof(destroyHandleParams));
  455.  
  456. destroyHandleParams.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER;
  457.  
  458. fbcStatus = pFn.nvFBCDestroyHandle(fbcHandle, &destroyHandleParams);
  459. if (fbcStatus != NVFBC_SUCCESS) {
  460. fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
  461. return EXIT_FAILURE;
  462. }
  463.  
  464. fclose(fd);
  465. printf("File '%s' saved. It can played back with e.g., mplayer.\n",
  466. filename);
  467.  
  468. return EXIT_SUCCESS;
  469. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement