Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*!
- * \brief
- * Demonstrates how to use NvFBC to grab frames to an OpenGL texture in
- * video memory and send them to the HW encoder using NvEncodeAPI's OpenGL
- * interface.
- *
- * \file
- * This sample demonstrates the following features:
- * - Capture to video memory (texture) using OpenGL interop;
- * - Manage a GL context externally, and pass it to NvFBC;
- * - Disable automatic modeset recovery;
- * - Register the texture for NvEncodeAPI's use;
- * - Encode the frame in the texture using the NvEncodeAPI's OpenGL interface
- *
- * \copyright
- * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <dlfcn.h>
- #include <string.h>
- #include <getopt.h>
- #include <unistd.h>
- #include <GL/gl.h>
- #include <GL/glx.h>
- #include <X11/Xlib.h>
- #include "NvFBC.h"
- #include "nvEncodeAPI.h"
- #include "NvFBCUtils.h"
- #define APP_VERSION 1
- #define LIB_NVFBC_NAME "libnvidia-fbc.so.1"
- #define LIB_ENCODEAPI_NAME "libnvidia-encode.so.1"
- #define N_FRAMES 1
- /*
- * Global variables
- */
- GLXContext glxCtx = None;
- GLXFBConfig glxFBConfig = None;
- NV_ENCODE_API_FUNCTION_LIST pEncFn;
- /*
- * NvEncodeAPI entry point
- */
- typedef NVENCSTATUS (NVENCAPI *PFNNVENCODEAPICREATEINSTANCEPROC)(NV_ENCODE_API_FUNCTION_LIST *);
- enum codecType {
- CODEC_H264,
- CODEC_HEVC
- };
- /**
- * Prints usage information.
- */
- static void usage(const char *pname)
- {
- printf("Usage: %s [options]\n", pname);
- printf("\n");
- printf("Options:\n");
- printf(" --help|-h This message\n");
- printf(" --frames|-f <n> Number of frames to capture (default: %u)\n",
- N_FRAMES);
- printf(" --size|-s <w>x<h> Size of the captured frames\n");
- printf(" (default: size of the framebuffer)\n");
- printf(" --codec|-c <str> Codec to use\n");
- printf(" Can be 'h264' or 'hevc'\n");
- printf(" (default: 'h264')\n");
- printf(" --output|-o <str> Name of the output file \n");
- printf(" (default: \"output\"\n");
- printf(" The codec used will be appended to this\n");
- printf(" name\n");
- }
- /**
- * Creates an OpenGL context.
- *
- * This context will then be passed to NvFBC for its internal use.
- *
- * \param [out] *glxCtx
- * The created OpenGL context.
- * \param [out] *glxFbConfig
- * The used framebuffer configuration.
- *
- * \return
- * NVFBC_TRUE in case of success, NVFBC_FALSE otherwise.
- */
- static NVFBC_BOOL gl_init(void)
- {
- Display *dpy = None;
- Pixmap pixmap = None;
- GLXPixmap glxPixmap = None;
- GLXFBConfig *fbConfigs;
- Bool res;
- int n;
- static int initialized = False;
- if (initialized) {
- return True;
- }
- int attribs[] = {
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
- GLX_BIND_TO_TEXTURE_RGBA_EXT, 1,
- GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
- None
- };
- dpy = XOpenDisplay(NULL);
- if (dpy == None) {
- fprintf(stderr, "Unable to open display\n");
- return NVFBC_FALSE;
- }
- fbConfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &n);
- if (!fbConfigs) {
- fprintf(stderr, "Unable to find FB configs\n");
- return NVFBC_FALSE;
- }
- glxCtx = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, None, True);
- if (glxCtx == None) {
- fprintf(stderr, "Unable to create GL context\n");
- return NVFBC_FALSE;
- }
- pixmap = XCreatePixmap(dpy, XDefaultRootWindow(dpy), 1, 1, DisplayPlanes(dpy, XDefaultScreen(dpy)));
- if (pixmap == None) {
- fprintf(stderr, "Unable to create pixmap\n");
- return NVFBC_FALSE;
- }
- glxPixmap = glXCreatePixmap(dpy, fbConfigs[0], pixmap, NULL);
- if (glxPixmap == None) {
- fprintf(stderr, "Unable to create GLX pixmap\n");
- return NVFBC_FALSE;
- }
- res = glXMakeCurrent(dpy, glxPixmap, glxCtx);
- if (!res) {
- fprintf(stderr, "Unable to make context current\n");
- return NVFBC_FALSE;
- }
- glxFBConfig = fbConfigs[0];
- XFree(fbConfigs);
- initialized = True;
- return NVFBC_TRUE;
- }
- /**
- * Initializes the NvFBC library and creates an NvFBC instance.
- *
- * Creates and sets up a capture session to video memory.
- *
- * Creates and sets up an encode session and initializes the encoder with
- * parameters for generating an H.264 stream.
- *
- * Captures frames, encodes them and writes them out to a file (output.h264)
- */
- int test(int argc, char *argv[])
- {
- static struct option longopts[] = {
- { "frames", required_argument, NULL, 'f' },
- { "size", required_argument, NULL, 's' },
- { "codec", required_argument, NULL, 'c' },
- { "output", required_argument, NULL, 'o' },
- { NULL, 0, NULL, 0 }
- };
- int opt, ret;
- unsigned int n = 0, nFrames = N_FRAMES;
- NVFBC_SIZE frameSize = { 0, 0 };
- void *libNVFBC = NULL, *libEnc = NULL;
- PNVFBCCREATEINSTANCE NvFBCCreateInstance_ptr = NULL;
- PFNNVENCODEAPICREATEINSTANCEPROC NvEncodeAPICreateInstance = NULL;
- NVFBC_API_FUNCTION_LIST pFn;
- NVFBCSTATUS fbcStatus;
- NVFBC_BOOL fbcBool;
- NVENCSTATUS encStatus;
- NVFBC_SESSION_HANDLE fbcHandle;
- NVFBC_CREATE_HANDLE_PARAMS createHandleParams;
- NVFBC_DESTROY_HANDLE_PARAMS destroyHandleParams;
- NvFBCUtilsPrintVersions(APP_VERSION);
- /*
- * Parse the command line.
- */
- while ((opt = getopt_long(argc, argv, "hf:s:c:o:", longopts, NULL)) != -1) {
- switch (opt) {
- case 'f':
- nFrames = (unsigned int) atoi(optarg);
- break;
- case 's':
- ret = sscanf(optarg, "%ux%u", &frameSize.w, &frameSize.h);
- if (ret != 2) {
- fprintf(stderr, "Invalid size format: '%s'\n", optarg);
- return EXIT_FAILURE;
- }
- break;
- case 'h':
- default:
- usage(argv[0]);
- return EXIT_SUCCESS;
- }
- }
- /*
- * Dynamically load the NvFBC library.
- */
- libNVFBC = dlopen(LIB_NVFBC_NAME, RTLD_NOW);
- if (libNVFBC == NULL) {
- fprintf(stderr, "Unable to open '%s'\n", LIB_NVFBC_NAME);
- return EXIT_FAILURE;
- }
- /*
- * Dynamically load the NvEncodeAPI library.
- */
- libEnc = dlopen(LIB_ENCODEAPI_NAME, RTLD_NOW);
- if (libNVFBC == NULL) {
- fprintf(stderr, "Unable to open '%s'\n", LIB_ENCODEAPI_NAME);
- return EXIT_FAILURE;
- }
- /*
- * Initialize OpenGL.
- */
- fbcBool = gl_init();
- if (fbcBool != NVFBC_TRUE) {
- return EXIT_FAILURE;
- }
- /*
- * Resolve the 'NvFBCCreateInstance' symbol that will allow us to get
- * the API function pointers.
- */
- NvFBCCreateInstance_ptr =
- (PNVFBCCREATEINSTANCE) dlsym(libNVFBC, "NvFBCCreateInstance");
- if (NvFBCCreateInstance_ptr == NULL) {
- fprintf(stderr, "Unable to resolve symbol 'NvFBCCreateInstance'\n");
- return EXIT_FAILURE;
- }
- /*
- * Create an NvFBC instance.
- *
- * API function pointers are accessible through pFn.
- */
- memset(&pFn, 0, sizeof(pFn));
- pFn.dwVersion = NVFBC_VERSION;
- fbcStatus = NvFBCCreateInstance_ptr(&pFn);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "Unable to create NvFBC instance (status: %d)\n",
- fbcStatus);
- return EXIT_FAILURE;
- }
- /*
- * Resolve the 'NvEncodeAPICreateInstance' symbol that will allow us to get
- * the API function pointers.
- */
- NvEncodeAPICreateInstance =
- (PFNNVENCODEAPICREATEINSTANCEPROC) dlsym(libEnc, "NvEncodeAPICreateInstance");
- if (NvEncodeAPICreateInstance == NULL) {
- fprintf(stderr, "Unable to resolve symbol 'NvEncodeAPICreateInstance'\n");
- return EXIT_FAILURE;
- }
- /*
- * Create an NvEncodeAPI instance.
- *
- * API function pointers are accessible through pEncFn.
- */
- memset(&pEncFn, 0, sizeof(pEncFn));
- pEncFn.version = NV_ENCODE_API_FUNCTION_LIST_VER;
- encStatus = NvEncodeAPICreateInstance(&pEncFn);
- if (encStatus != NV_ENC_SUCCESS) {
- fprintf(stderr, "Unable to create NvEncodeAPI instance (status: %d)\n",
- encStatus);
- return EXIT_FAILURE;
- }
- /*
- * Create a session handle that is used to identify the client.
- *
- * Request that the GL context is externally managed.
- */
- memset(&createHandleParams, 0, sizeof(createHandleParams));
- createHandleParams.dwVersion = NVFBC_CREATE_HANDLE_PARAMS_VER;
- createHandleParams.bExternallyManagedContext = NVFBC_TRUE;
- createHandleParams.glxCtx = glxCtx;
- createHandleParams.glxFBConfig = glxFBConfig;
- fbcStatus = pFn.nvFBCCreateHandle(&fbcHandle, &createHandleParams);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- return EXIT_FAILURE;
- }
- NVFBC_GET_STATUS_PARAMS statusParams;
- NVFBC_CREATE_CAPTURE_SESSION_PARAMS createCaptureParams;
- NVFBC_TOGL_SETUP_PARAMS setupParams;
- NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroyCaptureParams;
- /*
- * Retrieve the size of framebuffer.
- */
- memset(&statusParams, 0, sizeof(statusParams));
- statusParams.dwVersion = NVFBC_GET_STATUS_PARAMS_VER;
- fbcStatus = pFn.nvFBCGetStatus(fbcHandle, &statusParams);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- goto fbc_fail;
- }
- if (statusParams.bCanCreateNow == NVFBC_FALSE) {
- fprintf(stderr, "It is not possible to create a capture session "
- "on this system.\n");
- goto fbc_fail;
- }
- printf("Screen size is %dx%d.\n",
- statusParams.screenSize.w, statusParams.screenSize.h);
- if (frameSize.w > statusParams.screenSize.w ||
- frameSize.h > statusParams.screenSize.h) {
- fprintf(stderr, "Frames larger than %dx%d cannot be captured on this "
- "system.\n", statusParams.screenSize.w, statusParams.screenSize.h);
- goto fbc_fail;
- }
- if (frameSize.w == 0) {
- frameSize.w = statusParams.screenSize.w;
- }
- if (frameSize.h == 0) {
- frameSize.h = statusParams.screenSize.h;
- }
- printf("FRAME_SIZE %d %d\n", frameSize.w, frameSize.h);
- memset(&createCaptureParams, 0, sizeof(createCaptureParams));
- NVFBC_SIZE framey = {0, 0};
- createCaptureParams.dwVersion = NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER;
- createCaptureParams.eCaptureType = NVFBC_CAPTURE_TO_GL;
- createCaptureParams.bWithCursor = NVFBC_FALSE;
- createCaptureParams.frameSize = framey;
- createCaptureParams.bRoundFrameSize = NVFBC_TRUE;
- createCaptureParams.eTrackingType = NVFBC_TRACKING_DEFAULT;
- createCaptureParams.bDisableAutoModesetRecovery = NVFBC_FALSE;
- fbcStatus = pFn.nvFBCCreateCaptureSession(fbcHandle, &createCaptureParams);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- goto fbc_fail;
- }
- /*
- * Set up the capture session.
- */
- memset(&setupParams, 0, sizeof(setupParams));
- setupParams.dwVersion = NVFBC_TOGL_SETUP_PARAMS_VER;
- setupParams.eBufferFormat = NVFBC_BUFFER_FORMAT_NV12;
- fbcStatus = pFn.nvFBCToGLSetUp(fbcHandle, &setupParams);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- goto fbc_fail;
- }
- /*
- * Start capturing and encoding frames.
- */
- printf("Capturing %dx%d frames...\n", frameSize.w, frameSize.h);
- for (n = 0; n < nFrames; n++) {
- NVFBC_TOGL_GRAB_FRAME_PARAMS grabParams;
- memset(&grabParams, 0, sizeof(grabParams));
- grabParams.dwVersion = NVFBC_TOGL_GRAB_FRAME_PARAMS_VER;
- grabParams.dwFlags = NVFBC_TOGL_GRAB_FLAGS_NOWAIT;
- /*
- * Capture a frame.
- */
- fbcStatus = pFn.nvFBCToGLGrabFrame(fbcHandle, &grabParams);
- if (fbcStatus == NVFBC_ERR_MUST_RECREATE) {
- printf("Capture session must be recreated!\n");
- break;
- } else if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- break;
- }
- usleep(1000000/300);
- }
- printf("Captured %d frames.\n", n);
- printf("Destroying resources...\n");
- fbc_fail:
- /*
- * Destroy capture session.
- */
- memset(&destroyCaptureParams, 0, sizeof(destroyCaptureParams));
- destroyCaptureParams.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER;
- fbcStatus = pFn.nvFBCDestroyCaptureSession(fbcHandle, &destroyCaptureParams);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- }
- /*
- * Destroy session handle, tear down more resources.
- */
- memset(&destroyHandleParams, 0, sizeof(destroyHandleParams));
- destroyHandleParams.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER;
- fbcStatus = pFn.nvFBCDestroyHandle(fbcHandle, &destroyHandleParams);
- if (fbcStatus != NVFBC_SUCCESS) {
- fprintf(stderr, "%s\n", pFn.nvFBCGetLastErrorStr(fbcHandle));
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
- }
- int main(int argc, char *argv[]) {
- int count = 0;
- while (True) {
- printf("test %d\n", ++count);
- test(argc, argv);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement